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 0630d38..41cecb9 100644 --- a/internal/parser/cppcheck/parser.go +++ b/internal/parser/cppcheck/parser.go @@ -9,18 +9,18 @@ import ( "github.com/joint-online-judge/JOJ3/internal/stage" ) -type CppCheck struct{} - type Match struct { - Severity []string + Keywords []string + Severity []string // TODO: remove me Score int } 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 { @@ -32,6 +32,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] @@ -89,8 +91,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/cppcheck/score.go b/internal/parser/cppcheck/score.go index 9b30b1c..6b380ab 100644 --- a/internal/parser/cppcheck/score.go +++ b/internal/parser/cppcheck/score.go @@ -3,6 +3,7 @@ package cppcheck import ( "fmt" "log/slog" + "strings" ) type Severity int @@ -42,28 +43,38 @@ func severityFromString(severityString string) (Severity, error) { 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 + // 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 } - 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 { - 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..d3a0c3f 100644 --- a/internal/parser/cpplint/parser.go +++ b/internal/parser/cpplint/parser.go @@ -11,18 +11,27 @@ import ( "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"` + ForceQuitOnDeduct bool `default:"false"` } 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 +46,25 @@ 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) { + score -= match.Score + } } } - score -= confidence parts := strings.Split(category, "/") if len(parts) > 0 { category := parts[0] @@ -76,8 +95,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 }