From fb61ad33e3847ba8b018fe4752761384c5a51244 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Fri, 29 Mar 2024 14:57:46 +0800 Subject: [PATCH 01/25] docs(README.md): Added link to go-judge Github repo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ffcd5b6..8244647 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Quick Start -To register the sandbox executor, you need to run go-judge before running this program. +To register the sandbox executor, you need to run [`go-judge`](https://github.com/criyle/go-judge) before running this program. Install `go-judge` and start it with `go-judge -enable-grpc` ```bash $ make test -- 2.30.2 From be21a1629358d62de438b8855389742a14574401 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Fri, 29 Mar 2024 15:08:37 +0800 Subject: [PATCH 02/25] feat(ClangTidy-struct): Setup of ClangTidy struct, copied from Dummy --- internal/executors/all.go | 1 + internal/executors/clang_tidy/executor.go | 29 ++++++++++++ internal/executors/clang_tidy/meta.go | 9 ++++ internal/parsers/all.go | 1 + internal/parsers/clang_tidy/meta.go | 9 ++++ internal/parsers/clang_tidy/parser.go | 57 +++++++++++++++++++++++ 6 files changed, 106 insertions(+) create mode 100644 internal/executors/clang_tidy/executor.go create mode 100644 internal/executors/clang_tidy/meta.go create mode 100644 internal/parsers/clang_tidy/meta.go create mode 100644 internal/parsers/clang_tidy/parser.go diff --git a/internal/executors/all.go b/internal/executors/all.go index bd860e6..fc0e2b6 100644 --- a/internal/executors/all.go +++ b/internal/executors/all.go @@ -1,6 +1,7 @@ package executors import ( + _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/executors/clang_tidy" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/executors/dummy" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/executors/sandbox" ) diff --git a/internal/executors/clang_tidy/executor.go b/internal/executors/clang_tidy/executor.go new file mode 100644 index 0000000..7e227bf --- /dev/null +++ b/internal/executors/clang_tidy/executor.go @@ -0,0 +1,29 @@ +package clang_tidy + +import ( + "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" + "github.com/criyle/go-judge/envexec" +) + +type ClangTidy struct{} + +func (e *ClangTidy) Run(cmds []stage.Cmd) ([]stage.ExecutorResult, error) { + var res []stage.ExecutorResult + for range cmds { + res = append(res, stage.ExecutorResult{ + Status: stage.Status(envexec.StatusInvalid), + ExitStatus: 0, + Error: "I'm a dummy", + Time: 0, + Memory: 0, + RunTime: 0, + Files: map[string]string{}, + FileIDs: map[string]string{}, + }) + } + return res, nil +} + +func (e *ClangTidy) Cleanup() error { + return nil +} diff --git a/internal/executors/clang_tidy/meta.go b/internal/executors/clang_tidy/meta.go new file mode 100644 index 0000000..a8e4fc7 --- /dev/null +++ b/internal/executors/clang_tidy/meta.go @@ -0,0 +1,9 @@ +package clang_tidy + +import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" + +var name = "clang-tidy" + +func init() { + stage.RegisterExecutor(name, &ClangTidy{}) +} diff --git a/internal/parsers/all.go b/internal/parsers/all.go index ecc658c..ba5106b 100644 --- a/internal/parsers/all.go +++ b/internal/parsers/all.go @@ -1,6 +1,7 @@ package parsers import ( + _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/clang_tidy" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/diff" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/dummy" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/resultstatus" diff --git a/internal/parsers/clang_tidy/meta.go b/internal/parsers/clang_tidy/meta.go new file mode 100644 index 0000000..ea144c0 --- /dev/null +++ b/internal/parsers/clang_tidy/meta.go @@ -0,0 +1,9 @@ +package clang_tidy + +import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" + +var name = "clang-tidy" + +func init() { + stage.RegisterParser(name, &ClangTidy{}) +} diff --git a/internal/parsers/clang_tidy/parser.go b/internal/parsers/clang_tidy/parser.go new file mode 100644 index 0000000..db3300e --- /dev/null +++ b/internal/parsers/clang_tidy/parser.go @@ -0,0 +1,57 @@ +package clang_tidy + +import ( + "encoding/json" + "fmt" + + "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" + "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/pkg/dummy" + "github.com/criyle/go-judge/envexec" +) + +type Conf struct { + Score int + Comment string +} + +type ClangTidy struct{} + +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, + ), + } + } + var dummyResult dummy.Result + err := json.Unmarshal([]byte(stdout), &dummyResult) + if err != nil { + return stage.ParserResult{ + Score: 0, + Comment: fmt.Sprintf("Failed to parse result: %s", err), + } + } + return stage.ParserResult{ + Score: dummyResult.Score + conf.Score, + Comment: dummyResult.Comment + conf.Comment, + } +} + +func (*ClangTidy) 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 eb4815f10d0378604c3c8af9fd7e45b597d4f0d1 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 30 Apr 2024 21:44:10 +0800 Subject: [PATCH 03/25] test(examples/clang_tidy/sillycode.cpp): Auto formatting test files --- examples/clang_tidy/.gitignore | 1 + examples/clang_tidy/conf.toml | 32 ++++ examples/clang_tidy/sillycode.cpp | 262 ++++++++++++++++++++++++++++++ 3 files changed, 295 insertions(+) create mode 100644 examples/clang_tidy/.gitignore create mode 100644 examples/clang_tidy/conf.toml create mode 100644 examples/clang_tidy/sillycode.cpp diff --git a/examples/clang_tidy/.gitignore b/examples/clang_tidy/.gitignore new file mode 100644 index 0000000..a6c57f5 --- /dev/null +++ b/examples/clang_tidy/.gitignore @@ -0,0 +1 @@ +*.json diff --git a/examples/clang_tidy/conf.toml b/examples/clang_tidy/conf.toml new file mode 100644 index 0000000..c8ca732 --- /dev/null +++ b/examples/clang_tidy/conf.toml @@ -0,0 +1,32 @@ +skipGitea = true +[[stages]] +name = "clang-tidy" +[stages.executor] +name = "clang-tidy" +[stages.executor.with.default] +args = ["clang-tidy", "--header-filter=.*", "--quiet", "-checks=*", "sillycode.cpp"] +env = ["PATH=/usr/bin:/bin"] +[stages.executor.with.default.copyIn.dummy] +src = "./../../build/dummy" +copyOut = ["stdout", "stderr"] +[stages.executor.with.default.stdin] +content = "" +[stages.executor.with.default.stdout] +name = "stdout" +max = 65_536 +[stages.executor.with.default.stderr] +name = "stderr" +max = 65_536 +[stages.parser] +name = "clang-tidy" +[stages.parser.with] +score = 100 +[[stages.parser.with.matches]] +keyword = ["cppcoreguidelines-avoid-non-const-global-variables"] +score = 5 +[[stages.parser.with.matches]] +keyword = ["readability-identifier-length","misc-use-anonymous-namespace"] +score = 2 +[[stages.parser.with.matches]] +keyword = ["llvmlibc-implementation-in-namespace"] +score = 0 diff --git a/examples/clang_tidy/sillycode.cpp b/examples/clang_tidy/sillycode.cpp new file mode 100644 index 0000000..d5cd9bc --- /dev/null +++ b/examples/clang_tidy/sillycode.cpp @@ -0,0 +1,262 @@ +#include + +#include + +#include +class Date { + // ... +public: + Month month() const; // do + int month(); // don't + // ... +}; + +void do_something(vector& v) +{ + string val; + cin >> val; + // ... + int index = 0; // bad + for (int i = 0; i < v.size(); ++i) + if (v[i] == val) { + index = i; + break; + } + // ... +} + +struct X { + char ch; + int i; + string s; + char ch2; + + X& operator=(const X& a); // NOLINT(clang-analyzer-valist.Uninitialized) + X(const X&); +}; + +X waste(const char* p) +{ + if (p == nullptr) throw Nullptr_error{}; + int n = strlen(p); + auto buf = new char[n]; + if (buf == nullptr) throw Allocation_error{}; + for (int i = 0; i < n; ++i) buf[i] = p[i]; + // ... manipulate buffer ... + X x; + x.ch = 'a'; + x.s = string(n); // give x.s space for *ps + for (int i = 0; i < x.s.size(); ++i) x.s[i] = buf[i]; // copy buf into x.s + delete buf; + return x; +} + +void driver() +{ + X x = waste("Typical argument"); + // ... +} + +class X { // BAD + int i; + string s; + int j; +public: + X() :i{666}, s{"qqq"} { } // j is uninitialized + X(int ii) :i{ii} {} // s is "" and j is uninitialized + // ... +}; + +class X2 { + int i {666}; + string s {"qqq"}; + int j {0}; +public: + X2() = default; // all members are initialized to their defaults + X2(int ii) :i{ii} {} // s and j initialized to their defaults + // ... +}; + +class X3 { // BAD: inexplicit, argument passing overhead + int i; + string s; + int j; +public: + X3(int ii = 666, const string& ss = "qqq", int jj = 0) + :i{ii}, s{ss}, j{jj} { } // all members are initialized to their defaults + // ... +}; + + +class Foo { + string s; + int i; +public: + Foo& operator=(Foo&& a); + // ... +}; + +Foo& Foo::operator=(Foo&& a) // OK, but there is a cost +{ + if (this == &a) return *this; // this line is redundant + s = std::move(a.s); + i = a.i; + return *this; +} + +template +class Vector2 { + // ... + Vector2(Vector2&& a) { *this = a; } // just use the copy + Vector2& operator=(Vector2&& a) { *this = a; } // just use the copy + //... +public: + T* elem; + int sz; +}; + +void f2(N::X& a, N::X& b) +{ + swap(a,b); // calls N::swap +} + +void f3(N::X& a, N::X& b) +{ + using std::swap; // make std::swap available + swap(a,b); // calls N::swap if it exists, otherwise std::swap +} + + +// webcolors.h (third party header) +#define RED 0xFF0000 +#define GREEN 0x00FF00 +#define BLUE 0x0000FF + +// productinfo.h +// The following define product subtypes based on color +#define RED 0 +#define PURPLE 1 +#define BLUE 2 + +int webby = BLUE; // webby==2; probably not what was desired + +enum class Webcolor { red=0xFF0000, green=0x00FF00, blue=0x0000FF }; +enum class Productinfo { red=0, purple=1, blue=2 }; + +int webby = blue; // error: be specific +Webcolor webby = Webcolor::blue; + +enum Webcolor { red=0xFF0000, green=0x00FF00, blue=0x0000FF }; +enum Productinfo { red=0, purple=1, blue=2 }; + +int webby = blue; // error, ambiguous: be specific +Webcolor webby = Webcolor::blue; + +enum class Webcolor { red=0xFF0000, green=0x00FF00, blue=0x0000FF }; +enum class Productinfo { red=0, purple=1, blue=2 }; + +int webby = blue; // error: blue undefined in this scope +Webcolor webby = Webcolor::blue; + + +void sink(unique_ptr); // consumes the widget + +void sink(widget*); // just uses the widget + +void thinko(const unique_ptr&); // usually not what you want + +void reseat(unique_ptr&); // "will" or "might" reseat pointer + +constexpr int max = 8*1024; +int buf[max]; // OK, but suspicious: uninitialized +f.read(buf, max); + +constexpr int max = 8*1024; +int buf[max] = {0}; // better in some situations +f.read(buf, max); + +string s; // s is default initialized to "" +cin >> s; // s expands to hold the string + + +error_code ec; +Value v = [&] { + auto p = get_value(); // get_value() returns a pair + ec = p.first; + return p.second; +}(); + +Value v = [] { + auto p = get_value(); // get_value() returns a pair + if (p.first) throw Bad_value{p.first}; + return p.second; +}(); + +SomeLargeType var; // ugly CaMeLcAsEvArIaBlE + +if (cond) // some non-trivial condition + Set(&var); +else if (cond2 || !cond3) { + var = Set2(3.14); +} +else { + var = 0; + for (auto& e : something) + var += e; +} + +string var = [&]{ + if (!in) return ""; // default + string s; + for (char c : in >> c) + s += toupper(c); + return s; +}(); // note () + +void use(int n) +{ + switch (n) { // good + case 0: // ... + case 7: // ... + } +} + +int n = numeric_limits::max(); +int m = n + 1; // bad + +std::string s = "hello world"; +double* p = (double*)(&s); // BAD + +class base { public: virtual ~base() = 0; }; + +class derived1 : public base { }; + +class derived2 : public base { + std::string s; +public: + std::string get_s() { return s; } +}; + +derived1 d1; +base* p = &d1; // ok, implicit conversion to pointer to base is fine + +derived2* p2 = (derived2*)(p); // BAD, tries to treat d1 as a derived2, which it is not +cout << p2.get_s(); // tries to access d1's nonexistent string member, instead sees arbitrary bytes near d1 + +void f(const int& i) { + (int&)(i) = 42; // BAD +} + +static int i = 0; +static const int j = 0; + +f(i); // silent side effect +f(j); // undefined behavior + + +auto x = m*v1 + vv; // multiply m with v1 and add the result to vv + +int i; +for (i = 0; i < max; ++i); // bug waiting to happen +if (i == j) + return i; -- 2.30.2 From e133b13a840b7ff601ae34f82a1c7d2131ee3d04 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Wed, 1 May 2024 00:18:09 +0800 Subject: [PATCH 04/25] feat(internal/executors/clang_tidy,-internal/parsers/clang_tidy,-cmd/joj3/main_test.go): Parsers and executors for clang-tidy --- cmd/joj3/main_test.go | 5 + internal/executors/clang_tidy/executor.go | 46 ++++- internal/parsers/clang_tidy/convert.go | 135 +++++++++++++++ internal/parsers/clang_tidy/formatter.go | 201 ++++++++++++++++++++++ internal/parsers/clang_tidy/parser.go | 36 ++-- internal/parsers/clang_tidy/score.go | 31 ++++ 6 files changed, 437 insertions(+), 17 deletions(-) create mode 100644 internal/parsers/clang_tidy/convert.go create mode 100644 internal/parsers/clang_tidy/formatter.go create mode 100644 internal/parsers/clang_tidy/score.go diff --git a/cmd/joj3/main_test.go b/cmd/joj3/main_test.go index 73b387d..33f16a0 100644 --- a/cmd/joj3/main_test.go +++ b/cmd/joj3/main_test.go @@ -53,6 +53,11 @@ func TestMain(t *testing.T) { {Score: 100, Comment: "executor status: run time: \\d+ ns, memory: \\d+ bytes"}, }}, }}, + {"clang_tidy", []stage.StageResult{ + {Name: "clang-tidy", Results: []stage.ParserResult{ + {Score: -200, Comment: ""}, + }}, + }}, {"compile_error", []stage.StageResult{ {Name: "compile", Results: []stage.ParserResult{ {Score: 0, Comment: "Unexpected executor status: Nonzero Exit Status\\."}, diff --git a/internal/executors/clang_tidy/executor.go b/internal/executors/clang_tidy/executor.go index 7e227bf..045fd4f 100644 --- a/internal/executors/clang_tidy/executor.go +++ b/internal/executors/clang_tidy/executor.go @@ -1,6 +1,10 @@ package clang_tidy import ( + "fmt" + "io" + "os/exec" + "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" "github.com/criyle/go-judge/envexec" ) @@ -9,17 +13,49 @@ type ClangTidy struct{} func (e *ClangTidy) Run(cmds []stage.Cmd) ([]stage.ExecutorResult, error) { var res []stage.ExecutorResult - for range cmds { - res = append(res, stage.ExecutorResult{ - Status: stage.Status(envexec.StatusInvalid), + + for _, cmd := range cmds { + args := "" + for _, arg := range cmd.Args { + args += fmt.Sprint(arg) + args += " " + } + clang_tidy_Cmd := exec.Command("bash", "-c", args) + clang_tidy_stdout, err1 := clang_tidy_Cmd.StdoutPipe() + clang_tidy_stderr, err2 := clang_tidy_Cmd.StderrPipe() + if err1 != nil { + return nil, err1 + } + if err2 != nil { + return nil, err2 + } + _ = clang_tidy_Cmd.Start() + clang_tidy_Out, err1 := io.ReadAll(clang_tidy_stdout) + clang_tidy_Err, err2 := io.ReadAll(clang_tidy_stderr) + + if err1 != nil { + return nil, err1 + } + if err2 != nil { + return nil, err2 + } + + _ = clang_tidy_Cmd.Wait() + + r := stage.ExecutorResult{ + Status: stage.Status(envexec.StatusAccepted), ExitStatus: 0, - Error: "I'm a dummy", + Error: "", Time: 0, Memory: 0, RunTime: 0, Files: map[string]string{}, FileIDs: map[string]string{}, - }) + } + r.Files["stdout"] = string(clang_tidy_Out) + // TODO: We may don't want stderr + r.Files["stderr"] = string(clang_tidy_Err) + res = append(res, r) } return res, nil } diff --git a/internal/parsers/clang_tidy/convert.go b/internal/parsers/clang_tidy/convert.go new file mode 100644 index 0000000..ab63b86 --- /dev/null +++ b/internal/parsers/clang_tidy/convert.go @@ -0,0 +1,135 @@ +// Referenced from https://github.com/yuriisk/clang-tidy-converter/blob/master/clang_tidy_converter/parser/clang_tidy_parser.py +package clang_tidy + +import ( + "os" + "path/filepath" + "regexp" + "strconv" +) + +type Level int + +const ( + UNKNOWN Level = iota + NOTE + REMARK + WARNING + ERROR + FATAL +) + +type ClangMessage struct { + filepath string + line int + column int + level Level + message string + diagnosticName string + detailsLines []string + children []ClangMessage +} + +func newClangMessage(filepath string, line int, column int, level Level, message string, diagnosticName string, detailsLines []string, children []ClangMessage) *ClangMessage { + if detailsLines == nil { + detailsLines = make([]string, 0) + } + if children == nil { + children = make([]ClangMessage, 0) + } + + return &ClangMessage{ + filepath: filepath, + line: line, + column: column, + level: level, + message: message, + diagnosticName: diagnosticName, + detailsLines: detailsLines, + children: children, + } +} + +func LevelFromString(levelString string) Level { + switch levelString { + case "note": + return NOTE + case "remark": + return REMARK + case "warning": + return WARNING + case "error": + return ERROR + case "fatal": + return FATAL + default: + return UNKNOWN + } +} + +func is_ignored(line string) bool { + IGNORE_REGEX := regexp.MustCompile("^error:.*$") + return IGNORE_REGEX.MatchString(line) +} + +func parse_message(line string) ClangMessage { + MESSAGE_REGEX := regexp.MustCompile(`^(?P.+):(?P\d+):(?P\d+): (?P\S+): (?P.*?)(?: \[(?P.*)\])?\n$`) + regex_res := MESSAGE_REGEX.FindStringSubmatch(line) + if len(regex_res) == 0 { + return *newClangMessage("", 0, 0, UNKNOWN, "", "", nil, nil) + } else { + filepath := regex_res[1] + line, _ := strconv.Atoi(regex_res[2]) + column, _ := strconv.Atoi(regex_res[3]) + level := LevelFromString(regex_res[4]) + message := regex_res[5] + diagnostic_name := regex_res[6] + + return ClangMessage{ + filepath: filepath, + line: line, + column: column, + level: level, + message: message, + diagnosticName: diagnostic_name, + detailsLines: make([]string, 0), + children: make([]ClangMessage, 0), + } + } +} + +func group_messages(messages []ClangMessage) []ClangMessage { + grouped_messages := make([]ClangMessage, 0) + for _, message := range messages { + if message.level == NOTE { + grouped_messages[len(grouped_messages)-1].children = append(grouped_messages[len(grouped_messages)-1].children, message) + } else { + grouped_messages = append(grouped_messages, message) + } + } + return grouped_messages +} + +func convert_paths_to_relative(messages *[]ClangMessage) { + currentDir, _ := os.Getwd() + for i := range *messages { + (*messages)[i].filepath, _ = filepath.Rel(currentDir, (*messages)[i].filepath) + } +} + +func parse_lines(lines []string) []ClangMessage { + messages := make([]ClangMessage, 0) + for _, line := range lines { + if is_ignored(string(line)) { + continue + } + message := parse_message(string(line)) + if message.level == UNKNOWN && len(messages) > 0 { + messages[len(messages)-1].detailsLines = append(messages[len(messages)-1].detailsLines, string(line)) + } else { + messages = append(messages, message) + } + } + convert_paths_to_relative(&messages) + return group_messages(messages) +} diff --git a/internal/parsers/clang_tidy/formatter.go b/internal/parsers/clang_tidy/formatter.go new file mode 100644 index 0000000..058d4a1 --- /dev/null +++ b/internal/parsers/clang_tidy/formatter.go @@ -0,0 +1,201 @@ +// Referenced from https://github.com/yuriisk/clang-tidy-converter/blob/master/clang_tidy_converter/parser/clang_tidy_parser.py +package clang_tidy + +import ( + "fmt" + "strings" +) + +type json_message struct { + Type string `json:"type"` + Check_name string `json:"check_name"` + Description string `json:"description"` + Content map[string]interface{} `json:"content"` + Categories []string `json:"categories"` + Location map[string]interface{} `json:"location"` + Trace map[string]interface{} `json:"trace"` + Severity string `json:"severity"` + Fingerprint string `json:"fingerprint"` +} + +func format(messages []ClangMessage) []json_message { + formatted_messages := make([]json_message, len(messages)) + for i, message := range messages { + formatted_messages[i] = format_message(message) + } + return formatted_messages +} + +func format_message(message ClangMessage) json_message { + result := json_message{ + Type: "issue", + Check_name: message.diagnosticName, + Description: message.message, + Content: extract_content(message), + Categories: extract_categories(message), + Location: extract_location(message), + Trace: extract_trace(message), + Severity: extract_severity(message), + Fingerprint: "", + // Fingerprint: generate_fingerprint(message), + } + return result +} + +func messages_to_text(messages []ClangMessage) []string { + text_lines := []string{} + for _, message := range messages { + text_lines = append(text_lines, fmt.Sprintf("%s:%d:%d: %s", message.filepath, message.line, message.column, message.message)) + text_lines = append(text_lines, message.detailsLines...) + text_lines = append(text_lines, messages_to_text(message.children)...) + } + return text_lines +} + +func extract_content(message ClangMessage) map[string]interface{} { + detailLines := "" + for _, line := range message.detailsLines { + if line == "" { + continue + } + detailLines += (line + "\n") + } + for _, line := range messages_to_text(message.children) { + if line == "" { + continue + } + detailLines += (line + "\n") + } + result := map[string]interface{}{ + "body": "```\n" + detailLines + "```", + } + return result +} + +func remove_duplicates(list []string) []string { + uniqueMap := make(map[string]bool) + for _, v := range list { + uniqueMap[v] = true + } + result := []string{} + for k := range uniqueMap { + result = append(result, k) + } + return result +} + +func extract_categories(message ClangMessage) []string { + BUGRISC_CATEGORY := "Bug Risk" + CLARITY_CATEGORY := "Clarity" + COMPATIBILITY_CATEGORY := "Compatibility" + COMPLEXITY_CATEGORY := "Complexity" + DUPLICATION_CATEGORY := "Duplication" + PERFORMANCE_CATEGORY := "Performance" + SECURITY_CATEGORY := "Security" + STYLE_CATEGORY := "Style" + + categories := []string{} + if strings.Contains(message.diagnosticName, "bugprone") { + categories = append(categories, BUGRISC_CATEGORY) + } + if strings.Contains(message.diagnosticName, "modernize") { + categories = append(categories, COMPATIBILITY_CATEGORY) + } + if strings.Contains(message.diagnosticName, "portability") { + categories = append(categories, COMPATIBILITY_CATEGORY) + } + if strings.Contains(message.diagnosticName, "performance") { + categories = append(categories, PERFORMANCE_CATEGORY) + } + if strings.Contains(message.diagnosticName, "readability") { + categories = append(categories, CLARITY_CATEGORY) + } + if strings.Contains(message.diagnosticName, "cloexec") { + categories = append(categories, SECURITY_CATEGORY) + } + if strings.Contains(message.diagnosticName, "security") { + categories = append(categories, SECURITY_CATEGORY) + } + if strings.Contains(message.diagnosticName, "naming") { + categories = append(categories, STYLE_CATEGORY) + } + if strings.Contains(message.diagnosticName, "misc") { + categories = append(categories, STYLE_CATEGORY) + } + if strings.Contains(message.diagnosticName, "cppcoreguidelines") { + categories = append(categories, STYLE_CATEGORY) + } + if strings.Contains(message.diagnosticName, "hicpp") { + categories = append(categories, STYLE_CATEGORY) + } + if strings.Contains(message.diagnosticName, "simplify") { + categories = append(categories, COMPLEXITY_CATEGORY) + } + if strings.Contains(message.diagnosticName, "redundant") { + categories = append(categories, DUPLICATION_CATEGORY) + } + if strings.HasPrefix(message.diagnosticName, "boost-use-to-string") { + categories = append(categories, COMPATIBILITY_CATEGORY) + } + if len(categories) == 0 { + categories = append(categories, BUGRISC_CATEGORY) + } + return remove_duplicates(categories) +} + +func extract_location(message ClangMessage) map[string]interface{} { + location := map[string]interface{}{ + "path": message.filepath, + "lines": map[string]interface{}{ + "begin": message.line, + }, + } + return location +} + +func extract_other_locations(message ClangMessage) []map[string]interface{} { + location_list := []map[string]interface{}{} + for _, child := range message.children { + location_list = append(location_list, extract_location(child)) + location_list = append(location_list, extract_other_locations(child)...) + } + return location_list +} + +func extract_trace(message ClangMessage) map[string]interface{} { + result := map[string]interface{}{ + "locations": extract_other_locations(message), + } + return result +} + +func extract_severity(message ClangMessage) string { + switch message.level { + case NOTE: + return "info" + case REMARK: + return "minor" + case WARNING: + return "major" + case ERROR: + return "critical" + case FATAL: + return "blocker" + default: + return "unknown" + } +} + +// func generate_fingerprint(message ClangMessage) string { +// h := md5.New() +// h.Write([]byte(message.filepath)) +// h.Write([]byte(fmt.Sprintf("%d", message.line))) +// h.Write([]byte(fmt.Sprintf("%d", message.column))) +// h.Write([]byte(message.message)) +// h.Write([]byte(message.diagnosticName)) +// for _, child := range message.children { +// childFingerprint := generate_fingerprint(child) +// h.Write([]byte(childFingerprint)) +// } +// return hex.EncodeToString(h.Sum(nil)) +// } diff --git a/internal/parsers/clang_tidy/parser.go b/internal/parsers/clang_tidy/parser.go index db3300e..2ce969e 100644 --- a/internal/parsers/clang_tidy/parser.go +++ b/internal/parsers/clang_tidy/parser.go @@ -3,15 +3,21 @@ package clang_tidy import ( "encoding/json" "fmt" + "os" + "strings" "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" - "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/pkg/dummy" "github.com/criyle/go-judge/envexec" ) +type Match struct { + Keyword []string + Score int +} + type Conf struct { Score int - Comment string + Matches []Match } type ClangTidy struct{} @@ -19,6 +25,20 @@ type ClangTidy struct{} func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { stdout := executorResult.Files["stdout"] stderr := executorResult.Files["stderr"] + + lines := strings.SplitAfter(stdout, "\n") + messages := parse_lines(lines) + formatted_messages := format(messages) + + // TODO: Handle the json file (parse into markdown and delete it?) + json_file, _ := os.Create("./clangtidy_result.json") + defer json_file.Close() + + encoder := json.NewEncoder(json_file) + encoder.SetEscapeHTML(false) + encoder.SetIndent("", " ") + _ = encoder.Encode(formatted_messages) + if executorResult.Status != stage.Status(envexec.StatusAccepted) { return stage.ParserResult{ Score: 0, @@ -28,17 +48,9 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { ), } } - var dummyResult dummy.Result - err := json.Unmarshal([]byte(stdout), &dummyResult) - if err != nil { - return stage.ParserResult{ - Score: 0, - Comment: fmt.Sprintf("Failed to parse result: %s", err), - } - } return stage.ParserResult{ - Score: dummyResult.Score + conf.Score, - Comment: dummyResult.Comment + conf.Comment, + Score: get_score(formatted_messages, conf), + Comment: "", } } diff --git a/internal/parsers/clang_tidy/score.go b/internal/parsers/clang_tidy/score.go new file mode 100644 index 0000000..1c204eb --- /dev/null +++ b/internal/parsers/clang_tidy/score.go @@ -0,0 +1,31 @@ +package clang_tidy + +func Contains[T comparable](arr []T, element T) bool { + for i := range arr { + // TODO: The keyword in json report might also be an array, need to split it + // TODO: Might use string.Contains() rather than == + if element == arr[i] { + return true + } + } + return false +} + +func get_score(json_messages []json_message, conf Conf) int { + fullmark := conf.Score + for _, json_message := range json_messages { + keyword := json_message.Check_name + flag := false + for _, match := range conf.Matches { + if Contains(match.Keyword, keyword) { + fullmark -= match.Score + flag = true + break + } + } + if !flag { + fullmark -= 1 + } + } + return fullmark +} -- 2.30.2 From ecb2f0218234f73e79055501ac281a5d3345b2d6 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Sun, 5 May 2024 14:24:15 +0800 Subject: [PATCH 05/25] fix(cmd/joj3/main_test.go,-examples/clang-tidy,-internal/parsers/clang_tidy): Switched clang-tidy's executor to sandbox --- cmd/joj3/main_test.go | 7 +- .../{clang_tidy => clang-tidy}/.gitignore | 0 examples/clang-tidy/CMakeLists.txt | 5 + examples/clang-tidy/conf.toml | 62 + .../{clang_tidy => clang-tidy}/sillycode.cpp | 0 examples/clang_tidy/clangtidy_result.json | 1996 +++++++++++++++++ examples/clang_tidy/conf.toml | 32 - internal/parsers/clang_tidy/convert.go | 4 +- internal/parsers/clang_tidy/parser.go | 21 +- 9 files changed, 2079 insertions(+), 48 deletions(-) rename examples/{clang_tidy => clang-tidy}/.gitignore (100%) create mode 100644 examples/clang-tidy/CMakeLists.txt create mode 100644 examples/clang-tidy/conf.toml rename examples/{clang_tidy => clang-tidy}/sillycode.cpp (100%) create mode 100644 examples/clang_tidy/clangtidy_result.json delete mode 100644 examples/clang_tidy/conf.toml diff --git a/cmd/joj3/main_test.go b/cmd/joj3/main_test.go index 33f16a0..44b4821 100644 --- a/cmd/joj3/main_test.go +++ b/cmd/joj3/main_test.go @@ -53,9 +53,12 @@ func TestMain(t *testing.T) { {Score: 100, Comment: "executor status: run time: \\d+ ns, memory: \\d+ bytes"}, }}, }}, - {"clang_tidy", []stage.StageResult{ + {"clang-tidy", []stage.StageResult{ + {Name: "prepare", Results: []stage.ParserResult{ + {Score: 0, Comment: ""}, + }}, {Name: "clang-tidy", Results: []stage.ParserResult{ - {Score: -200, Comment: ""}, + {Score: 10, Comment: ""}, }}, }}, {"compile_error", []stage.StageResult{ diff --git a/examples/clang_tidy/.gitignore b/examples/clang-tidy/.gitignore similarity index 100% rename from examples/clang_tidy/.gitignore rename to examples/clang-tidy/.gitignore diff --git a/examples/clang-tidy/CMakeLists.txt b/examples/clang-tidy/CMakeLists.txt new file mode 100644 index 0000000..99463a8 --- /dev/null +++ b/examples/clang-tidy/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.0) + +project(MyProject) + +add_executable(main sillycode.cpp) diff --git a/examples/clang-tidy/conf.toml b/examples/clang-tidy/conf.toml new file mode 100644 index 0000000..5391357 --- /dev/null +++ b/examples/clang-tidy/conf.toml @@ -0,0 +1,62 @@ +skipGitea = true +[[stages]] +name = "prepare" +[stages.executor] +name = "sandbox" +[stages.executor.with.default] +args = ["cmake", "-S", ".", "-DDRONE=ON", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "-B", "build"] +env = ["PATH=/usr/bin:/bin"] +cpuLimit = 10_000_000_000 +memoryLimit = 104_857_600 +procLimit = 50 +copyInCwd = true +copyOut = ["stdout"] +copyOutCached = ["build/compile_commands.json"] +[stages.executor.with.default.stdin] +content = "" +[stages.executor.with.default.stdout] +name = "stdout" +max = 65_536 +[stages.executor.with.default.stderr] +name = "stderr" +max = 65_536 +[stages.parser] +name = "dummy" +[stages.parser.with] +score = 0 +comment = "" +[[stages]] +name = "clang-tidy" +[stages.executor] +name = "sandbox" +[stages.executor.with.default] +args = ["clang-tidy", "--header-filter=.*", "--quiet", "-checks=*", "sillycode.cpp", "-p", "build"] +env = ["PATH=/usr/bin:/bin"] +cpuLimit = 10_000_000_000 +memoryLimit = 104_857_600 +procLimit = 50 +copyInCwd = true +copyOut = ["stdout"] +[stages.executor.with.default.stdin] +content = "" +[stages.executor.with.default.stdout] +name = "stdout" +max = 65_536 +[stages.executor.with.default.stderr] +name = "stderr" +max = 65_536 +[stages.executor.with.default.copyInCached] +"build/compile_commands.json" = "build/compile_commands.json" +[stages.parser] +name = "clang-tidy" +[stages.parser.with] +score = 100 +[[stages.parser.with.matches]] +keyword = ["cppcoreguidelines-avoid-non-const-global-variables"] +score = 5 +[[stages.parser.with.matches]] +keyword = ["readability-identifier-length","misc-use-anonymous-namespace"] +score = 2 +[[stages.parser.with.matches]] +keyword = ["llvmlibc-implementation-in-namespace"] +score = 0 diff --git a/examples/clang_tidy/sillycode.cpp b/examples/clang-tidy/sillycode.cpp similarity index 100% rename from examples/clang_tidy/sillycode.cpp rename to examples/clang-tidy/sillycode.cpp diff --git a/examples/clang_tidy/clangtidy_result.json b/examples/clang_tidy/clangtidy_result.json new file mode 100644 index 0000000..19acf18 --- /dev/null +++ b/examples/clang_tidy/clangtidy_result.json @@ -0,0 +1,1996 @@ +[ + { + "type": "issue", + "check_name": "clang-diagnostic-error", + "description": "'gtest/test.h' file not found", + "content": { + "body": "```\n#include \n\n ^\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 3 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "critical", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-use-trailing-return-type", + "description": "use a trailing return type for this function", + "content": { + "body": "```\n Month month() const; // do\n\n ^\n\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 9 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-use-trailing-return-type", + "description": "use a trailing return type for this function", + "content": { + "body": "```\n int month(); // don't\n\n ~~~ ^\n\n auto -> int\n\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 10 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "google-runtime-references", + "description": "non-const reference parameter 'v', make it const or use a pointer", + "content": { + "body": "```\nvoid do_something(vector& v)\n\n ^\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 14 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "misc-unused-parameters", + "description": "parameter 'v' is unused", + "content": { + "body": "```\nvoid do_something(vector& v)\n\n ^\n\n /*v*/\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 14 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-init-variables", + "description": "variable 'val' is not initialized", + "content": { + "body": "```\n string val;\n\n ^\n\n = 0\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 16 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-special-member-functions", + "description": "class 'X' defines a copy constructor and a copy assignment operator but does not define a destructor, a move constructor or a move assignment operator", + "content": { + "body": "```\nstruct X {\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 28 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-special-member-functions", + "description": "class 'X' defines a copy constructor and a copy assignment operator but does not define a destructor, a move constructor or a move assignment operator", + "content": { + "body": "```\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 28 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "misc-non-private-member-variables-in-classes", + "description": "member variable 'ch' has public visibility", + "content": { + "body": "```\n char ch;\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 29 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "misc-non-private-member-variables-in-classes", + "description": "member variable 'i' has public visibility", + "content": { + "body": "```\n int i;\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 30 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "misc-non-private-member-variables-in-classes", + "description": "member variable 's' has public visibility", + "content": { + "body": "```\n string s;\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 31 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "misc-non-private-member-variables-in-classes", + "description": "member variable 'ch2' has public visibility", + "content": { + "body": "```\n char ch2;\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 32 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-use-trailing-return-type", + "description": "use a trailing return type for this function", + "content": { + "body": "```\n X& operator=(const X& a); // NOLINT(clang-analyzer-valist.Uninitialized)\n\n ~~ ^\n\n auto -> X&\n\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 34 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-use-trailing-return-type", + "description": "use a trailing return type for this function", + "content": { + "body": "```\nX waste(const char* p)\n\n~ ^\n\nauto -> X\n\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 38 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-init-variables", + "description": "variable 'n' is not initialized", + "content": { + "body": "```\n int n = strlen(p);\n\n ^\n\n = 0\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 41 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-owning-memory", + "description": "initializing non-owner 'char *' with a newly created 'gsl::owner<>'", + "content": { + "body": "```\n auto buf = new char[n];\n\n ^\n\n../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp:42:5: type deduction did not result in an owner\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 42 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [ + { + "lines": { + "begin": 42 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + } + ] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "llvm-qualified-auto", + "description": "'auto buf' can be declared as 'auto *buf'", + "content": { + "body": "```\n auto buf = new char[n];\n\n ^\n\nnote: this fix will not be applied because it overlaps with another fix\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 42 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "readability-qualified-auto", + "description": "'auto buf' can be declared as 'auto *buf'", + "content": { + "body": "```\nnote: this fix will not be applied because it overlaps with another fix\n\n```" + }, + "categories": [ + "Clarity" + ], + "location": { + "lines": { + "begin": 42 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-braces-around-statements", + "description": "statement should be inside braces", + "content": { + "body": "```\n for (int i = 0; i < n; ++i) buf[i] = p[i];\n\n ^\n\n {\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 44 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "readability-braces-around-statements", + "description": "statement should be inside braces", + "content": { + "body": "```\n for (int i = 0; i < n; ++i) buf[i] = p[i];\n\n ^\n\n {\n\n```" + }, + "categories": [ + "Clarity" + ], + "location": { + "lines": { + "begin": 44 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-pro-bounds-pointer-arithmetic", + "description": "do not use pointer arithmetic", + "content": { + "body": "```\n for (int i = 0; i < n; ++i) buf[i] = p[i];\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 44 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-pro-bounds-pointer-arithmetic", + "description": "do not use pointer arithmetic", + "content": { + "body": "```\n for (int i = 0; i < n; ++i) buf[i] = p[i];\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 44 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-owning-memory", + "description": "deleting a pointer through a type that is not marked 'gsl::owner<>'; consider using a smart pointer instead", + "content": { + "body": "```\n delete buf;\n\n ^\n\n../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp:42:5: variable declared here\n auto buf = new char[n];\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 50 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [ + { + "lines": { + "begin": 42 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + } + ] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-avoid-magic-numbers", + "description": "666 is a magic number; consider replacing it with a named constant", + "content": { + "body": "```\n int i {666};\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 71 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "readability-magic-numbers", + "description": "666 is a magic number; consider replacing it with a named constant", + "content": { + "body": "```\n```" + }, + "categories": [ + "Clarity" + ], + "location": { + "lines": { + "begin": 71 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "google-explicit-constructor", + "description": "single-argument constructors must be marked explicit to avoid unintentional implicit conversions", + "content": { + "body": "```\n X2(int ii) :i{ii} {} // s and j initialized to their defaults\n\n ^\n\n explicit \n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 76 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-explicit-conversions", + "description": "single-argument constructors must be marked explicit to avoid unintentional implicit conversions", + "content": { + "body": "```\n X2(int ii) :i{ii} {} // s and j initialized to their defaults\n\n ^\n\n explicit \n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 76 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-use-default-member-init", + "description": "use default member initializer for 'i'", + "content": { + "body": "```\n int i;\n\n ^\n\n {ii}\n\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 81 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-use-default-member-init", + "description": "use default member initializer for 'j'", + "content": { + "body": "```\n int j;\n\n ^\n\n {jj}\n\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 83 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-pro-type-member-init", + "description": "constructor does not initialize these fields: s", + "content": { + "body": "```\n X3(int ii = 666, const string& ss = \"qqq\", int jj = 0)\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 85 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "google-explicit-constructor", + "description": "constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions", + "content": { + "body": "```\n X3(int ii = 666, const string& ss = \"qqq\", int jj = 0)\n\n ^\n\n explicit \n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 85 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-explicit-conversions", + "description": "constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions", + "content": { + "body": "```\n X3(int ii = 666, const string& ss = \"qqq\", int jj = 0)\n\n ^\n\n explicit \n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 85 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-member-init", + "description": "constructor does not initialize these fields: s", + "content": { + "body": "```\n X3(int ii = 666, const string& ss = \"qqq\", int jj = 0)\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 85 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "fuchsia-default-arguments-declarations", + "description": "declaring a parameter with a default argument is disallowed", + "content": { + "body": "```\n X3(int ii = 666, const string& ss = \"qqq\", int jj = 0)\n\n ^ ~~~~~~\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 85 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-avoid-magic-numbers", + "description": "666 is a magic number; consider replacing it with a named constant", + "content": { + "body": "```\n X3(int ii = 666, const string& ss = \"qqq\", int jj = 0)\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 85 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "readability-magic-numbers", + "description": "666 is a magic number; consider replacing it with a named constant", + "content": { + "body": "```\n```" + }, + "categories": [ + "Clarity" + ], + "location": { + "lines": { + "begin": 85 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "misc-unused-parameters", + "description": "parameter 'ss' is unused", + "content": { + "body": "```\n X3(int ii = 666, const string& ss = \"qqq\", int jj = 0)\n\n ^~\n\n /*ss*/\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 85 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "fuchsia-default-arguments-declarations", + "description": "declaring a parameter with a default argument is disallowed", + "content": { + "body": "```\n X3(int ii = 666, const string& ss = \"qqq\", int jj = 0)\n\n ^ ~~~~\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 85 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-special-member-functions", + "description": "class 'Foo' defines a move assignment operator but does not define a destructor, a copy constructor, a copy assignment operator or a move constructor", + "content": { + "body": "```\nclass Foo {\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 91 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-special-member-functions", + "description": "class 'Foo' defines a move assignment operator but does not define a destructor, a copy constructor, a copy assignment operator or a move constructor", + "content": { + "body": "```\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 91 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-noexcept-move", + "description": "move assignment operators should be marked noexcept", + "content": { + "body": "```\n Foo& operator=(Foo&& a);\n\n ^\n\n noexcept \n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 95 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-use-trailing-return-type", + "description": "use a trailing return type for this function", + "content": { + "body": "```\n Foo& operator=(Foo&& a);\n\n ~~~~ ^\n\n auto -> Foo&\n\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 95 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "performance-noexcept-move-constructor", + "description": "move assignment operators should be marked noexcept", + "content": { + "body": "```\n Foo& operator=(Foo&& a);\n\n ^\n\n noexcept \n\n```" + }, + "categories": [ + "Performance" + ], + "location": { + "lines": { + "begin": 95 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-noexcept-move", + "description": "move assignment operators should be marked noexcept", + "content": { + "body": "```\nFoo& Foo::operator=(Foo&& a) // OK, but there is a cost\n\n ^\n\n noexcept \n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 99 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-use-trailing-return-type", + "description": "use a trailing return type for this function", + "content": { + "body": "```\nFoo& Foo::operator=(Foo&& a) // OK, but there is a cost\n\n~~~~ ^\n\nauto -> Foo&\n\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 99 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "performance-noexcept-move-constructor", + "description": "move assignment operators should be marked noexcept", + "content": { + "body": "```\nFoo& Foo::operator=(Foo&& a) // OK, but there is a cost\n\n ^\n\n noexcept \n\n```" + }, + "categories": [ + "Performance" + ], + "location": { + "lines": { + "begin": 99 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-braces-around-statements", + "description": "statement should be inside braces", + "content": { + "body": "```\n if (this == &a) return *this; // this line is redundant\n\n ^\n\n {\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 101 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "readability-braces-around-statements", + "description": "statement should be inside braces", + "content": { + "body": "```\n if (this == &a) return *this; // this line is redundant\n\n ^\n\n {\n\n```" + }, + "categories": [ + "Clarity" + ], + "location": { + "lines": { + "begin": 101 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-special-member-functions", + "description": "class 'Vector2' defines a move constructor and a move assignment operator but does not define a destructor, a copy constructor or a copy assignment operator", + "content": { + "body": "```\nclass Vector2 {\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 108 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-special-member-functions", + "description": "class 'Vector2' defines a move constructor and a move assignment operator but does not define a destructor, a copy constructor or a copy assignment operator", + "content": { + "body": "```\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 108 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-pro-type-member-init", + "description": "constructor does not initialize these fields: sz", + "content": { + "body": "```\n Vector2(Vector2&& a) { *this = a; } // just use the copy\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 110 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-member-init", + "description": "constructor does not initialize these fields: sz", + "content": { + "body": "```\n Vector2(Vector2&& a) { *this = a; } // just use the copy\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 110 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-noexcept-move", + "description": "move constructors should be marked noexcept", + "content": { + "body": "```\n Vector2(Vector2&& a) { *this = a; } // just use the copy\n\n ^\n\n noexcept \n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 110 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "performance-noexcept-move-constructor", + "description": "move constructors should be marked noexcept", + "content": { + "body": "```\n Vector2(Vector2&& a) { *this = a; } // just use the copy\n\n ^\n\n noexcept \n\n```" + }, + "categories": [ + "Performance" + ], + "location": { + "lines": { + "begin": 110 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-noexcept-move", + "description": "move assignment operators should be marked noexcept", + "content": { + "body": "```\n Vector2& operator=(Vector2&& a) { *this = a; } // just use the copy\n\n ^\n\n noexcept \n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 111 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-use-trailing-return-type", + "description": "use a trailing return type for this function", + "content": { + "body": "```\n Vector2& operator=(Vector2&& a) { *this = a; } // just use the copy\n\n ~~~~~~~~ ^\n\n auto -> Vector2&\n\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 111 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "performance-noexcept-move-constructor", + "description": "move assignment operators should be marked noexcept", + "content": { + "body": "```\n Vector2& operator=(Vector2&& a) { *this = a; } // just use the copy\n\n ^\n\n noexcept \n\n```" + }, + "categories": [ + "Performance" + ], + "location": { + "lines": { + "begin": 111 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "misc-non-private-member-variables-in-classes", + "description": "member variable 'elem' has public visibility", + "content": { + "body": "```\n T* elem;\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 114 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "misc-non-private-member-variables-in-classes", + "description": "member variable 'sz' has public visibility", + "content": { + "body": "```\n int sz;\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 115 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "google-runtime-references", + "description": "non-const reference parameter 'a', make it const or use a pointer", + "content": { + "body": "```\nvoid f2(N::X& a, N::X& b)\n\n ^\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 118 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "google-runtime-references", + "description": "non-const reference parameter 'b', make it const or use a pointer", + "content": { + "body": "```\nvoid f2(N::X& a, N::X& b)\n\n ^\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 118 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "google-runtime-references", + "description": "non-const reference parameter 'a', make it const or use a pointer", + "content": { + "body": "```\nvoid f3(N::X& a, N::X& b)\n\n ^\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 123 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "misc-unused-parameters", + "description": "parameter 'a' is unused", + "content": { + "body": "```\nvoid f3(N::X& a, N::X& b)\n\n ^\n\n /*a*/\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 123 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "google-runtime-references", + "description": "non-const reference parameter 'b', make it const or use a pointer", + "content": { + "body": "```\nvoid f3(N::X& a, N::X& b)\n\n ^\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 123 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "misc-unused-parameters", + "description": "parameter 'b' is unused", + "content": { + "body": "```\nvoid f3(N::X& a, N::X& b)\n\n ^\n\n /*b*/\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 123 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-macro-usage", + "description": "macro 'RED' used to declare a constant; consider using a 'constexpr' constant", + "content": { + "body": "```\n#define RED 0xFF0000\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 131 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-macro-usage", + "description": "macro 'GREEN' used to declare a constant; consider using a 'constexpr' constant", + "content": { + "body": "```\n#define GREEN 0x00FF00\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 132 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-macro-usage", + "description": "macro 'BLUE' used to declare a constant; consider using a 'constexpr' constant", + "content": { + "body": "```\n#define BLUE 0x0000FF\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 133 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-macro-usage", + "description": "macro 'RED' used to declare a constant; consider using a 'constexpr' constant", + "content": { + "body": "```\n#define RED 0\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 137 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-macro-usage", + "description": "macro 'PURPLE' used to declare a constant; consider using a 'constexpr' constant", + "content": { + "body": "```\n#define PURPLE 1\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 138 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-macro-usage", + "description": "macro 'BLUE' used to declare a constant; consider using a 'constexpr' constant", + "content": { + "body": "```\n#define BLUE 2\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 139 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "google-runtime-references", + "description": "non-const reference parameter at index 0, make it const or use a pointer", + "content": { + "body": "```\nvoid reseat(unique_ptr&); // \"will\" or \"might\" reseat pointer\n\n ^\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 168 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-avoid-c-arrays", + "description": "do not declare C-style arrays, use std::array<> instead", + "content": { + "body": "```\nint buf[max]; // OK, but suspicious: uninitialized\n\n^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 171 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-avoid-c-arrays", + "description": "do not declare C-style arrays, use std::array<> instead", + "content": { + "body": "```\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 171 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-avoid-c-arrays", + "description": "do not declare C-style arrays, use std::array<> instead", + "content": { + "body": "```\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 171 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-avoid-c-arrays", + "description": "do not declare C-style arrays, use std::array<> instead", + "content": { + "body": "```\nint buf[max] = {0}; // better in some situations\n\n^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 175 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-avoid-c-arrays", + "description": "do not declare C-style arrays, use std::array<> instead", + "content": { + "body": "```\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 175 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-avoid-c-arrays", + "description": "do not declare C-style arrays, use std::array<> instead", + "content": { + "body": "```\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 175 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-multiway-paths-covered", + "description": "potential uncovered code path; add a default label", + "content": { + "body": "```\n switch (n) { // good\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 218 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-avoid-magic-numbers", + "description": "7 is a magic number; consider replacing it with a named constant", + "content": { + "body": "```\n case 7: // ...\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 220 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "readability-magic-numbers", + "description": "7 is a magic number; consider replacing it with a named constant", + "content": { + "body": "```\n```" + }, + "categories": [ + "Clarity" + ], + "location": { + "lines": { + "begin": 220 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-special-member-functions", + "description": "class 'base' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator", + "content": { + "body": "```\nclass base { public: virtual ~base() = 0; };\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 230 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "hicpp-special-member-functions", + "description": "class 'base' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator", + "content": { + "body": "```\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 230 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "modernize-use-trailing-return-type", + "description": "use a trailing return type for this function", + "content": { + "body": "```\n std::string get_s() { return s; }\n\n ^\n\n```" + }, + "categories": [ + "Compatibility" + ], + "location": { + "lines": { + "begin": 237 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "fuchsia-statically-constructed-objects", + "description": "static objects are disallowed; if possible, use a constexpr constructor instead", + "content": { + "body": "```\nderived1 d1;\n\n^\n\n```" + }, + "categories": [ + "Bug Risk" + ], + "location": { + "lines": { + "begin": 240 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-pro-type-cstyle-cast", + "description": "do not use C-style cast to convert between unrelated types", + "content": { + "body": "```\nderived2* p2 = (derived2*)(p); // BAD, tries to treat d1 as a derived2, which it is not\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 243 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "google-readability-casting", + "description": "C-style casts are discouraged; use reinterpret_cast", + "content": { + "body": "```\nderived2* p2 = (derived2*)(p); // BAD, tries to treat d1 as a derived2, which it is not\n\n ^~~~~~~~~~~\n\n reinterpret_cast\n\n```" + }, + "categories": [ + "Clarity" + ], + "location": { + "lines": { + "begin": 243 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "google-readability-casting", + "description": "C-style casts are discouraged; use const_cast", + "content": { + "body": "```\n (int&)(i) = 42; // BAD\n\n ^~~~~~\n\n const_cast\n\n```" + }, + "categories": [ + "Clarity" + ], + "location": { + "lines": { + "begin": 247 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "cppcoreguidelines-avoid-magic-numbers", + "description": "42 is a magic number; consider replacing it with a named constant", + "content": { + "body": "```\n (int&)(i) = 42; // BAD\n\n ^\n\n```" + }, + "categories": [ + "Style" + ], + "location": { + "lines": { + "begin": 247 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + }, + { + "type": "issue", + "check_name": "readability-magic-numbers", + "description": "42 is a magic number; consider replacing it with a named constant", + "content": { + "body": "```\n```" + }, + "categories": [ + "Clarity" + ], + "location": { + "lines": { + "begin": 247 + }, + "path": "../home/zjche/Desktop/JOJ3/examples/clang_tidy/sillycode.cpp" + }, + "trace": { + "locations": [] + }, + "severity": "major", + "fingerprint": "" + } +] diff --git a/examples/clang_tidy/conf.toml b/examples/clang_tidy/conf.toml deleted file mode 100644 index c8ca732..0000000 --- a/examples/clang_tidy/conf.toml +++ /dev/null @@ -1,32 +0,0 @@ -skipGitea = true -[[stages]] -name = "clang-tidy" -[stages.executor] -name = "clang-tidy" -[stages.executor.with.default] -args = ["clang-tidy", "--header-filter=.*", "--quiet", "-checks=*", "sillycode.cpp"] -env = ["PATH=/usr/bin:/bin"] -[stages.executor.with.default.copyIn.dummy] -src = "./../../build/dummy" -copyOut = ["stdout", "stderr"] -[stages.executor.with.default.stdin] -content = "" -[stages.executor.with.default.stdout] -name = "stdout" -max = 65_536 -[stages.executor.with.default.stderr] -name = "stderr" -max = 65_536 -[stages.parser] -name = "clang-tidy" -[stages.parser.with] -score = 100 -[[stages.parser.with.matches]] -keyword = ["cppcoreguidelines-avoid-non-const-global-variables"] -score = 5 -[[stages.parser.with.matches]] -keyword = ["readability-identifier-length","misc-use-anonymous-namespace"] -score = 2 -[[stages.parser.with.matches]] -keyword = ["llvmlibc-implementation-in-namespace"] -score = 0 diff --git a/internal/parsers/clang_tidy/convert.go b/internal/parsers/clang_tidy/convert.go index ab63b86..63bafe0 100644 --- a/internal/parsers/clang_tidy/convert.go +++ b/internal/parsers/clang_tidy/convert.go @@ -2,7 +2,6 @@ package clang_tidy import ( - "os" "path/filepath" "regexp" "strconv" @@ -111,7 +110,8 @@ func group_messages(messages []ClangMessage) []ClangMessage { } func convert_paths_to_relative(messages *[]ClangMessage) { - currentDir, _ := os.Getwd() + // currentDir, _ := os.Getwd() + currentDir := "/w" for i := range *messages { (*messages)[i].filepath, _ = filepath.Rel(currentDir, (*messages)[i].filepath) } diff --git a/internal/parsers/clang_tidy/parser.go b/internal/parsers/clang_tidy/parser.go index 2ce969e..76fcb42 100644 --- a/internal/parsers/clang_tidy/parser.go +++ b/internal/parsers/clang_tidy/parser.go @@ -2,12 +2,10 @@ package clang_tidy import ( "encoding/json" - "fmt" "os" "strings" "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" - "github.com/criyle/go-judge/envexec" ) type Match struct { @@ -24,7 +22,6 @@ type ClangTidy struct{} func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { stdout := executorResult.Files["stdout"] - stderr := executorResult.Files["stderr"] lines := strings.SplitAfter(stdout, "\n") messages := parse_lines(lines) @@ -39,15 +36,15 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { encoder.SetIndent("", " ") _ = encoder.Encode(formatted_messages) - if executorResult.Status != stage.Status(envexec.StatusAccepted) { - return stage.ParserResult{ - Score: 0, - Comment: fmt.Sprintf( - "Unexpected executor status: %s.\nStderr: %s", - executorResult.Status, 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: get_score(formatted_messages, conf), Comment: "", -- 2.30.2 From 82c01468668c353694c1e1a99d499a7b803711db Mon Sep 17 00:00:00 2001 From: zjc_he Date: Sun, 5 May 2024 14:30:33 +0800 Subject: [PATCH 06/25] fix(internal/executors/clang_tidy): Removing unused clang-tidy executors --- internal/executors/clang_tidy/executor.go | 65 ----------------------- internal/executors/clang_tidy/meta.go | 9 ---- 2 files changed, 74 deletions(-) delete mode 100644 internal/executors/clang_tidy/executor.go delete mode 100644 internal/executors/clang_tidy/meta.go diff --git a/internal/executors/clang_tidy/executor.go b/internal/executors/clang_tidy/executor.go deleted file mode 100644 index 045fd4f..0000000 --- a/internal/executors/clang_tidy/executor.go +++ /dev/null @@ -1,65 +0,0 @@ -package clang_tidy - -import ( - "fmt" - "io" - "os/exec" - - "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" - "github.com/criyle/go-judge/envexec" -) - -type ClangTidy struct{} - -func (e *ClangTidy) Run(cmds []stage.Cmd) ([]stage.ExecutorResult, error) { - var res []stage.ExecutorResult - - for _, cmd := range cmds { - args := "" - for _, arg := range cmd.Args { - args += fmt.Sprint(arg) - args += " " - } - clang_tidy_Cmd := exec.Command("bash", "-c", args) - clang_tidy_stdout, err1 := clang_tidy_Cmd.StdoutPipe() - clang_tidy_stderr, err2 := clang_tidy_Cmd.StderrPipe() - if err1 != nil { - return nil, err1 - } - if err2 != nil { - return nil, err2 - } - _ = clang_tidy_Cmd.Start() - clang_tidy_Out, err1 := io.ReadAll(clang_tidy_stdout) - clang_tidy_Err, err2 := io.ReadAll(clang_tidy_stderr) - - if err1 != nil { - return nil, err1 - } - if err2 != nil { - return nil, err2 - } - - _ = clang_tidy_Cmd.Wait() - - r := stage.ExecutorResult{ - Status: stage.Status(envexec.StatusAccepted), - ExitStatus: 0, - Error: "", - Time: 0, - Memory: 0, - RunTime: 0, - Files: map[string]string{}, - FileIDs: map[string]string{}, - } - r.Files["stdout"] = string(clang_tidy_Out) - // TODO: We may don't want stderr - r.Files["stderr"] = string(clang_tidy_Err) - res = append(res, r) - } - return res, nil -} - -func (e *ClangTidy) Cleanup() error { - return nil -} diff --git a/internal/executors/clang_tidy/meta.go b/internal/executors/clang_tidy/meta.go deleted file mode 100644 index a8e4fc7..0000000 --- a/internal/executors/clang_tidy/meta.go +++ /dev/null @@ -1,9 +0,0 @@ -package clang_tidy - -import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" - -var name = "clang-tidy" - -func init() { - stage.RegisterExecutor(name, &ClangTidy{}) -} -- 2.30.2 From 2df84bb39a8eb9c98aeacb787158eb0dada42160 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Sun, 5 May 2024 14:31:38 +0800 Subject: [PATCH 07/25] fix(internal/executors/all.go): Fixing import bugs --- internal/executors/all.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/executors/all.go b/internal/executors/all.go index fc0e2b6..bd860e6 100644 --- a/internal/executors/all.go +++ b/internal/executors/all.go @@ -1,7 +1,6 @@ package executors import ( - _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/executors/clang_tidy" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/executors/dummy" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/executors/sandbox" ) -- 2.30.2 From e5af7d0b29feb8a1151fe5f0e2e861d96da1c80c Mon Sep 17 00:00:00 2001 From: zjc_he Date: Sun, 5 May 2024 19:31:11 +0800 Subject: [PATCH 08/25] feat(examples/clang-tidy/sillycode): Linking clang-tidy examples to JOJ3-example repo --- .gitmodules | 4 ++++ examples/clang-tidy/sillycode | 1 + 2 files changed, 5 insertions(+) create mode 160000 examples/clang-tidy/sillycode diff --git a/.gitmodules b/.gitmodules index 13637d8..91b7153 100644 --- a/.gitmodules +++ b/.gitmodules @@ -26,3 +26,7 @@ path = examples/keyword/clang-tidy/sillycode url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git branch = keyword/clang-tidy/sillycode +[submodule "examples/clang-tidy/sillycode"] + path = examples/clang-tidy/sillycode + url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git + branch = clang-tidy/sillycode diff --git a/examples/clang-tidy/sillycode b/examples/clang-tidy/sillycode new file mode 160000 index 0000000..adb2715 --- /dev/null +++ b/examples/clang-tidy/sillycode @@ -0,0 +1 @@ +Subproject commit adb271587b82936a092a1675213a4924782e9018 -- 2.30.2 From cd53640bfe0b63d119f8111647321fb0cf34fec4 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Sun, 5 May 2024 19:39:51 +0800 Subject: [PATCH 09/25] fix(examples/clang-tidy): removing old test files for clang-tidy --- examples/clang-tidy/.gitignore | 1 - examples/clang-tidy/CMakeLists.txt | 5 - examples/clang-tidy/conf.toml | 62 ------- examples/clang-tidy/sillycode | 2 +- examples/clang-tidy/sillycode.cpp | 262 ----------------------------- 5 files changed, 1 insertion(+), 331 deletions(-) delete mode 100644 examples/clang-tidy/.gitignore delete mode 100644 examples/clang-tidy/CMakeLists.txt delete mode 100644 examples/clang-tidy/conf.toml delete mode 100644 examples/clang-tidy/sillycode.cpp diff --git a/examples/clang-tidy/.gitignore b/examples/clang-tidy/.gitignore deleted file mode 100644 index a6c57f5..0000000 --- a/examples/clang-tidy/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.json diff --git a/examples/clang-tidy/CMakeLists.txt b/examples/clang-tidy/CMakeLists.txt deleted file mode 100644 index 99463a8..0000000 --- a/examples/clang-tidy/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 3.0) - -project(MyProject) - -add_executable(main sillycode.cpp) diff --git a/examples/clang-tidy/conf.toml b/examples/clang-tidy/conf.toml deleted file mode 100644 index 5391357..0000000 --- a/examples/clang-tidy/conf.toml +++ /dev/null @@ -1,62 +0,0 @@ -skipGitea = true -[[stages]] -name = "prepare" -[stages.executor] -name = "sandbox" -[stages.executor.with.default] -args = ["cmake", "-S", ".", "-DDRONE=ON", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "-B", "build"] -env = ["PATH=/usr/bin:/bin"] -cpuLimit = 10_000_000_000 -memoryLimit = 104_857_600 -procLimit = 50 -copyInCwd = true -copyOut = ["stdout"] -copyOutCached = ["build/compile_commands.json"] -[stages.executor.with.default.stdin] -content = "" -[stages.executor.with.default.stdout] -name = "stdout" -max = 65_536 -[stages.executor.with.default.stderr] -name = "stderr" -max = 65_536 -[stages.parser] -name = "dummy" -[stages.parser.with] -score = 0 -comment = "" -[[stages]] -name = "clang-tidy" -[stages.executor] -name = "sandbox" -[stages.executor.with.default] -args = ["clang-tidy", "--header-filter=.*", "--quiet", "-checks=*", "sillycode.cpp", "-p", "build"] -env = ["PATH=/usr/bin:/bin"] -cpuLimit = 10_000_000_000 -memoryLimit = 104_857_600 -procLimit = 50 -copyInCwd = true -copyOut = ["stdout"] -[stages.executor.with.default.stdin] -content = "" -[stages.executor.with.default.stdout] -name = "stdout" -max = 65_536 -[stages.executor.with.default.stderr] -name = "stderr" -max = 65_536 -[stages.executor.with.default.copyInCached] -"build/compile_commands.json" = "build/compile_commands.json" -[stages.parser] -name = "clang-tidy" -[stages.parser.with] -score = 100 -[[stages.parser.with.matches]] -keyword = ["cppcoreguidelines-avoid-non-const-global-variables"] -score = 5 -[[stages.parser.with.matches]] -keyword = ["readability-identifier-length","misc-use-anonymous-namespace"] -score = 2 -[[stages.parser.with.matches]] -keyword = ["llvmlibc-implementation-in-namespace"] -score = 0 diff --git a/examples/clang-tidy/sillycode b/examples/clang-tidy/sillycode index adb2715..a2c3c2f 160000 --- a/examples/clang-tidy/sillycode +++ b/examples/clang-tidy/sillycode @@ -1 +1 @@ -Subproject commit adb271587b82936a092a1675213a4924782e9018 +Subproject commit a2c3c2f9141a769968858ab77fce45bbd2e408b5 diff --git a/examples/clang-tidy/sillycode.cpp b/examples/clang-tidy/sillycode.cpp deleted file mode 100644 index d5cd9bc..0000000 --- a/examples/clang-tidy/sillycode.cpp +++ /dev/null @@ -1,262 +0,0 @@ -#include - -#include - -#include -class Date { - // ... -public: - Month month() const; // do - int month(); // don't - // ... -}; - -void do_something(vector& v) -{ - string val; - cin >> val; - // ... - int index = 0; // bad - for (int i = 0; i < v.size(); ++i) - if (v[i] == val) { - index = i; - break; - } - // ... -} - -struct X { - char ch; - int i; - string s; - char ch2; - - X& operator=(const X& a); // NOLINT(clang-analyzer-valist.Uninitialized) - X(const X&); -}; - -X waste(const char* p) -{ - if (p == nullptr) throw Nullptr_error{}; - int n = strlen(p); - auto buf = new char[n]; - if (buf == nullptr) throw Allocation_error{}; - for (int i = 0; i < n; ++i) buf[i] = p[i]; - // ... manipulate buffer ... - X x; - x.ch = 'a'; - x.s = string(n); // give x.s space for *ps - for (int i = 0; i < x.s.size(); ++i) x.s[i] = buf[i]; // copy buf into x.s - delete buf; - return x; -} - -void driver() -{ - X x = waste("Typical argument"); - // ... -} - -class X { // BAD - int i; - string s; - int j; -public: - X() :i{666}, s{"qqq"} { } // j is uninitialized - X(int ii) :i{ii} {} // s is "" and j is uninitialized - // ... -}; - -class X2 { - int i {666}; - string s {"qqq"}; - int j {0}; -public: - X2() = default; // all members are initialized to their defaults - X2(int ii) :i{ii} {} // s and j initialized to their defaults - // ... -}; - -class X3 { // BAD: inexplicit, argument passing overhead - int i; - string s; - int j; -public: - X3(int ii = 666, const string& ss = "qqq", int jj = 0) - :i{ii}, s{ss}, j{jj} { } // all members are initialized to their defaults - // ... -}; - - -class Foo { - string s; - int i; -public: - Foo& operator=(Foo&& a); - // ... -}; - -Foo& Foo::operator=(Foo&& a) // OK, but there is a cost -{ - if (this == &a) return *this; // this line is redundant - s = std::move(a.s); - i = a.i; - return *this; -} - -template -class Vector2 { - // ... - Vector2(Vector2&& a) { *this = a; } // just use the copy - Vector2& operator=(Vector2&& a) { *this = a; } // just use the copy - //... -public: - T* elem; - int sz; -}; - -void f2(N::X& a, N::X& b) -{ - swap(a,b); // calls N::swap -} - -void f3(N::X& a, N::X& b) -{ - using std::swap; // make std::swap available - swap(a,b); // calls N::swap if it exists, otherwise std::swap -} - - -// webcolors.h (third party header) -#define RED 0xFF0000 -#define GREEN 0x00FF00 -#define BLUE 0x0000FF - -// productinfo.h -// The following define product subtypes based on color -#define RED 0 -#define PURPLE 1 -#define BLUE 2 - -int webby = BLUE; // webby==2; probably not what was desired - -enum class Webcolor { red=0xFF0000, green=0x00FF00, blue=0x0000FF }; -enum class Productinfo { red=0, purple=1, blue=2 }; - -int webby = blue; // error: be specific -Webcolor webby = Webcolor::blue; - -enum Webcolor { red=0xFF0000, green=0x00FF00, blue=0x0000FF }; -enum Productinfo { red=0, purple=1, blue=2 }; - -int webby = blue; // error, ambiguous: be specific -Webcolor webby = Webcolor::blue; - -enum class Webcolor { red=0xFF0000, green=0x00FF00, blue=0x0000FF }; -enum class Productinfo { red=0, purple=1, blue=2 }; - -int webby = blue; // error: blue undefined in this scope -Webcolor webby = Webcolor::blue; - - -void sink(unique_ptr); // consumes the widget - -void sink(widget*); // just uses the widget - -void thinko(const unique_ptr&); // usually not what you want - -void reseat(unique_ptr&); // "will" or "might" reseat pointer - -constexpr int max = 8*1024; -int buf[max]; // OK, but suspicious: uninitialized -f.read(buf, max); - -constexpr int max = 8*1024; -int buf[max] = {0}; // better in some situations -f.read(buf, max); - -string s; // s is default initialized to "" -cin >> s; // s expands to hold the string - - -error_code ec; -Value v = [&] { - auto p = get_value(); // get_value() returns a pair - ec = p.first; - return p.second; -}(); - -Value v = [] { - auto p = get_value(); // get_value() returns a pair - if (p.first) throw Bad_value{p.first}; - return p.second; -}(); - -SomeLargeType var; // ugly CaMeLcAsEvArIaBlE - -if (cond) // some non-trivial condition - Set(&var); -else if (cond2 || !cond3) { - var = Set2(3.14); -} -else { - var = 0; - for (auto& e : something) - var += e; -} - -string var = [&]{ - if (!in) return ""; // default - string s; - for (char c : in >> c) - s += toupper(c); - return s; -}(); // note () - -void use(int n) -{ - switch (n) { // good - case 0: // ... - case 7: // ... - } -} - -int n = numeric_limits::max(); -int m = n + 1; // bad - -std::string s = "hello world"; -double* p = (double*)(&s); // BAD - -class base { public: virtual ~base() = 0; }; - -class derived1 : public base { }; - -class derived2 : public base { - std::string s; -public: - std::string get_s() { return s; } -}; - -derived1 d1; -base* p = &d1; // ok, implicit conversion to pointer to base is fine - -derived2* p2 = (derived2*)(p); // BAD, tries to treat d1 as a derived2, which it is not -cout << p2.get_s(); // tries to access d1's nonexistent string member, instead sees arbitrary bytes near d1 - -void f(const int& i) { - (int&)(i) = 42; // BAD -} - -static int i = 0; -static const int j = 0; - -f(i); // silent side effect -f(j); // undefined behavior - - -auto x = m*v1 + vv; // multiply m with v1 and add the result to vv - -int i; -for (i = 0; i < max; ++i); // bug waiting to happen -if (i == j) - return i; -- 2.30.2 From f68bbef4a600f61c2fe99c5a4bfe56e4cdf29c0a Mon Sep 17 00:00:00 2001 From: zjc_he Date: Sun, 5 May 2024 20:51:03 +0800 Subject: [PATCH 10/25] fix(examples/clang-tidy): Update config files --- examples/clang-tidy/sillycode | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/clang-tidy/sillycode b/examples/clang-tidy/sillycode index a2c3c2f..267f23c 160000 --- a/examples/clang-tidy/sillycode +++ b/examples/clang-tidy/sillycode @@ -1 +1 @@ -Subproject commit a2c3c2f9141a769968858ab77fce45bbd2e408b5 +Subproject commit 267f23cc74cea628850633dd39d7a1f37d7f7eb3 -- 2.30.2 From 5c42a5f055030f501518d2dc508c1c36cf1151a6 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Sun, 5 May 2024 20:57:33 +0800 Subject: [PATCH 11/25] fix(internal/clang_tidy/score.go): Unlisted keywords will be 0 point rather than 1 --- internal/parsers/clang_tidy/convert.go | 1 - internal/parsers/clang_tidy/score.go | 5 ----- 2 files changed, 6 deletions(-) diff --git a/internal/parsers/clang_tidy/convert.go b/internal/parsers/clang_tidy/convert.go index 63bafe0..e386586 100644 --- a/internal/parsers/clang_tidy/convert.go +++ b/internal/parsers/clang_tidy/convert.go @@ -110,7 +110,6 @@ func group_messages(messages []ClangMessage) []ClangMessage { } func convert_paths_to_relative(messages *[]ClangMessage) { - // currentDir, _ := os.Getwd() currentDir := "/w" for i := range *messages { (*messages)[i].filepath, _ = filepath.Rel(currentDir, (*messages)[i].filepath) diff --git a/internal/parsers/clang_tidy/score.go b/internal/parsers/clang_tidy/score.go index 1c204eb..04ab6fe 100644 --- a/internal/parsers/clang_tidy/score.go +++ b/internal/parsers/clang_tidy/score.go @@ -15,17 +15,12 @@ func get_score(json_messages []json_message, conf Conf) int { fullmark := conf.Score for _, json_message := range json_messages { keyword := json_message.Check_name - flag := false for _, match := range conf.Matches { if Contains(match.Keyword, keyword) { fullmark -= match.Score - flag = true break } } - if !flag { - fullmark -= 1 - } } return fullmark } -- 2.30.2 From 061664eb70419972bdab042f314fcb90a6cd4d4b Mon Sep 17 00:00:00 2001 From: zjc_he Date: Sun, 5 May 2024 21:36:52 +0800 Subject: [PATCH 12/25] feat(internal/parsers/clang_tidy): Added comments for clang-tidy parser --- examples/clang-tidy/sillycode | 2 +- internal/parsers/clang_tidy/parser.go | 2 +- internal/parsers/clang_tidy/score.go | 57 +++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/examples/clang-tidy/sillycode b/examples/clang-tidy/sillycode index 267f23c..bb8c33d 160000 --- a/examples/clang-tidy/sillycode +++ b/examples/clang-tidy/sillycode @@ -1 +1 @@ -Subproject commit 267f23cc74cea628850633dd39d7a1f37d7f7eb3 +Subproject commit bb8c33dc62742f7fc9f25ac91582fc4fa4ac3d5d diff --git a/internal/parsers/clang_tidy/parser.go b/internal/parsers/clang_tidy/parser.go index 76fcb42..96f8344 100644 --- a/internal/parsers/clang_tidy/parser.go +++ b/internal/parsers/clang_tidy/parser.go @@ -47,7 +47,7 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { // } return stage.ParserResult{ Score: get_score(formatted_messages, conf), - Comment: "", + Comment: get_comment(formatted_messages), } } diff --git a/internal/parsers/clang_tidy/score.go b/internal/parsers/clang_tidy/score.go index 04ab6fe..002533f 100644 --- a/internal/parsers/clang_tidy/score.go +++ b/internal/parsers/clang_tidy/score.go @@ -1,10 +1,14 @@ package clang_tidy -func Contains[T comparable](arr []T, element T) bool { +import ( + "fmt" + "strings" +) + +func Contains(arr []string, element string) bool { for i := range arr { // TODO: The keyword in json report might also be an array, need to split it - // TODO: Might use string.Contains() rather than == - if element == arr[i] { + if strings.Contains(arr[i], element) { return true } } @@ -24,3 +28,50 @@ func get_score(json_messages []json_message, conf Conf) int { } return fullmark } + +func get_comment(json_messages []json_message) string { + res := "```\n### Test results summary\n\n" + keys := [...]string{ + "codequality-unchecked-malloc-result", + "codequality-no-global-variables", + "codequality-no-header-guard", + "codequality-no-fflush-stdin", + "readability-function-size", + "readability-identifier-naming", + "readability-redundant", + "readability-misleading-indentation", + "readability-misplaced-array-index", + "cppcoreguidelines-init-variables", + "bugprone-suspicious-string-compare", + "google-global-names-in-headers", + "clang-diagnostic", + "clang-analyzer", + "misc", + "performance", + "others", + } + mapping := map[string]int{} + for _, key := range keys { + mapping[key] = 0 + } + for _, json_message := range json_messages { + keyword := json_message.Check_name + flag := true + for key := range mapping { + if strings.Contains(keyword, key) { + mapping[key] += 1 + flag = false + break + } + } + if flag { + mapping["others"] += 1 + } + } + + for i, key := range keys { + res = fmt.Sprintf("%s%d. %s: %d\n", res, i+1, key, mapping[key]) + } + res += "```" + return res +} -- 2.30.2 From 430662daca4e1709fa1a59c29cd2cefd52802f37 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Sun, 5 May 2024 21:44:47 +0800 Subject: [PATCH 13/25] fix(internal/parsers/clang_tidy/score.go): slightly fix the output format --- examples/clang-tidy/sillycode | 2 +- internal/parsers/clang_tidy/score.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/clang-tidy/sillycode b/examples/clang-tidy/sillycode index bb8c33d..422868c 160000 --- a/examples/clang-tidy/sillycode +++ b/examples/clang-tidy/sillycode @@ -1 +1 @@ -Subproject commit bb8c33dc62742f7fc9f25ac91582fc4fa4ac3d5d +Subproject commit 422868c1c6427ce73e665477b40922c72ccc14e5 diff --git a/internal/parsers/clang_tidy/score.go b/internal/parsers/clang_tidy/score.go index 002533f..9630824 100644 --- a/internal/parsers/clang_tidy/score.go +++ b/internal/parsers/clang_tidy/score.go @@ -30,7 +30,7 @@ func get_score(json_messages []json_message, conf Conf) int { } func get_comment(json_messages []json_message) string { - res := "```\n### Test results summary\n\n" + res := "### Test results summary\n\n" keys := [...]string{ "codequality-unchecked-malloc-result", "codequality-no-global-variables", @@ -72,6 +72,5 @@ func get_comment(json_messages []json_message) string { for i, key := range keys { res = fmt.Sprintf("%s%d. %s: %d\n", res, i+1, key, mapping[key]) } - res += "```" return res } -- 2.30.2 From 07ef611f95accbca5daedecf3ce7ea2cf11977fa Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 7 May 2024 14:46:34 +0800 Subject: [PATCH 14/25] feat(internal/parsers/clang_tidy): Allow working root dir to be set in config, default is "/w" --- examples/clang-tidy/sillycode | 2 +- internal/parsers/clang_tidy/convert.go | 8 ++++---- internal/parsers/clang_tidy/parser.go | 6 ++++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/examples/clang-tidy/sillycode b/examples/clang-tidy/sillycode index 422868c..580d9c9 160000 --- a/examples/clang-tidy/sillycode +++ b/examples/clang-tidy/sillycode @@ -1 +1 @@ -Subproject commit 422868c1c6427ce73e665477b40922c72ccc14e5 +Subproject commit 580d9c9e20ae887551af2f87483d82cf6efa6f6d diff --git a/internal/parsers/clang_tidy/convert.go b/internal/parsers/clang_tidy/convert.go index e386586..7bbf442 100644 --- a/internal/parsers/clang_tidy/convert.go +++ b/internal/parsers/clang_tidy/convert.go @@ -109,14 +109,14 @@ func group_messages(messages []ClangMessage) []ClangMessage { return grouped_messages } -func convert_paths_to_relative(messages *[]ClangMessage) { - currentDir := "/w" +func convert_paths_to_relative(messages *[]ClangMessage, conf Conf) { + currentDir := conf.RootDir for i := range *messages { (*messages)[i].filepath, _ = filepath.Rel(currentDir, (*messages)[i].filepath) } } -func parse_lines(lines []string) []ClangMessage { +func parse_lines(lines []string, conf Conf) []ClangMessage { messages := make([]ClangMessage, 0) for _, line := range lines { if is_ignored(string(line)) { @@ -129,6 +129,6 @@ func parse_lines(lines []string) []ClangMessage { messages = append(messages, message) } } - convert_paths_to_relative(&messages) + convert_paths_to_relative(&messages, conf) return group_messages(messages) } diff --git a/internal/parsers/clang_tidy/parser.go b/internal/parsers/clang_tidy/parser.go index 96f8344..bdf8f52 100644 --- a/internal/parsers/clang_tidy/parser.go +++ b/internal/parsers/clang_tidy/parser.go @@ -14,7 +14,8 @@ type Match struct { } type Conf struct { - Score int + Score int `default:"100"` + RootDir string `default:"\\w"` Matches []Match } @@ -24,7 +25,7 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { stdout := executorResult.Files["stdout"] lines := strings.SplitAfter(stdout, "\n") - messages := parse_lines(lines) + messages := parse_lines(lines, conf) formatted_messages := format(messages) // TODO: Handle the json file (parse into markdown and delete it?) @@ -36,6 +37,7 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { encoder.SetIndent("", " ") _ = encoder.Encode(formatted_messages) + // TODO: Handle unexpected errors from executor // if executorResult.Status != stage.Status(envexec.StatusAccepted) { // return stage.ParserResult{ // Score: 0, -- 2.30.2 From 87c2bc38d047a33336a30761aa1a3d1fc5e0f2f6 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 7 May 2024 14:52:12 +0800 Subject: [PATCH 15/25] fix(internal/parsers/clang_tidy/parser.go): Removing unused local json file --- internal/parsers/clang_tidy/parser.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/internal/parsers/clang_tidy/parser.go b/internal/parsers/clang_tidy/parser.go index bdf8f52..2a22154 100644 --- a/internal/parsers/clang_tidy/parser.go +++ b/internal/parsers/clang_tidy/parser.go @@ -1,8 +1,6 @@ package clang_tidy import ( - "encoding/json" - "os" "strings" "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" @@ -28,15 +26,6 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { messages := parse_lines(lines, conf) formatted_messages := format(messages) - // TODO: Handle the json file (parse into markdown and delete it?) - json_file, _ := os.Create("./clangtidy_result.json") - defer json_file.Close() - - encoder := json.NewEncoder(json_file) - encoder.SetEscapeHTML(false) - encoder.SetIndent("", " ") - _ = encoder.Encode(formatted_messages) - // TODO: Handle unexpected errors from executor // if executorResult.Status != stage.Status(envexec.StatusAccepted) { // return stage.ParserResult{ -- 2.30.2 From b0f3c880d59bcf234f099f6a5a9e31577d9a8271 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 7 May 2024 15:38:05 +0800 Subject: [PATCH 16/25] fix(internal/parsers/clang_tidy/parser.go): Fix typo in default root dir --- internal/parsers/clang_tidy/parser.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/parsers/clang_tidy/parser.go b/internal/parsers/clang_tidy/parser.go index 2a22154..58a8a7d 100644 --- a/internal/parsers/clang_tidy/parser.go +++ b/internal/parsers/clang_tidy/parser.go @@ -13,7 +13,7 @@ type Match struct { type Conf struct { Score int `default:"100"` - RootDir string `default:"\\w"` + RootDir string `default:"/w"` Matches []Match } -- 2.30.2 From 09024b4c15fefca2bdc062195f12e3d142c71a16 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 7 May 2024 15:39:26 +0800 Subject: [PATCH 17/25] fix(internal/parsers/clang_tidy/formatter.go): remove unused code for fingerprints --- internal/parsers/clang_tidy/formatter.go | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/internal/parsers/clang_tidy/formatter.go b/internal/parsers/clang_tidy/formatter.go index 058d4a1..2a955c3 100644 --- a/internal/parsers/clang_tidy/formatter.go +++ b/internal/parsers/clang_tidy/formatter.go @@ -15,7 +15,6 @@ type json_message struct { Location map[string]interface{} `json:"location"` Trace map[string]interface{} `json:"trace"` Severity string `json:"severity"` - Fingerprint string `json:"fingerprint"` } func format(messages []ClangMessage) []json_message { @@ -36,8 +35,6 @@ func format_message(message ClangMessage) json_message { Location: extract_location(message), Trace: extract_trace(message), Severity: extract_severity(message), - Fingerprint: "", - // Fingerprint: generate_fingerprint(message), } return result } @@ -185,17 +182,3 @@ func extract_severity(message ClangMessage) string { return "unknown" } } - -// func generate_fingerprint(message ClangMessage) string { -// h := md5.New() -// h.Write([]byte(message.filepath)) -// h.Write([]byte(fmt.Sprintf("%d", message.line))) -// h.Write([]byte(fmt.Sprintf("%d", message.column))) -// h.Write([]byte(message.message)) -// h.Write([]byte(message.diagnosticName)) -// for _, child := range message.children { -// childFingerprint := generate_fingerprint(child) -// h.Write([]byte(childFingerprint)) -// } -// return hex.EncodeToString(h.Sum(nil)) -// } -- 2.30.2 From 6429d820a9569b1429762d17ee7195b5dfea7bbd Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 7 May 2024 16:03:49 +0800 Subject: [PATCH 18/25] fix(internal/parsers/clang_tidy/parser.go): check the return value of executor, if not 0 or 1 then report error --- examples/clang-tidy/sillycode | 2 +- internal/parsers/clang_tidy/parser.go | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/examples/clang-tidy/sillycode b/examples/clang-tidy/sillycode index 580d9c9..4b00eac 160000 --- a/examples/clang-tidy/sillycode +++ b/examples/clang-tidy/sillycode @@ -1 +1 @@ -Subproject commit 580d9c9e20ae887551af2f87483d82cf6efa6f6d +Subproject commit 4b00eacf88277a06bbb5052e5b2688cd622521d0 diff --git a/internal/parsers/clang_tidy/parser.go b/internal/parsers/clang_tidy/parser.go index 58a8a7d..a416b25 100644 --- a/internal/parsers/clang_tidy/parser.go +++ b/internal/parsers/clang_tidy/parser.go @@ -1,9 +1,11 @@ package clang_tidy import ( + "fmt" "strings" "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" + "github.com/criyle/go-judge/envexec" ) type Match struct { @@ -21,21 +23,24 @@ type ClangTidy struct{} func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { stdout := executorResult.Files["stdout"] + stderr := executorResult.Files["stderr"] lines := strings.SplitAfter(stdout, "\n") messages := parse_lines(lines, conf) formatted_messages := format(messages) - // TODO: Handle unexpected errors from executor - // if executorResult.Status != stage.Status(envexec.StatusAccepted) { - // return stage.ParserResult{ - // Score: 0, - // Comment: fmt.Sprintf( - // "Unexpected executor status: %s.\nStderr: %s", - // executorResult.Status, stderr, - // ), - // } - // } + if executorResult.Status != stage.Status(envexec.StatusAccepted) { + if !((executorResult.Status == stage.Status(envexec.StatusNonzeroExitStatus)) && + (executorResult.ExitStatus == 1)) { + return stage.ParserResult{ + Score: 0, + Comment: fmt.Sprintf( + "Unexpected executor status: %s.\nStderr: %s", + executorResult.Status, stderr, + ), + } + } + } return stage.ParserResult{ Score: get_score(formatted_messages, conf), Comment: get_comment(formatted_messages), -- 2.30.2 From 84121aa6f4ca4e9cdd7318c2b7c4d22068497d7c Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 7 May 2024 16:12:03 +0800 Subject: [PATCH 19/25] fix(internal/parsers/clang_tidy/score.go): Add a missing keyword --- examples/clang-tidy/sillycode | 2 +- internal/parsers/clang_tidy/score.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/clang-tidy/sillycode b/examples/clang-tidy/sillycode index 4b00eac..54de5d5 160000 --- a/examples/clang-tidy/sillycode +++ b/examples/clang-tidy/sillycode @@ -1 +1 @@ -Subproject commit 4b00eacf88277a06bbb5052e5b2688cd622521d0 +Subproject commit 54de5d52294a9e7c8264cfbbe387bc1a23050d71 diff --git a/internal/parsers/clang_tidy/score.go b/internal/parsers/clang_tidy/score.go index 9630824..245b676 100644 --- a/internal/parsers/clang_tidy/score.go +++ b/internal/parsers/clang_tidy/score.go @@ -37,6 +37,7 @@ func get_comment(json_messages []json_message) string { "codequality-no-header-guard", "codequality-no-fflush-stdin", "readability-function-size", + "readability-duplicate-include", "readability-identifier-naming", "readability-redundant", "readability-misleading-indentation", -- 2.30.2 From 0393ba6e232e43a3faed3bbf1cd2afb38e7eb44a Mon Sep 17 00:00:00 2001 From: zjc_he Date: Tue, 7 May 2024 16:24:09 +0800 Subject: [PATCH 20/25] feat(examples/clang-tidy/sillycode): putting two stages together --- examples/clang-tidy/sillycode | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/clang-tidy/sillycode b/examples/clang-tidy/sillycode index 54de5d5..a16c54c 160000 --- a/examples/clang-tidy/sillycode +++ b/examples/clang-tidy/sillycode @@ -1 +1 @@ -Subproject commit 54de5d52294a9e7c8264cfbbe387bc1a23050d71 +Subproject commit a16c54c3ac3254437b8d523f1a3fa5bd3067a81a -- 2.30.2 From adefbfd1fabe1dfeb59da7d6304bf913287be55e Mon Sep 17 00:00:00 2001 From: zjc_he Date: Fri, 10 May 2024 23:23:12 +0800 Subject: [PATCH 21/25] style(internal/parsers/clangtidy): fix naming convention --- examples/clang-tidy/sillycode | 2 +- internal/parsers/all.go | 2 +- internal/parsers/clang_tidy/formatter.go | 184 ------------------ .../{clang_tidy => clangtidy}/convert.go | 24 +-- internal/parsers/clangtidy/formatter.go | 184 ++++++++++++++++++ .../parsers/{clang_tidy => clangtidy}/meta.go | 4 +- .../{clang_tidy => clangtidy}/parser.go | 10 +- .../{clang_tidy => clangtidy}/score.go | 16 +- 8 files changed, 213 insertions(+), 213 deletions(-) delete mode 100644 internal/parsers/clang_tidy/formatter.go rename internal/parsers/{clang_tidy => clangtidy}/convert.go (84%) create mode 100644 internal/parsers/clangtidy/formatter.go rename internal/parsers/{clang_tidy => clangtidy}/meta.go (74%) rename internal/parsers/{clang_tidy => clangtidy}/parser.go (86%) rename internal/parsers/{clang_tidy => clangtidy}/score.go (79%) diff --git a/examples/clang-tidy/sillycode b/examples/clang-tidy/sillycode index a16c54c..a69a7e8 160000 --- a/examples/clang-tidy/sillycode +++ b/examples/clang-tidy/sillycode @@ -1 +1 @@ -Subproject commit a16c54c3ac3254437b8d523f1a3fa5bd3067a81a +Subproject commit a69a7e87fddaddf21fc4f9cd6774e310fa7137c1 diff --git a/internal/parsers/all.go b/internal/parsers/all.go index 64dddd9..4decc13 100644 --- a/internal/parsers/all.go +++ b/internal/parsers/all.go @@ -1,7 +1,7 @@ package parsers import ( - _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/clang_tidy" + _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/clangtidy" _ "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/clang_tidy/formatter.go b/internal/parsers/clang_tidy/formatter.go deleted file mode 100644 index 2a955c3..0000000 --- a/internal/parsers/clang_tidy/formatter.go +++ /dev/null @@ -1,184 +0,0 @@ -// Referenced from https://github.com/yuriisk/clang-tidy-converter/blob/master/clang_tidy_converter/parser/clang_tidy_parser.py -package clang_tidy - -import ( - "fmt" - "strings" -) - -type json_message struct { - Type string `json:"type"` - Check_name string `json:"check_name"` - Description string `json:"description"` - Content map[string]interface{} `json:"content"` - Categories []string `json:"categories"` - Location map[string]interface{} `json:"location"` - Trace map[string]interface{} `json:"trace"` - Severity string `json:"severity"` -} - -func format(messages []ClangMessage) []json_message { - formatted_messages := make([]json_message, len(messages)) - for i, message := range messages { - formatted_messages[i] = format_message(message) - } - return formatted_messages -} - -func format_message(message ClangMessage) json_message { - result := json_message{ - Type: "issue", - Check_name: message.diagnosticName, - Description: message.message, - Content: extract_content(message), - Categories: extract_categories(message), - Location: extract_location(message), - Trace: extract_trace(message), - Severity: extract_severity(message), - } - return result -} - -func messages_to_text(messages []ClangMessage) []string { - text_lines := []string{} - for _, message := range messages { - text_lines = append(text_lines, fmt.Sprintf("%s:%d:%d: %s", message.filepath, message.line, message.column, message.message)) - text_lines = append(text_lines, message.detailsLines...) - text_lines = append(text_lines, messages_to_text(message.children)...) - } - return text_lines -} - -func extract_content(message ClangMessage) map[string]interface{} { - detailLines := "" - for _, line := range message.detailsLines { - if line == "" { - continue - } - detailLines += (line + "\n") - } - for _, line := range messages_to_text(message.children) { - if line == "" { - continue - } - detailLines += (line + "\n") - } - result := map[string]interface{}{ - "body": "```\n" + detailLines + "```", - } - return result -} - -func remove_duplicates(list []string) []string { - uniqueMap := make(map[string]bool) - for _, v := range list { - uniqueMap[v] = true - } - result := []string{} - for k := range uniqueMap { - result = append(result, k) - } - return result -} - -func extract_categories(message ClangMessage) []string { - BUGRISC_CATEGORY := "Bug Risk" - CLARITY_CATEGORY := "Clarity" - COMPATIBILITY_CATEGORY := "Compatibility" - COMPLEXITY_CATEGORY := "Complexity" - DUPLICATION_CATEGORY := "Duplication" - PERFORMANCE_CATEGORY := "Performance" - SECURITY_CATEGORY := "Security" - STYLE_CATEGORY := "Style" - - categories := []string{} - if strings.Contains(message.diagnosticName, "bugprone") { - categories = append(categories, BUGRISC_CATEGORY) - } - if strings.Contains(message.diagnosticName, "modernize") { - categories = append(categories, COMPATIBILITY_CATEGORY) - } - if strings.Contains(message.diagnosticName, "portability") { - categories = append(categories, COMPATIBILITY_CATEGORY) - } - if strings.Contains(message.diagnosticName, "performance") { - categories = append(categories, PERFORMANCE_CATEGORY) - } - if strings.Contains(message.diagnosticName, "readability") { - categories = append(categories, CLARITY_CATEGORY) - } - if strings.Contains(message.diagnosticName, "cloexec") { - categories = append(categories, SECURITY_CATEGORY) - } - if strings.Contains(message.diagnosticName, "security") { - categories = append(categories, SECURITY_CATEGORY) - } - if strings.Contains(message.diagnosticName, "naming") { - categories = append(categories, STYLE_CATEGORY) - } - if strings.Contains(message.diagnosticName, "misc") { - categories = append(categories, STYLE_CATEGORY) - } - if strings.Contains(message.diagnosticName, "cppcoreguidelines") { - categories = append(categories, STYLE_CATEGORY) - } - if strings.Contains(message.diagnosticName, "hicpp") { - categories = append(categories, STYLE_CATEGORY) - } - if strings.Contains(message.diagnosticName, "simplify") { - categories = append(categories, COMPLEXITY_CATEGORY) - } - if strings.Contains(message.diagnosticName, "redundant") { - categories = append(categories, DUPLICATION_CATEGORY) - } - if strings.HasPrefix(message.diagnosticName, "boost-use-to-string") { - categories = append(categories, COMPATIBILITY_CATEGORY) - } - if len(categories) == 0 { - categories = append(categories, BUGRISC_CATEGORY) - } - return remove_duplicates(categories) -} - -func extract_location(message ClangMessage) map[string]interface{} { - location := map[string]interface{}{ - "path": message.filepath, - "lines": map[string]interface{}{ - "begin": message.line, - }, - } - return location -} - -func extract_other_locations(message ClangMessage) []map[string]interface{} { - location_list := []map[string]interface{}{} - for _, child := range message.children { - location_list = append(location_list, extract_location(child)) - location_list = append(location_list, extract_other_locations(child)...) - } - return location_list -} - -func extract_trace(message ClangMessage) map[string]interface{} { - result := map[string]interface{}{ - "locations": extract_other_locations(message), - } - return result -} - -func extract_severity(message ClangMessage) string { - switch message.level { - case NOTE: - return "info" - case REMARK: - return "minor" - case WARNING: - return "major" - case ERROR: - return "critical" - case FATAL: - return "blocker" - default: - return "unknown" - } -} diff --git a/internal/parsers/clang_tidy/convert.go b/internal/parsers/clangtidy/convert.go similarity index 84% rename from internal/parsers/clang_tidy/convert.go rename to internal/parsers/clangtidy/convert.go index 7bbf442..9d829dd 100644 --- a/internal/parsers/clang_tidy/convert.go +++ b/internal/parsers/clangtidy/convert.go @@ -1,5 +1,5 @@ // Referenced from https://github.com/yuriisk/clang-tidy-converter/blob/master/clang_tidy_converter/parser/clang_tidy_parser.py -package clang_tidy +package clangtidy import ( "path/filepath" @@ -49,7 +49,7 @@ func newClangMessage(filepath string, line int, column int, level Level, message } } -func LevelFromString(levelString string) Level { +func levelFromString(levelString string) Level { switch levelString { case "note": return NOTE @@ -66,12 +66,12 @@ func LevelFromString(levelString string) Level { } } -func is_ignored(line string) bool { +func isIgnored(line string) bool { IGNORE_REGEX := regexp.MustCompile("^error:.*$") return IGNORE_REGEX.MatchString(line) } -func parse_message(line string) ClangMessage { +func parseMessage(line string) ClangMessage { MESSAGE_REGEX := regexp.MustCompile(`^(?P.+):(?P\d+):(?P\d+): (?P\S+): (?P.*?)(?: \[(?P.*)\])?\n$`) regex_res := MESSAGE_REGEX.FindStringSubmatch(line) if len(regex_res) == 0 { @@ -80,7 +80,7 @@ func parse_message(line string) ClangMessage { filepath := regex_res[1] line, _ := strconv.Atoi(regex_res[2]) column, _ := strconv.Atoi(regex_res[3]) - level := LevelFromString(regex_res[4]) + level := levelFromString(regex_res[4]) message := regex_res[5] diagnostic_name := regex_res[6] @@ -97,7 +97,7 @@ func parse_message(line string) ClangMessage { } } -func group_messages(messages []ClangMessage) []ClangMessage { +func groupMessages(messages []ClangMessage) []ClangMessage { grouped_messages := make([]ClangMessage, 0) for _, message := range messages { if message.level == NOTE { @@ -109,26 +109,26 @@ func group_messages(messages []ClangMessage) []ClangMessage { return grouped_messages } -func convert_paths_to_relative(messages *[]ClangMessage, conf Conf) { +func convertPathsToRelative(messages *[]ClangMessage, conf Conf) { currentDir := conf.RootDir for i := range *messages { (*messages)[i].filepath, _ = filepath.Rel(currentDir, (*messages)[i].filepath) } } -func parse_lines(lines []string, conf Conf) []ClangMessage { +func ParseLines(lines []string, conf Conf) []ClangMessage { messages := make([]ClangMessage, 0) for _, line := range lines { - if is_ignored(string(line)) { + if isIgnored(string(line)) { continue } - message := parse_message(string(line)) + message := parseMessage(string(line)) if message.level == UNKNOWN && len(messages) > 0 { messages[len(messages)-1].detailsLines = append(messages[len(messages)-1].detailsLines, string(line)) } else { messages = append(messages, message) } } - convert_paths_to_relative(&messages, conf) - return group_messages(messages) + convertPathsToRelative(&messages, conf) + return groupMessages(messages) } diff --git a/internal/parsers/clangtidy/formatter.go b/internal/parsers/clangtidy/formatter.go new file mode 100644 index 0000000..5968eeb --- /dev/null +++ b/internal/parsers/clangtidy/formatter.go @@ -0,0 +1,184 @@ +// Referenced from https://github.com/yuriisk/clang-tidy-converter/blob/master/clang_tidy_converter/parser/clang_tidy_parser.py +package clangtidy + +import ( + "fmt" + "strings" +) + +type JsonMessage struct { + Type string `json:"type"` + CheckName string `json:"check_name"` + Description string `json:"description"` + Content map[string]interface{} `json:"content"` + Categories []string `json:"categories"` + Location map[string]interface{} `json:"location"` + Trace map[string]interface{} `json:"trace"` + Severity string `json:"severity"` +} + +func Format(messages []ClangMessage) []JsonMessage { + formattedMessages := make([]JsonMessage, len(messages)) + for i, message := range messages { + formattedMessages[i] = formatMessage(message) + } + return formattedMessages +} + +func formatMessage(message ClangMessage) JsonMessage { + result := JsonMessage{ + Type: "issue", + CheckName: message.diagnosticName, + Description: message.message, + Content: extractContent(message), + Categories: extractCategories(message), + Location: extractLocation(message), + Trace: extractTrace(message), + Severity: extractSeverity(message), + } + return result +} + +func messagesToText(messages []ClangMessage) []string { + textLines := []string{} + for _, message := range messages { + textLines = append(textLines, fmt.Sprintf("%s:%d:%d: %s", message.filepath, message.line, message.column, message.message)) + textLines = append(textLines, message.detailsLines...) + textLines = append(textLines, messagesToText(message.children)...) + } + return textLines +} + +func extractContent(message ClangMessage) map[string]interface{} { + detailLines := "" + for _, line := range message.detailsLines { + if line == "" { + continue + } + detailLines += (line + "\n") + } + for _, line := range messagesToText(message.children) { + if line == "" { + continue + } + detailLines += (line + "\n") + } + result := map[string]interface{}{ + "body": "```\n" + detailLines + "```", + } + return result +} + +func removeDuplicates(list []string) []string { + uniqueMap := make(map[string]bool) + for _, v := range list { + uniqueMap[v] = true + } + result := []string{} + for k := range uniqueMap { + result = append(result, k) + } + return result +} + +func extractCategories(message ClangMessage) []string { + bugriskCategory := "Bug Risk" + clarityCategory := "Clarity" + compatibilityCategory := "Compatibility" + complexityCategory := "Complexity" + duplicationCategory := "Duplication" + performanceCategory := "Performance" + securityCategory := "Security" + styleCategory := "Style" + + categories := []string{} + if strings.Contains(message.diagnosticName, "bugprone") { + categories = append(categories, bugriskCategory) + } + if strings.Contains(message.diagnosticName, "modernize") { + categories = append(categories, compatibilityCategory) + } + if strings.Contains(message.diagnosticName, "portability") { + categories = append(categories, compatibilityCategory) + } + if strings.Contains(message.diagnosticName, "performance") { + categories = append(categories, performanceCategory) + } + if strings.Contains(message.diagnosticName, "readability") { + categories = append(categories, clarityCategory) + } + if strings.Contains(message.diagnosticName, "cloexec") { + categories = append(categories, securityCategory) + } + if strings.Contains(message.diagnosticName, "security") { + categories = append(categories, securityCategory) + } + if strings.Contains(message.diagnosticName, "naming") { + categories = append(categories, styleCategory) + } + if strings.Contains(message.diagnosticName, "misc") { + categories = append(categories, styleCategory) + } + if strings.Contains(message.diagnosticName, "cppcoreguidelines") { + categories = append(categories, styleCategory) + } + if strings.Contains(message.diagnosticName, "hicpp") { + categories = append(categories, styleCategory) + } + if strings.Contains(message.diagnosticName, "simplify") { + categories = append(categories, complexityCategory) + } + if strings.Contains(message.diagnosticName, "redundant") { + categories = append(categories, duplicationCategory) + } + if strings.HasPrefix(message.diagnosticName, "boost-use-to-string") { + categories = append(categories, compatibilityCategory) + } + if len(categories) == 0 { + categories = append(categories, bugriskCategory) + } + return removeDuplicates(categories) +} + +func extractLocation(message ClangMessage) map[string]interface{} { + location := map[string]interface{}{ + "path": message.filepath, + "lines": map[string]interface{}{ + "begin": message.line, + }, + } + return location +} + +func extractOtherLocations(message ClangMessage) []map[string]interface{} { + location_list := []map[string]interface{}{} + for _, child := range message.children { + location_list = append(location_list, extractLocation(child)) + location_list = append(location_list, extractOtherLocations(child)...) + } + return location_list +} + +func extractTrace(message ClangMessage) map[string]interface{} { + result := map[string]interface{}{ + "locations": extractOtherLocations(message), + } + return result +} + +func extractSeverity(message ClangMessage) string { + switch message.level { + case NOTE: + return "info" + case REMARK: + return "minor" + case WARNING: + return "major" + case ERROR: + return "critical" + case FATAL: + return "blocker" + default: + return "unknown" + } +} diff --git a/internal/parsers/clang_tidy/meta.go b/internal/parsers/clangtidy/meta.go similarity index 74% rename from internal/parsers/clang_tidy/meta.go rename to internal/parsers/clangtidy/meta.go index ea144c0..dcf7406 100644 --- a/internal/parsers/clang_tidy/meta.go +++ b/internal/parsers/clangtidy/meta.go @@ -1,8 +1,8 @@ -package clang_tidy +package clangtidy import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" -var name = "clang-tidy" +var name = "clangtidy" func init() { stage.RegisterParser(name, &ClangTidy{}) diff --git a/internal/parsers/clang_tidy/parser.go b/internal/parsers/clangtidy/parser.go similarity index 86% rename from internal/parsers/clang_tidy/parser.go rename to internal/parsers/clangtidy/parser.go index a416b25..38940f0 100644 --- a/internal/parsers/clang_tidy/parser.go +++ b/internal/parsers/clangtidy/parser.go @@ -1,4 +1,4 @@ -package clang_tidy +package clangtidy import ( "fmt" @@ -26,8 +26,8 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { stderr := executorResult.Files["stderr"] lines := strings.SplitAfter(stdout, "\n") - messages := parse_lines(lines, conf) - formatted_messages := format(messages) + messages := ParseLines(lines, conf) + formattedMessages := Format(messages) if executorResult.Status != stage.Status(envexec.StatusAccepted) { if !((executorResult.Status == stage.Status(envexec.StatusNonzeroExitStatus)) && @@ -42,8 +42,8 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { } } return stage.ParserResult{ - Score: get_score(formatted_messages, conf), - Comment: get_comment(formatted_messages), + Score: GetScore(formattedMessages, conf), + Comment: GetComment(formattedMessages), } } diff --git a/internal/parsers/clang_tidy/score.go b/internal/parsers/clangtidy/score.go similarity index 79% rename from internal/parsers/clang_tidy/score.go rename to internal/parsers/clangtidy/score.go index 245b676..bb4c291 100644 --- a/internal/parsers/clang_tidy/score.go +++ b/internal/parsers/clangtidy/score.go @@ -1,11 +1,11 @@ -package clang_tidy +package clangtidy import ( "fmt" "strings" ) -func Contains(arr []string, element string) bool { +func contains(arr []string, element string) bool { for i := range arr { // TODO: The keyword in json report might also be an array, need to split it if strings.Contains(arr[i], element) { @@ -15,12 +15,12 @@ func Contains(arr []string, element string) bool { return false } -func get_score(json_messages []json_message, conf Conf) int { +func GetScore(json_messages []JsonMessage, conf Conf) int { fullmark := conf.Score for _, json_message := range json_messages { - keyword := json_message.Check_name + keyword := json_message.CheckName for _, match := range conf.Matches { - if Contains(match.Keyword, keyword) { + if contains(match.Keyword, keyword) { fullmark -= match.Score break } @@ -29,7 +29,7 @@ func get_score(json_messages []json_message, conf Conf) int { return fullmark } -func get_comment(json_messages []json_message) string { +func GetComment(jsonMessages []JsonMessage) string { res := "### Test results summary\n\n" keys := [...]string{ "codequality-unchecked-malloc-result", @@ -55,8 +55,8 @@ func get_comment(json_messages []json_message) string { for _, key := range keys { mapping[key] = 0 } - for _, json_message := range json_messages { - keyword := json_message.Check_name + for _, jsonMessage := range jsonMessages { + keyword := jsonMessage.CheckName flag := true for key := range mapping { if strings.Contains(keyword, key) { -- 2.30.2 From 30da9a4ebd35ffbaf074321b06df576d246d6699 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Fri, 10 May 2024 23:42:37 +0800 Subject: [PATCH 22/25] refactor(examples/clangtidy): rebase clangtidy example --- .gitmodules | 4 ++++ examples/{clang-tidy => clangtidy}/sillycode | 0 2 files changed, 4 insertions(+) rename examples/{clang-tidy => clangtidy}/sillycode (100%) diff --git a/.gitmodules b/.gitmodules index 91b7153..dd16605 100644 --- a/.gitmodules +++ b/.gitmodules @@ -30,3 +30,7 @@ path = examples/clang-tidy/sillycode url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git branch = clang-tidy/sillycode +[submodule "examples/clangtidy/sillycode"] + path = examples/clangtidy/sillycode + url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git + branch = clangtidy/sillycode diff --git a/examples/clang-tidy/sillycode b/examples/clangtidy/sillycode similarity index 100% rename from examples/clang-tidy/sillycode rename to examples/clangtidy/sillycode -- 2.30.2 From 30a891b6f6951e08d040e36d3c395664ad743eb2 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Fri, 10 May 2024 23:48:46 +0800 Subject: [PATCH 23/25] refactor(examples/keyword/clangtidy): rebase clangtidy keyword example --- .gitmodules | 12 ++++-------- examples/keyword/{clang-tidy => clangtidy}/sillycode | 0 2 files changed, 4 insertions(+), 8 deletions(-) rename examples/keyword/{clang-tidy => clangtidy}/sillycode (100%) diff --git a/.gitmodules b/.gitmodules index dd16605..71c5721 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,15 +22,11 @@ path = examples/keyword/cpplint/sillycode url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git branch = keyword/cpplint/sillycode -[submodule "examples/keyword/clang-tidy/sillycode"] - path = examples/keyword/clang-tidy/sillycode - url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git - branch = keyword/clang-tidy/sillycode -[submodule "examples/clang-tidy/sillycode"] - path = examples/clang-tidy/sillycode - url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git - branch = clang-tidy/sillycode [submodule "examples/clangtidy/sillycode"] path = examples/clangtidy/sillycode url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git branch = clangtidy/sillycode +[submodule "examples/keyword/clangtidy/sillycode"] + path = examples/keyword/clangtidy/sillycode + url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git + branch = keyword/clangtidy/sillycode diff --git a/examples/keyword/clang-tidy/sillycode b/examples/keyword/clangtidy/sillycode similarity index 100% rename from examples/keyword/clang-tidy/sillycode rename to examples/keyword/clangtidy/sillycode -- 2.30.2 From d04f83e9fc178dcf9593ace6da727cb7000a3ee0 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Fri, 10 May 2024 23:57:11 +0800 Subject: [PATCH 24/25] style(internal/parsers/clagtidy): fix more naming conventions --- internal/parsers/clangtidy/convert.go | 32 ++++++++++++------------- internal/parsers/clangtidy/formatter.go | 10 ++++---- internal/parsers/clangtidy/score.go | 6 ++--- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/internal/parsers/clangtidy/convert.go b/internal/parsers/clangtidy/convert.go index 9d829dd..2208c15 100644 --- a/internal/parsers/clangtidy/convert.go +++ b/internal/parsers/clangtidy/convert.go @@ -67,22 +67,22 @@ func levelFromString(levelString string) Level { } func isIgnored(line string) bool { - IGNORE_REGEX := regexp.MustCompile("^error:.*$") - return IGNORE_REGEX.MatchString(line) + ignore_Regex := regexp.MustCompile("^error:.*$") + return ignore_Regex.MatchString(line) } func parseMessage(line string) ClangMessage { - MESSAGE_REGEX := regexp.MustCompile(`^(?P.+):(?P\d+):(?P\d+): (?P\S+): (?P.*?)(?: \[(?P.*)\])?\n$`) - regex_res := MESSAGE_REGEX.FindStringSubmatch(line) - if len(regex_res) == 0 { + messageRegex := regexp.MustCompile(`^(?P.+):(?P\d+):(?P\d+): (?P\S+): (?P.*?)(?: \[(?P.*)\])?\n$`) + regexRes := messageRegex.FindStringSubmatch(line) + if len(regexRes) == 0 { return *newClangMessage("", 0, 0, UNKNOWN, "", "", nil, nil) } else { - filepath := regex_res[1] - line, _ := strconv.Atoi(regex_res[2]) - column, _ := strconv.Atoi(regex_res[3]) - level := levelFromString(regex_res[4]) - message := regex_res[5] - diagnostic_name := regex_res[6] + filepath := regexRes[1] + line, _ := strconv.Atoi(regexRes[2]) + column, _ := strconv.Atoi(regexRes[3]) + level := levelFromString(regexRes[4]) + message := regexRes[5] + diagnosticName := regexRes[6] return ClangMessage{ filepath: filepath, @@ -90,7 +90,7 @@ func parseMessage(line string) ClangMessage { column: column, level: level, message: message, - diagnosticName: diagnostic_name, + diagnosticName: diagnosticName, detailsLines: make([]string, 0), children: make([]ClangMessage, 0), } @@ -98,15 +98,15 @@ func parseMessage(line string) ClangMessage { } func groupMessages(messages []ClangMessage) []ClangMessage { - grouped_messages := make([]ClangMessage, 0) + groupedMessages := make([]ClangMessage, 0) for _, message := range messages { if message.level == NOTE { - grouped_messages[len(grouped_messages)-1].children = append(grouped_messages[len(grouped_messages)-1].children, message) + groupedMessages[len(groupedMessages)-1].children = append(groupedMessages[len(groupedMessages)-1].children, message) } else { - grouped_messages = append(grouped_messages, message) + groupedMessages = append(groupedMessages, message) } } - return grouped_messages + return groupedMessages } func convertPathsToRelative(messages *[]ClangMessage, conf Conf) { diff --git a/internal/parsers/clangtidy/formatter.go b/internal/parsers/clangtidy/formatter.go index 5968eeb..21bda2a 100644 --- a/internal/parsers/clangtidy/formatter.go +++ b/internal/parsers/clangtidy/formatter.go @@ -8,7 +8,7 @@ import ( type JsonMessage struct { Type string `json:"type"` - CheckName string `json:"check_name"` + CheckName string `json:"checkname"` Description string `json:"description"` Content map[string]interface{} `json:"content"` Categories []string `json:"categories"` @@ -151,12 +151,12 @@ func extractLocation(message ClangMessage) map[string]interface{} { } func extractOtherLocations(message ClangMessage) []map[string]interface{} { - location_list := []map[string]interface{}{} + locationList := []map[string]interface{}{} for _, child := range message.children { - location_list = append(location_list, extractLocation(child)) - location_list = append(location_list, extractOtherLocations(child)...) + locationList = append(locationList, extractLocation(child)) + locationList = append(locationList, extractOtherLocations(child)...) } - return location_list + return locationList } func extractTrace(message ClangMessage) map[string]interface{} { diff --git a/internal/parsers/clangtidy/score.go b/internal/parsers/clangtidy/score.go index bb4c291..f6fa39e 100644 --- a/internal/parsers/clangtidy/score.go +++ b/internal/parsers/clangtidy/score.go @@ -15,10 +15,10 @@ func contains(arr []string, element string) bool { return false } -func GetScore(json_messages []JsonMessage, conf Conf) int { +func GetScore(jsonMessages []JsonMessage, conf Conf) int { fullmark := conf.Score - for _, json_message := range json_messages { - keyword := json_message.CheckName + for _, jsonMessage := range jsonMessages { + keyword := jsonMessage.CheckName for _, match := range conf.Matches { if contains(match.Keyword, keyword) { fullmark -= match.Score -- 2.30.2 From 3aa0b2e4224138f2d5703112c480b1dc3ca3b4f1 Mon Sep 17 00:00:00 2001 From: zjc_he Date: Fri, 10 May 2024 23:59:29 +0800 Subject: [PATCH 25/25] style(internal/parsers/clangtidy/convert.go): fix more and more naming conventions --- internal/parsers/clangtidy/convert.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/parsers/clangtidy/convert.go b/internal/parsers/clangtidy/convert.go index 2208c15..ea5aa1f 100644 --- a/internal/parsers/clangtidy/convert.go +++ b/internal/parsers/clangtidy/convert.go @@ -67,8 +67,8 @@ func levelFromString(levelString string) Level { } func isIgnored(line string) bool { - ignore_Regex := regexp.MustCompile("^error:.*$") - return ignore_Regex.MatchString(line) + ignoreRegex := regexp.MustCompile("^error:.*$") + return ignoreRegex.MatchString(line) } func parseMessage(line string) ClangMessage { -- 2.30.2