feat(parser): unify parsers conf #74

Merged
张泊明518370910136 merged 3 commits from linter-parsers into master 2024-11-02 16:35:07 +08:00
4 changed files with 92 additions and 44 deletions

View File

@ -19,6 +19,7 @@ type Conf struct {
Matches []Match Matches []Match
Stdout string `default:"stdout"` Stdout string `default:"stdout"`
Stderr string `default:"stderr"` Stderr string `default:"stderr"`
ForceQuitOnDeduct bool `default:"false"`
} }
type ClangTidy struct{} type ClangTidy struct{}
@ -56,8 +57,13 @@ func (*ClangTidy) Run(results []stage.ExecutorResult, confAny any) (
return nil, true, err return nil, true, err
} }
var res []stage.ParserResult var res []stage.ParserResult
forceQuit := false
for _, result := range results { for _, result := range results {
res = append(res, Parse(result, *conf)) parseRes := Parse(result, *conf)
if conf.ForceQuitOnDeduct && parseRes.Score < conf.Score {
forceQuit = true
} }
return res, false, nil res = append(res, parseRes)
}
return res, forceQuit, nil
} }

View File

@ -9,10 +9,9 @@ import (
"github.com/joint-online-judge/JOJ3/internal/stage" "github.com/joint-online-judge/JOJ3/internal/stage"
) )
type CppCheck struct{}
type Match struct { type Match struct {
Severity []string Keywords []string
Severity []string // TODO: remove me
Score int Score int
} }
@ -21,6 +20,7 @@ type Conf struct {
Matches []Match Matches []Match
Stdout string `default:"stdout"` Stdout string `default:"stdout"`
Stderr string `default:"stderr"` Stderr string `default:"stderr"`
ForceQuitOnDeduct bool `default:"false"`
} }
type Record struct { type Record struct {
@ -32,6 +32,8 @@ type Record struct {
Id string `json:"id"` Id string `json:"id"`
} }
type CppCheck struct{}
func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
// stdout := executorResult.Files[conf.Stdout] // stdout := executorResult.Files[conf.Stdout]
stderr := executorResult.Files[conf.Stderr] stderr := executorResult.Files[conf.Stderr]
@ -89,8 +91,13 @@ func (*CppCheck) Run(results []stage.ExecutorResult, confAny any) (
return nil, true, err return nil, true, err
} }
var res []stage.ParserResult var res []stage.ParserResult
forceQuit := false
for _, result := range results { for _, result := range results {
res = append(res, Parse(result, *conf)) parseRes := Parse(result, *conf)
if conf.ForceQuitOnDeduct && parseRes.Score < conf.Score {
forceQuit = true
} }
return res, false, nil res = append(res, parseRes)
}
return res, forceQuit, nil
} }

View File

@ -3,6 +3,7 @@ package cppcheck
import ( import (
"fmt" "fmt"
"log/slog" "log/slog"
"strings"
) )
type Severity int type Severity int
@ -42,9 +43,10 @@ func severityFromString(severityString string) (Severity, error) {
func GetResult(records []Record, conf Conf) (string, int, error) { func GetResult(records []Record, conf Conf) (string, int, error) {
result := "### Test results summary\n\n" result := "### Test results summary\n\n"
var severityCounts [UNKNOWN + 1]int var severityCounts [UNKNOWN + 1]int
var severityScore [UNKNOWN + 1]int
score := conf.Score score := conf.Score
// TODO: remove me
if len(conf.Matches) == 0 {
var severityScore [UNKNOWN + 1]int
for _, match := range conf.Matches { for _, match := range conf.Matches {
severities := match.Severity severities := match.Severity
score := match.Score score := match.Score
@ -56,7 +58,6 @@ func GetResult(records []Record, conf Conf) (string, int, error) {
severityScore[int(severity)] = score severityScore[int(severity)] = score
} }
} }
for _, record := range records { for _, record := range records {
severity, err := severityFromString(record.Severity) severity, err := severityFromString(record.Severity)
if err != nil { if err != nil {
@ -65,6 +66,16 @@ func GetResult(records []Record, conf Conf) (string, int, error) {
severityCounts[int(severity)] += 1 severityCounts[int(severity)] += 1
score -= severityScore[int(severity)] score -= severityScore[int(severity)]
} }
}
for _, record := range records {
for _, match := range conf.Matches {
for _, keyword := range match.Keywords {
if strings.Contains(record.Id, keyword) {
score -= match.Score
}
}
}
}
result += fmt.Sprintf("1. error: %d\n", severityCounts[0]) result += fmt.Sprintf("1. error: %d\n", severityCounts[0])
result += fmt.Sprintf("2. warning: %d\n", severityCounts[1]) result += fmt.Sprintf("2. warning: %d\n", severityCounts[1])
result += fmt.Sprintf("3. portability: %d\n", severityCounts[2]) result += fmt.Sprintf("3. portability: %d\n", severityCounts[2])

View File

@ -11,18 +11,27 @@ import (
"github.com/joint-online-judge/JOJ3/pkg/utils" "github.com/joint-online-judge/JOJ3/pkg/utils"
) )
type Match struct {
Keywords []string
Score int
}
type Conf struct { type Conf struct {
Score int Score int
Matches []Match
Stdout string `default:"stdout"`
Stderr string `default:"stderr"`
ForceQuitOnDeduct bool `default:"false"`
} }
type Cpplint struct{} type Cpplint struct{}
func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
stderr := executorResult.Files["stderr"] stderr := executorResult.Files[conf.Stderr]
pattern := `(.+):(\d+): (.+) \[(.+)\] \[(\d)]\n` pattern := `(.+):(\d+): (.+) \[(.+)\] \[(\d)]\n`
re := regexp.MustCompile(pattern) re := regexp.MustCompile(pattern)
matches := re.FindAllStringSubmatch(stderr, -1) matches := re.FindAllStringSubmatch(stderr, -1)
score := 0 score := conf.Score
comment := "### Test results summary\n\n" comment := "### Test results summary\n\n"
categoryCount := map[string]int{} categoryCount := map[string]int{}
for _, match := range matches { for _, match := range matches {
@ -37,6 +46,8 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
// } // }
// message := match[3] // message := match[3]
category := match[4] category := match[4]
// TODO: remove me
if len(conf.Matches) == 0 {
confidence, err := strconv.Atoi(match[5]) confidence, err := strconv.Atoi(match[5])
if err != nil { if err != nil {
slog.Error("parse confidence", "error", err) slog.Error("parse confidence", "error", err)
@ -46,6 +57,14 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
} }
} }
score -= confidence score -= confidence
}
for _, match := range conf.Matches {
for _, keyword := range match.Keywords {
if strings.Contains(category, keyword) {
score -= match.Score
}
}
}
parts := strings.Split(category, "/") parts := strings.Split(category, "/")
if len(parts) > 0 { if len(parts) > 0 {
category := parts[0] category := parts[0]
@ -76,8 +95,13 @@ func (*Cpplint) Run(results []stage.ExecutorResult, confAny any) (
return nil, true, err return nil, true, err
} }
var res []stage.ParserResult var res []stage.ParserResult
forceQuit := false
for _, result := range results { for _, result := range results {
res = append(res, Parse(result, *conf)) parseRes := Parse(result, *conf)
if conf.ForceQuitOnDeduct && parseRes.Score < conf.Score {
forceQuit = true
} }
return res, false, nil res = append(res, parseRes)
}
return res, forceQuit, nil
} }