From ecac4986dec0bca0eb6129f08da1b7f9c93214f9 Mon Sep 17 00:00:00 2001 From: Boming Zhang Date: Sat, 2 Nov 2024 03:04:43 -0400 Subject: [PATCH 1/3] feat(parser): unify parsers conf --- internal/parser/cppcheck/parser.go | 6 ++-- internal/parser/cppcheck/score.go | 48 +++++------------------------- internal/parser/cpplint/parser.go | 36 ++++++++++++++-------- 3 files changed, 34 insertions(+), 56 deletions(-) diff --git a/internal/parser/cppcheck/parser.go b/internal/parser/cppcheck/parser.go index 0630d38..514eb56 100644 --- a/internal/parser/cppcheck/parser.go +++ b/internal/parser/cppcheck/parser.go @@ -9,10 +9,8 @@ import ( "github.com/joint-online-judge/JOJ3/internal/stage" ) -type CppCheck struct{} - type Match struct { - Severity []string + Keywords []string Score int } @@ -32,6 +30,8 @@ type Record struct { Id string `json:"id"` } +type CppCheck struct{} + func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { // stdout := executorResult.Files[conf.Stdout] stderr := executorResult.Files[conf.Stderr] diff --git a/internal/parser/cppcheck/score.go b/internal/parser/cppcheck/score.go index 9b30b1c..babdfe9 100644 --- a/internal/parser/cppcheck/score.go +++ b/internal/parser/cppcheck/score.go @@ -2,7 +2,7 @@ package cppcheck import ( "fmt" - "log/slog" + "strings" ) type Severity int @@ -18,52 +18,18 @@ const ( UNKNOWN ) -func severityFromString(severityString string) (Severity, error) { - switch severityString { - case "error": - return ERROR, nil - case "warning": - return WARNING, nil - case "portability": - return PORTABILITY, nil - case "performance": - return PERFORMANCE, nil - case "style": - return STYLE, nil - case "information": - return INFORMATION, nil - case "debug": - return DEBUG, nil - default: - return UNKNOWN, fmt.Errorf("unknown severity type \"%s\" for cppcheck", severityString) - } -} - func GetResult(records []Record, conf Conf) (string, int, error) { result := "### Test results summary\n\n" var severityCounts [UNKNOWN + 1]int - var severityScore [UNKNOWN + 1]int score := conf.Score - - for _, match := range conf.Matches { - severities := match.Severity - score := match.Score - for _, severityString := range severities { - severity, err := severityFromString(severityString) - if err != nil { - return "", 0, err - } - severityScore[int(severity)] = score - } - } - for _, record := range records { - severity, err := severityFromString(record.Severity) - if err != nil { - slog.Error("parse severity", "error", err) + for _, match := range conf.Matches { + for _, keyword := range match.Keywords { + if strings.Contains(record.Id, keyword) { + score -= match.Score + } + } } - severityCounts[int(severity)] += 1 - score -= severityScore[int(severity)] } result += fmt.Sprintf("1. error: %d\n", severityCounts[0]) result += fmt.Sprintf("2. warning: %d\n", severityCounts[1]) diff --git a/internal/parser/cpplint/parser.go b/internal/parser/cpplint/parser.go index 7c448f5..bc7abdb 100644 --- a/internal/parser/cpplint/parser.go +++ b/internal/parser/cpplint/parser.go @@ -2,27 +2,33 @@ package cpplint import ( "fmt" - "log/slog" "regexp" - "strconv" "strings" "github.com/joint-online-judge/JOJ3/internal/stage" "github.com/joint-online-judge/JOJ3/pkg/utils" ) +type Match struct { + Keywords []string + Score int +} + type Conf struct { - Score int + Score int + Matches []Match + Stdout string `default:"stdout"` + Stderr string `default:"stderr"` } type Cpplint struct{} func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { - stderr := executorResult.Files["stderr"] + stderr := executorResult.Files[conf.Stderr] pattern := `(.+):(\d+): (.+) \[(.+)\] \[(\d)]\n` re := regexp.MustCompile(pattern) matches := re.FindAllStringSubmatch(stderr, -1) - score := 0 + score := conf.Score comment := "### Test results summary\n\n" categoryCount := map[string]int{} for _, match := range matches { @@ -37,15 +43,21 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { // } // message := match[3] category := match[4] - confidence, err := strconv.Atoi(match[5]) - if err != nil { - slog.Error("parse confidence", "error", err) - return stage.ParserResult{ - Score: 0, - Comment: fmt.Sprintf("Unexpected parser error: %s.", err), + // confidence, err := strconv.Atoi(match[5]) + // if err != nil { + // slog.Error("parse confidence", "error", err) + // return stage.ParserResult{ + // Score: 0, + // Comment: fmt.Sprintf("Unexpected parser error: %s.", err), + // } + // } + for _, match := range conf.Matches { + for _, keyword := range match.Keywords { + if strings.Contains(category, keyword) { + score -= match.Score + } } } - score -= confidence parts := strings.Split(category, "/") if len(parts) > 0 { category := parts[0] -- 2.30.2 From 24204b47af54f8556fc2c7673b56595d71e0d62c Mon Sep 17 00:00:00 2001 From: Boming Zhang Date: Sat, 2 Nov 2024 03:36:32 -0400 Subject: [PATCH 2/3] feat(parser): support force quit on deduct --- internal/parser/clangtidy/parser.go | 20 +++++++++++++------- internal/parser/cppcheck/parser.go | 18 ++++++++++++------ internal/parser/cpplint/parser.go | 18 ++++++++++++------ 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/internal/parser/clangtidy/parser.go b/internal/parser/clangtidy/parser.go index 388715c..455e3d3 100644 --- a/internal/parser/clangtidy/parser.go +++ b/internal/parser/clangtidy/parser.go @@ -14,11 +14,12 @@ type Match struct { } type Conf struct { - Score int - RootDir string `default:"/w"` - Matches []Match - Stdout string `default:"stdout"` - Stderr string `default:"stderr"` + Score int + RootDir string `default:"/w"` + Matches []Match + Stdout string `default:"stdout"` + Stderr string `default:"stderr"` + ForceQuitOnDeduct bool `default:"false"` } type ClangTidy struct{} @@ -56,8 +57,13 @@ func (*ClangTidy) Run(results []stage.ExecutorResult, confAny any) ( return nil, true, err } var res []stage.ParserResult + forceQuit := false for _, result := range results { - res = append(res, Parse(result, *conf)) + parseRes := Parse(result, *conf) + if conf.ForceQuitOnDeduct && parseRes.Score < conf.Score { + forceQuit = true + } + res = append(res, parseRes) } - return res, false, nil + return res, forceQuit, nil } diff --git a/internal/parser/cppcheck/parser.go b/internal/parser/cppcheck/parser.go index 514eb56..9b65194 100644 --- a/internal/parser/cppcheck/parser.go +++ b/internal/parser/cppcheck/parser.go @@ -15,10 +15,11 @@ type Match struct { } type Conf struct { - Score int - Matches []Match - Stdout string `default:"stdout"` - Stderr string `default:"stderr"` + Score int + Matches []Match + Stdout string `default:"stdout"` + Stderr string `default:"stderr"` + ForceQuitOnDeduct bool `default:"false"` } type Record struct { @@ -89,8 +90,13 @@ func (*CppCheck) Run(results []stage.ExecutorResult, confAny any) ( return nil, true, err } var res []stage.ParserResult + forceQuit := false for _, result := range results { - res = append(res, Parse(result, *conf)) + parseRes := Parse(result, *conf) + if conf.ForceQuitOnDeduct && parseRes.Score < conf.Score { + forceQuit = true + } + res = append(res, parseRes) } - return res, false, nil + return res, forceQuit, nil } diff --git a/internal/parser/cpplint/parser.go b/internal/parser/cpplint/parser.go index bc7abdb..7498952 100644 --- a/internal/parser/cpplint/parser.go +++ b/internal/parser/cpplint/parser.go @@ -15,10 +15,11 @@ type Match struct { } type Conf struct { - Score int - Matches []Match - Stdout string `default:"stdout"` - Stderr string `default:"stderr"` + Score int + Matches []Match + Stdout string `default:"stdout"` + Stderr string `default:"stderr"` + ForceQuitOnDeduct bool `default:"false"` } type Cpplint struct{} @@ -88,8 +89,13 @@ func (*Cpplint) Run(results []stage.ExecutorResult, confAny any) ( return nil, true, err } var res []stage.ParserResult + forceQuit := false for _, result := range results { - res = append(res, Parse(result, *conf)) + parseRes := Parse(result, *conf) + if conf.ForceQuitOnDeduct && parseRes.Score < conf.Score { + forceQuit = true + } + res = append(res, parseRes) } - return res, false, nil + return res, forceQuit, nil } -- 2.30.2 From 4db6f556c6ca1692f40e93dc05490d6ea315af80 Mon Sep 17 00:00:00 2001 From: Boming Zhang Date: Sat, 2 Nov 2024 04:26:01 -0400 Subject: [PATCH 3/3] feat(parser): backward compatibility --- internal/parser/cppcheck/parser.go | 1 + internal/parser/cppcheck/score.go | 45 ++++++++++++++++++++++++++++++ internal/parser/cpplint/parser.go | 22 +++++++++------ 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/internal/parser/cppcheck/parser.go b/internal/parser/cppcheck/parser.go index 9b65194..41cecb9 100644 --- a/internal/parser/cppcheck/parser.go +++ b/internal/parser/cppcheck/parser.go @@ -11,6 +11,7 @@ import ( type Match struct { Keywords []string + Severity []string // TODO: remove me Score int } diff --git a/internal/parser/cppcheck/score.go b/internal/parser/cppcheck/score.go index babdfe9..6b380ab 100644 --- a/internal/parser/cppcheck/score.go +++ b/internal/parser/cppcheck/score.go @@ -2,6 +2,7 @@ package cppcheck import ( "fmt" + "log/slog" "strings" ) @@ -18,10 +19,54 @@ const ( UNKNOWN ) +func severityFromString(severityString string) (Severity, error) { + switch severityString { + case "error": + return ERROR, nil + case "warning": + return WARNING, nil + case "portability": + return PORTABILITY, nil + case "performance": + return PERFORMANCE, nil + case "style": + return STYLE, nil + case "information": + return INFORMATION, nil + case "debug": + return DEBUG, nil + default: + return UNKNOWN, fmt.Errorf("unknown severity type \"%s\" for cppcheck", severityString) + } +} + func GetResult(records []Record, conf Conf) (string, int, error) { result := "### Test results summary\n\n" var severityCounts [UNKNOWN + 1]int score := conf.Score + // TODO: remove me + if len(conf.Matches) == 0 { + var severityScore [UNKNOWN + 1]int + for _, match := range conf.Matches { + severities := match.Severity + score := match.Score + for _, severityString := range severities { + severity, err := severityFromString(severityString) + if err != nil { + return "", 0, err + } + severityScore[int(severity)] = score + } + } + for _, record := range records { + severity, err := severityFromString(record.Severity) + if err != nil { + slog.Error("parse severity", "error", err) + } + severityCounts[int(severity)] += 1 + score -= severityScore[int(severity)] + } + } for _, record := range records { for _, match := range conf.Matches { for _, keyword := range match.Keywords { diff --git a/internal/parser/cpplint/parser.go b/internal/parser/cpplint/parser.go index 7498952..d3a0c3f 100644 --- a/internal/parser/cpplint/parser.go +++ b/internal/parser/cpplint/parser.go @@ -2,7 +2,9 @@ package cpplint import ( "fmt" + "log/slog" "regexp" + "strconv" "strings" "github.com/joint-online-judge/JOJ3/internal/stage" @@ -44,14 +46,18 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { // } // message := match[3] category := match[4] - // confidence, err := strconv.Atoi(match[5]) - // if err != nil { - // slog.Error("parse confidence", "error", err) - // return stage.ParserResult{ - // Score: 0, - // Comment: fmt.Sprintf("Unexpected parser error: %s.", err), - // } - // } + // TODO: remove me + if len(conf.Matches) == 0 { + confidence, err := strconv.Atoi(match[5]) + if err != nil { + slog.Error("parse confidence", "error", err) + return stage.ParserResult{ + Score: 0, + Comment: fmt.Sprintf("Unexpected parser error: %s.", err), + } + } + score -= confidence + } for _, match := range conf.Matches { for _, keyword := range match.Keywords { if strings.Contains(category, keyword) { -- 2.30.2