From 33242654eadb9ff847b501b023f4d8bfc733c010 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Fri, 24 May 2024 11:04:14 +0800 Subject: [PATCH 1/4] init(internal/parsers/cppcheck/) cppcheck --- internal/parsers/cppcheck/meta.go | 9 ++++++ internal/parsers/cppcheck/parser.go | 48 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 internal/parsers/cppcheck/meta.go create mode 100644 internal/parsers/cppcheck/parser.go diff --git a/internal/parsers/cppcheck/meta.go b/internal/parsers/cppcheck/meta.go new file mode 100644 index 0000000..b811ad4 --- /dev/null +++ b/internal/parsers/cppcheck/meta.go @@ -0,0 +1,9 @@ +package cppcheck + +import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" + +var name = "cppcheck" + +func init() { + stage.RegisterParser(name, &CppCheck{}) +} diff --git a/internal/parsers/cppcheck/parser.go b/internal/parsers/cppcheck/parser.go new file mode 100644 index 0000000..43fc534 --- /dev/null +++ b/internal/parsers/cppcheck/parser.go @@ -0,0 +1,48 @@ +package cppcheck + +import ( + "fmt" + + "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" + "github.com/criyle/go-judge/envexec" +) + +type CppCheck struct{} + +type Conf struct { + Score int `default:"100"` + Comment string `default:""` +} + +func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { + // stdout := executorResult.Files["stdout"] + stderr := executorResult.Files["stderr"] + + if executorResult.Status != stage.Status(envexec.StatusAccepted) { + return stage.ParserResult{ + Score: 0, + Comment: fmt.Sprintf( + "Unexpected executor status: %s.\nStderr: %s", + executorResult.Status, stderr, + ), + } + } + return stage.ParserResult{ + Score: 0, + Comment: "", + } +} + +func (*CppCheck) Run(results []stage.ExecutorResult, confAny any) ( + []stage.ParserResult, bool, error, +) { + conf, err := stage.DecodeConf[Conf](confAny) + if err != nil { + return nil, true, err + } + var res []stage.ParserResult + for _, result := range results { + res = append(res, Parse(result, *conf)) + } + return res, false, nil +} -- 2.30.2 From 6bb70b1feff4df19661ace479831787193c8d561 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 28 May 2024 21:15:20 +0800 Subject: [PATCH 2/4] feat(examples/cppcheck/sillycode): update cppcheck sillycode example --- .gitmodules | 4 ++++ examples/cppcheck/sillycode | 1 + 2 files changed, 5 insertions(+) create mode 160000 examples/cppcheck/sillycode diff --git a/.gitmodules b/.gitmodules index 71c5721..d6f32b0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -30,3 +30,7 @@ path = examples/keyword/clangtidy/sillycode url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git branch = keyword/clangtidy/sillycode +[submodule "examples/cppcheck/sillycode"] + path = examples/cppcheck/sillycode + url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git + branch = cppcheck/sillycode diff --git a/examples/cppcheck/sillycode b/examples/cppcheck/sillycode new file mode 160000 index 0000000..8b4a93f --- /dev/null +++ b/examples/cppcheck/sillycode @@ -0,0 +1 @@ +Subproject commit 8b4a93f53cabc271269dcecbe073cfc0ab38d010 -- 2.30.2 From 7c8b93b0de1c086161ba8c6613a610ffd5d630f5 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 28 May 2024 21:19:10 +0800 Subject: [PATCH 3/4] feat(internal/parsers/all.go,-internal/parsers/cppcheck): cppcheck parser --- internal/parsers/all.go | 1 + internal/parsers/cppcheck/parser.go | 45 ++++++++++++++++++-- internal/parsers/cppcheck/score.go | 66 +++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 internal/parsers/cppcheck/score.go diff --git a/internal/parsers/all.go b/internal/parsers/all.go index 4decc13..615f90c 100644 --- a/internal/parsers/all.go +++ b/internal/parsers/all.go @@ -2,6 +2,7 @@ package parsers import ( _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/clangtidy" + _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/cppcheck" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/cpplint" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/diff" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/dummy" diff --git a/internal/parsers/cppcheck/parser.go b/internal/parsers/cppcheck/parser.go index 43fc534..69f39cc 100644 --- a/internal/parsers/cppcheck/parser.go +++ b/internal/parsers/cppcheck/parser.go @@ -1,7 +1,9 @@ package cppcheck import ( + "encoding/json" "fmt" + "strings" "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" "github.com/criyle/go-judge/envexec" @@ -9,9 +11,23 @@ import ( type CppCheck struct{} +type Match struct { + Severity []string + Score int +} + type Conf struct { - Score int `default:"100"` - Comment string `default:""` + Score int `default:"100"` + Matches []Match +} + +type Record struct { + File string `json:"file"` + Line int `json:"line"` + Column int `json:"column"` + Severity string `json:"severity"` + Message string `json:"message"` + Id string `json:"id"` } func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { @@ -27,9 +43,30 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { ), } } + records := make([]Record, 0) + lines := strings.Split(stderr, "\n") + for _, line := range lines { + if strings.TrimSpace(line) == "" { + continue + } + var record Record + _ = json.Unmarshal([]byte(line), &record) + records = append(records, record) + } + comment, score, err := GetResult(records, conf) + if err != nil { + return stage.ParserResult{ + Score: 0, + Comment: fmt.Sprintf( + "Unexpected parser error: %s.", + err, + ), + } + } + return stage.ParserResult{ - Score: 0, - Comment: "", + Score: score, + Comment: comment, } } diff --git a/internal/parsers/cppcheck/score.go b/internal/parsers/cppcheck/score.go new file mode 100644 index 0000000..d6028fb --- /dev/null +++ b/internal/parsers/cppcheck/score.go @@ -0,0 +1,66 @@ +package cppcheck + +import "fmt" + +type Severity int + +const ( + ERROR Severity = iota + WARNING + PROBABILITY + PERFORMANCE + STYLE + INFORMATION + UNKNOWN +) + +func severityFromString(severityString string) (Severity, error) { + switch severityString { + case "error": + return ERROR, nil + case "warning": + return WARNING, nil + case "probability": + return PROBABILITY, nil + case "performance": + return PERFORMANCE, nil + case "style": + return STYLE, nil + case "information": + return INFORMATION, nil + default: + return UNKNOWN, fmt.Errorf("unkown severity type \"%s\" for cppcheck", severityString) + } +} + +func GetResult(records []Record, conf Conf) (string, int, error) { + result := "### Test results summary\n\n" + var severityCounts [6]int + var severityScore [6]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, _ := severityFromString(record.Severity) + 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]) + result += fmt.Sprintf("3. probability: %d\n", severityCounts[2]) + result += fmt.Sprintf("4. performance: %d\n", severityCounts[3]) + result += fmt.Sprintf("5. style: %d\n", severityCounts[4]) + result += fmt.Sprintf("6. information: %d", severityCounts[5]) + return result, score, nil +} -- 2.30.2 From 18fc6239133597df260a27f00f845a1daa7aa7a4 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 28 May 2024 22:23:08 +0800 Subject: [PATCH 4/4] fix(examples/cppcheck/sillycode): fix cppcheck version issue --- examples/cppcheck/sillycode | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cppcheck/sillycode b/examples/cppcheck/sillycode index 8b4a93f..0815ab9 160000 --- a/examples/cppcheck/sillycode +++ b/examples/cppcheck/sillycode @@ -1 +1 @@ -Subproject commit 8b4a93f53cabc271269dcecbe073cfc0ab38d010 +Subproject commit 0815ab90d72641fc274231c075282567e9e17865 -- 2.30.2