From 5f778a269ab01267a27c7cc136a68769fb744623 Mon Sep 17 00:00:00 2001 From: jiangpeipei327 <786865644@qq.com> Date: Tue, 6 Feb 2024 15:51:56 +0800 Subject: [PATCH 1/4] add cppcheck --- Dockerfile | 2 + config/config.yaml | 42 ++++----- internal/linters/c/cppcheck/cppcheck.go | 85 +++++++++++++++++++ internal/linters/util.go | 108 ++++++++++++++++++++++++ main.go | 1 + 5 files changed, 217 insertions(+), 21 deletions(-) create mode 100644 internal/linters/c/cppcheck/cppcheck.go create mode 100644 internal/linters/util.go diff --git a/Dockerfile b/Dockerfile index d78cdad4..342290f9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,8 @@ RUN CGO_ENABLED=0 GOOS=linux go build -o /reviewbot . # install staticcheck lint tools RUN GOPATH=/go go install honnef.co/go/tools/cmd/staticcheck@2023.1.6 +RUN apt-get update && apt-get install -y cppcheck + FROM aslan-spock-register.qiniu.io/library/ubuntu:22.04 as runner RUN apt-get update && apt-get install -y ca-certificates \ diff --git a/config/config.yaml b/config/config.yaml index 372a3b66..91c37f62 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -1,4 +1,4 @@ -# Reviewbot follows a zero-configuration approach in its design, where the default behavior implemented in the code should be suitable for the majority of scenarios. +# Reviewbot follows a zero-configuration approach in its design, where the default behavior implemented in the code should be suitable for the majority of scenarios. # Configuration of the file is only necessary in special cases, such as: # 1. Using specific commands for a particular repository. # 2. Modifying the default global configuration. @@ -11,43 +11,43 @@ customConfig: # custom config for specific orgs or repos qbox: # github organization name golangci-lint: enable: true - args: ["run", "-D", "staticcheck"] # disable staticcheck globally since we have a separate linter for it + args: ["run", "-D", "staticcheck"] # disable staticcheck globally since we have a separate linter for it - qbox/net-cache: - luacheck: + qbox/net-cache: + luacheck: enable: true workDir: "nginx" # only run in the nginx directory since there are .luacheckrc files in this directory - qbox/kodo: - staticcheck: + qbox/kodo: + staticcheck: enable: true workDir: "src/qiniu.com/kodo" # only run in the src/qiniu.com/kodo directory since this is a monorepo - # NOTE: The following is primarily for the gray test github_check_run feature and will be removed in the future. - qbox/qhr: - golangci-lint: + # NOTE: The following is primarily for the gray test github_check_run feature and will be removed in the future. + qbox/qhr: + golangci-lint: enable: true githubReportType: "github_check_run" - args: ["run", "-D", "staticcheck"] - staticcheck: + args: ["run", "-D", "staticcheck"] + staticcheck: enable: true githubReportType: "github_check_run" args: ["-debug.no-compile-errors=true", "./..."] - qbox/net-gslb: - golangci-lint: + qbox/net-gslb: + golangci-lint: enable: true githubReportType: "github_check_run" - args: ["run", "-D", "staticcheck"] - staticcheck: + args: ["run", "-D", "staticcheck"] + staticcheck: enable: true githubReportType: "github_check_run" - args: ["-debug.no-compile-errors=true", "./..."] - qbox/qtest: - golangci-lint: + args: ["-debug.no-compile-errors=true", "./..."] + qbox/qtest: + golangci-lint: enable: true githubReportType: "github_check_run" - args: ["run", "-D", "staticcheck"] - staticcheck: + args: ["run", "-D", "staticcheck"] + staticcheck: enable: true githubReportType: "github_check_run" - args: ["-debug.no-compile-errors=true", "./..."] \ No newline at end of file + args: ["-debug.no-compile-errors=true", "./..."] diff --git a/internal/linters/c/cppcheck/cppcheck.go b/internal/linters/c/cppcheck/cppcheck.go new file mode 100644 index 00000000..d466de09 --- /dev/null +++ b/internal/linters/c/cppcheck/cppcheck.go @@ -0,0 +1,85 @@ +package cppcheck + +import ( + "bytes" + "os/exec" + + "github.com/google/go-github/v57/github" + "github.com/qiniu/x/log" + "github.com/qiniu/x/xlog" + "github.com/reviewbot/config" + "github.com/reviewbot/internal/linters" +) + +var lintName = "cppcheck" + +func init() { + linters.RegisterCodeReviewHandler(lintName, cppcheckHandler) +} + +func cppcheckHandler(log *xlog.Logger, linterConfig config.Linter, agent linters.Agent, event github.PullRequestEvent) (map[string][]linters.LinterOutput, error) { + executor, err := NewCppcheckExecutor(linterConfig.WorkDir) + if err != nil { + log.Errorf("init cppcheck executor failed: %v", err) + return nil, err + } + + if linters.IsEmpty(linterConfig.Args...) { + linterConfig.Args = append([]string{}, "--quiet", "--template='{file}:{line}:{column}: {message}'", "./") + } + + output, err := executor.Run(log, linterConfig.Args...) + if err != nil { + log.Errorf("cppcheck run failed: %v", err) + return nil, err + } + + parsedOutput, err := executor.Parse(log, output) + if err != nil { + log.Errorf("cppcheck parse output failed: %v", err) + return nil, err + } + + return parsedOutput, nil +} + +// Cppcheck is an executor that knows how to execute Cppcheck commands. +type Cppcheck struct { + // dir is the location of this repo. + dir string + // cppcheck is the path to the cppcheck binary. + cppcheck string +} + +// NewCppcheckExecutor returns a new executor that knows how to execute cppcheck commands +// TODO: with config +func NewCppcheckExecutor(dir string) (linters.Linter, error) { + log.Infof("cppcheck executor init") + g, err := exec.LookPath("cppcheck") + if err != nil { + return nil, err + } + return &Cppcheck{ + dir: dir, + cppcheck: g, + }, nil +} + +func (e *Cppcheck) Run(log *xlog.Logger, args ...string) ([]byte, error) { + c := exec.Command(e.cppcheck, args...) + c.Dir = e.dir + var out bytes.Buffer + c.Stdout = &out + c.Stderr = &out + err := c.Run() + if err != nil { + log.Errorf("cppcheck run with status: %v, mark and continue", err) + } else { + log.Infof("cppcheck succeeded") + } + return out.Bytes(), nil +} + +func (e *Cppcheck) Parse(log *xlog.Logger, output []byte) (map[string][]linters.LinterOutput, error) { + return linters.FormatLinterOutput(log, output, linters.FormatLinterLine) +} diff --git a/internal/linters/util.go b/internal/linters/util.go new file mode 100644 index 00000000..6357d797 --- /dev/null +++ b/internal/linters/util.go @@ -0,0 +1,108 @@ +package linters + +import ( + "fmt" + "path/filepath" + "regexp" + "strconv" + "strings" + + "github.com/qiniu/x/log" + "github.com/qiniu/x/xlog" +) + +func IsEmpty(args ...string) bool { + for _, arg := range args { + if arg != "" { + return false + } + } + + return true +} + +type FormatLinterLineFunc func(line string) (*LinterOutput, error) + +func FormatLinterOutput(log *xlog.Logger, output []byte, FormatLinter FormatLinterLineFunc) (map[string][]LinterOutput, error) { + lines := strings.Split(string(output), "\n") + + var result = make(map[string][]LinterOutput) + for _, line := range lines { + if line == "" { + continue + } + output, err := FormatLinter(line) + if err != nil { + log.Warnf("unexpected linter check output: %v", line) + // 不直接退出 + continue + } + + if output == nil { + continue + } + + if isGopAutoGeneratedFile(output.File) { + log.Infof("skip auto generated file by go+ : %s", output.File) + continue + } + + if outs, ok := result[output.File]; !ok { + result[output.File] = []LinterOutput{*output} + } else { + // remove duplicate + var existed bool + for _, v := range outs { + if v.File == output.File && v.Line == output.Line && v.Column == output.Column && v.Message == output.Message { + existed = true + break + } + } + + if !existed { + result[output.File] = append(result[output.File], *output) + } + } + } + + return result, nil +} + +// common format LinterLine +func FormatLinterLine(line string) (*LinterOutput, error) { + pattern := `^(.*):(\d+):(\d+): (.*)$` + regex, err := regexp.Compile(pattern) + if err != nil { + log.Errorf("compile regex failed: %v", err) + return nil, err + } + matches := regex.FindStringSubmatch(line) + if len(matches) != 5 { + return nil, fmt.Errorf("unexpected format, original: %s", line) + } + + lineNumber, err := strconv.ParseInt(matches[2], 10, 64) + if err != nil { + return nil, err + } + + columnNumber, err := strconv.ParseInt(matches[3], 10, 64) + if err != nil { + return nil, err + } + + return &LinterOutput{ + File: matches[1], + Line: int(lineNumber), + Column: int(columnNumber), + Message: matches[4], + }, nil +} + +var gop_auto_generated_file_pattern = `^.*_autogen.*.go$` +var gopGeneratedFileRegexp = regexp.MustCompile(gop_auto_generated_file_pattern) + +func isGopAutoGeneratedFile(file string) bool { + // TODO: need a more accurate way to determine whether it is a go+ auto generated file + return gopGeneratedFileRegexp.MatchString(filepath.Base(file)) +} diff --git a/main.go b/main.go index 3c1ce017..c84c4d76 100644 --- a/main.go +++ b/main.go @@ -35,6 +35,7 @@ import ( _ "github.com/qiniu/reviewbot/internal/linters/go/golangci_lint" _ "github.com/qiniu/reviewbot/internal/linters/go/staticcheck" _ "github.com/qiniu/reviewbot/internal/linters/lua/luacheck" + _ "github.com/reviewbot/internal/linters/c/cppcheck" ) type options struct { From 38abe7c851bca6e45b0825b151b33fa423fa7e3d Mon Sep 17 00:00:00 2001 From: jiangpeipei327 <786865644@qq.com> Date: Fri, 15 Mar 2024 16:46:20 +0800 Subject: [PATCH 2/4] fix --- .github/workflows/go.yml | 4 +- Dockerfile | 5 +- internal/linters/c/cppcheck/README.md | 12 ++ internal/linters/c/cppcheck/cppcheck.go | 83 +++----------- internal/linters/c/cppcheck/cppcheck_test.go | 52 +++++++++ internal/linters/linters.go | 2 +- internal/linters/linters_test.go | 17 ++- .../linters/lua/luacheck/luacheck_test.go | 24 ++-- internal/linters/util.go | 108 ------------------ main.go | 2 +- 10 files changed, 108 insertions(+), 201 deletions(-) create mode 100644 internal/linters/c/cppcheck/README.md create mode 100644 internal/linters/c/cppcheck/cppcheck_test.go delete mode 100644 internal/linters/util.go diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index f03bcba8..599e840c 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -24,8 +24,8 @@ jobs: - name: Run go vet run: go vet ./... - name: Run go fmt - run: go fmt ./... + run: go fmt ./... - name: Run go test - run: go test -v ./... + run: go test -v ./... - name: Run go build run: go build ./... \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 342290f9..66f297ad 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,8 +11,6 @@ RUN CGO_ENABLED=0 GOOS=linux go build -o /reviewbot . # install staticcheck lint tools RUN GOPATH=/go go install honnef.co/go/tools/cmd/staticcheck@2023.1.6 -RUN apt-get update && apt-get install -y cppcheck - FROM aslan-spock-register.qiniu.io/library/ubuntu:22.04 as runner RUN apt-get update && apt-get install -y ca-certificates \ @@ -26,6 +24,9 @@ RUN apt-get update && apt-get install -y luarocks \ && luarocks install luacheck \ && rm -rf /var/lib/apt/lists/* +# install cppcheck lint tools +RUN apt-get update && apt-get install -y cppcheck \ + && rm -rf /var/lib/apt/lists/* # 设置golang环境 ENV GOLANG_DOWNLOAD_URL https://go.dev/dl/go1.21.5.linux-amd64.tar.gz diff --git a/internal/linters/c/cppcheck/README.md b/internal/linters/c/cppcheck/README.md new file mode 100644 index 00000000..bc2d85a2 --- /dev/null +++ b/internal/linters/c/cppcheck/README.md @@ -0,0 +1,12 @@ +# Cppcheck - A tool for static C/C++ code analysis +Syntax:
+ cppcheck [OPTIONS] [files or paths]
+If a directory is given instead of a filename, *.cpp, *.cxx, *.cc, *.c++, *.c, *.ipp, *.ixx, *.tpp, and *.txx files are checked recursively from the given directory.
+ + +Example usage in this repo:
+Recursively check the current folder, format the error messages as file name:line number:column number: warning message and don't print progress:
+cppcheck --quiet --template='{file}:{line}:{column}: {message}' .
+ +For more information:
+ https://files.cppchecksolutions.com/manual.pdf
diff --git a/internal/linters/c/cppcheck/cppcheck.go b/internal/linters/c/cppcheck/cppcheck.go index d466de09..ad8a7477 100644 --- a/internal/linters/c/cppcheck/cppcheck.go +++ b/internal/linters/c/cppcheck/cppcheck.go @@ -1,85 +1,40 @@ package cppcheck import ( - "bytes" - "os/exec" + "strings" - "github.com/google/go-github/v57/github" - "github.com/qiniu/x/log" + "github.com/qiniu/reviewbot/internal/linters" "github.com/qiniu/x/xlog" - "github.com/reviewbot/config" - "github.com/reviewbot/internal/linters" ) -var lintName = "cppcheck" +// refer to https://cppcheck.sourceforge.io/ +var linterName = "cppcheck" func init() { - linters.RegisterCodeReviewHandler(lintName, cppcheckHandler) + linters.RegisterPullRequestHandler(linterName, cppcheckHandler) } -func cppcheckHandler(log *xlog.Logger, linterConfig config.Linter, agent linters.Agent, event github.PullRequestEvent) (map[string][]linters.LinterOutput, error) { - executor, err := NewCppcheckExecutor(linterConfig.WorkDir) - if err != nil { - log.Errorf("init cppcheck executor failed: %v", err) - return nil, err - } - - if linters.IsEmpty(linterConfig.Args...) { - linterConfig.Args = append([]string{}, "--quiet", "--template='{file}:{line}:{column}: {message}'", "./") - } +func cppcheckHandler(log *xlog.Logger, a linters.Agent) error { - output, err := executor.Run(log, linterConfig.Args...) - if err != nil { - log.Errorf("cppcheck run failed: %v", err) - return nil, err - } - - parsedOutput, err := executor.Parse(log, output) - if err != nil { - log.Errorf("cppcheck parse output failed: %v", err) - return nil, err + if linters.IsEmpty(a.LinterConfig.Args...) { + a.LinterConfig.Args = append([]string{}, "--quiet", "--template='{file}:{line}:{column}: {message}'", ".") } - return parsedOutput, nil -} - -// Cppcheck is an executor that knows how to execute Cppcheck commands. -type Cppcheck struct { - // dir is the location of this repo. - dir string - // cppcheck is the path to the cppcheck binary. - cppcheck string + return linters.GeneralHandler(log, a, func(l *xlog.Logger, output []byte) (map[string][]linters.LinterOutput, error) { + return linters.Parse(log, output, cppcheckParser) + }) } -// NewCppcheckExecutor returns a new executor that knows how to execute cppcheck commands -// TODO: with config -func NewCppcheckExecutor(dir string) (linters.Linter, error) { - log.Infof("cppcheck executor init") - g, err := exec.LookPath("cppcheck") +func cppcheckParser(line string) (*linters.LinterOutput, error) { + lineResult, err := linters.GeneralLineParser(line) if err != nil { return nil, err - } - return &Cppcheck{ - dir: dir, - cppcheck: g, - }, nil -} -func (e *Cppcheck) Run(log *xlog.Logger, args ...string) ([]byte, error) { - c := exec.Command(e.cppcheck, args...) - c.Dir = e.dir - var out bytes.Buffer - c.Stdout = &out - c.Stderr = &out - err := c.Run() - if err != nil { - log.Errorf("cppcheck run with status: %v, mark and continue", err) - } else { - log.Infof("cppcheck succeeded") } - return out.Bytes(), nil -} - -func (e *Cppcheck) Parse(log *xlog.Logger, output []byte) (map[string][]linters.LinterOutput, error) { - return linters.FormatLinterOutput(log, output, linters.FormatLinterLine) + return &linters.LinterOutput{ + File: strings.TrimLeft(lineResult.File, "'"), + Line: lineResult.Line, + Column: lineResult.Column, + Message: strings.TrimRight(lineResult.Message, "'"), + }, nil } diff --git a/internal/linters/c/cppcheck/cppcheck_test.go b/internal/linters/c/cppcheck/cppcheck_test.go new file mode 100644 index 00000000..6bc9c33e --- /dev/null +++ b/internal/linters/c/cppcheck/cppcheck_test.go @@ -0,0 +1,52 @@ +package cppcheck + +import ( + "testing" + + "github.com/qiniu/reviewbot/internal/linters" +) + +func TestFormatCppCheckLine(t *testing.T) { + tc := []struct { + input string + expected *linters.LinterOutput + }{ + {"'cppcheck_test.c:6:7: Array 'a[10]' accessed at index 10, which is out of bounds.'", &linters.LinterOutput{ + File: "cppcheck_test.c", + Line: 6, + Column: 7, + Message: "Array 'a[10]' accessed at index 10, which is out of bounds.", + }}, + {"'fdk-aac-0.1.4-libMpegTPDec-src/tpdec_asc.cpp:1198:23: Variable 'bitsAvailable' is reassigned a value before the old one has been used.'", &linters.LinterOutput{ + File: "fdk-aac-0.1.4-libMpegTPDec-src/tpdec_asc.cpp", + Line: 1198, + Column: 23, + Message: "Variable 'bitsAvailable' is reassigned a value before the old one has been used.", + }}, + {"Checking test/tpdec_adts.c", nil}, + } + + for _, c := range tc { + + output, err := cppcheckParser(c.input) + + if output == nil { + if c.expected != nil { + t.Errorf("expected: %v, got: %v", c.expected, output) + } + continue + } + + if c.expected == nil && output != nil { + t.Errorf("expected error, got: %v", output) + } + + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if output.File != c.expected.File || output.Line != c.expected.Line || output.Column != c.expected.Column || output.Message != c.expected.Message { + t.Errorf("expected: %v, got: %v", c.expected, output) + } + } +} diff --git a/internal/linters/linters.go b/internal/linters/linters.go index 453dc49a..6ac9499c 100644 --- a/internal/linters/linters.go +++ b/internal/linters/linters.go @@ -139,7 +139,7 @@ func ExecRun(workDir, command string, args ...string) ([]byte, error) { c := exec.Command(g, args...) c.Dir = workDir - return c.Output() + return c.CombinedOutput() } // GeneralParse parses the output of a linter command. diff --git a/internal/linters/linters_test.go b/internal/linters/linters_test.go index 509a8e43..d75575c5 100644 --- a/internal/linters/linters_test.go +++ b/internal/linters/linters_test.go @@ -48,16 +48,6 @@ func TestFormatStaticcheckLine(t *testing.T) { for _, c := range tc { output, err := GeneralLineParser(c.input) - if c.expected == nil && output != nil { - t.Errorf("expected error, got: %v", output) - } else { - continue - } - - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if output == nil { if c.expected != nil { t.Errorf("expected: %v, got: %v", c.expected, output) @@ -65,6 +55,13 @@ func TestFormatStaticcheckLine(t *testing.T) { continue } + if c.expected == nil && output != nil { + t.Errorf("expected error, got: %v", output) + } + + if err != nil { + t.Errorf("unexpected error: %v", err) + } if output.File != c.expected.File || output.Line != c.expected.Line || output.Column != c.expected.Column || output.Message != c.expected.Message { t.Errorf("expected: %v, got: %v", c.expected, output) } diff --git a/internal/linters/lua/luacheck/luacheck_test.go b/internal/linters/lua/luacheck/luacheck_test.go index c703cb36..af116a26 100644 --- a/internal/linters/lua/luacheck/luacheck_test.go +++ b/internal/linters/lua/luacheck/luacheck_test.go @@ -28,25 +28,25 @@ func TestFormatLuaCheckLine(t *testing.T) { expected *linters.LinterOutput }{ {" video/mp4/libs/mp4lib.lua:184:11: value assigned to variable mem_data is overwritten on line 202 before use", &linters.LinterOutput{ - File: " video/mp4/libs/mp4lib.lua:184:11", + File: "video/mp4/libs/mp4lib.lua", Line: 184, Column: 11, Message: "value assigned to variable mem_data is overwritten on line 202 before use", }}, {" utils/jsonschema.lua:723:121: line is too long (142 > 120)", &linters.LinterOutput{ - File: " utils/jsonschema.lua", + File: "utils/jsonschema.lua", Line: 723, Column: 121, Message: "line is too long (142 > 120)", }}, {" utils/httpc/http_simple.lua:24:1: setting read-only global variable _VERSION", &linters.LinterOutput{ - File: " utils/httpc/http_simple.lua", + File: "utils/httpc/http_simple.lua", Line: 24, Column: 1, Message: "setting read-only global variable _VERSION", }}, {" test/qtest_access.lua:1220:1: inconsistent indentation (SPACE followed by TAB)", &linters.LinterOutput{ - File: " test/qtest_access.lua", + File: "test/qtest_access.lua", Line: 1220, Column: 1, Message: "inconsistent indentation (SPACE followed by TAB)", @@ -56,23 +56,21 @@ func TestFormatLuaCheckLine(t *testing.T) { for _, c := range tc { output, err := luacheckParser(c.input) + if output == nil { + if c.expected != nil { + t.Errorf("expected: %v, got: %v", c.expected, output) + } + continue + } + if c.expected == nil && output != nil { t.Errorf("expected error, got: %v", output) - } else { - continue } if err != nil { t.Errorf("unexpected error: %v", err) } - if output == nil { - if c.expected != nil { - t.Errorf("expected: %v, got: %v", c.expected, output) - } - continue - } - if output.File != c.expected.File || output.Line != c.expected.Line || output.Column != c.expected.Column || output.Message != c.expected.Message { t.Errorf("expected: %v, got: %v", c.expected, output) } diff --git a/internal/linters/util.go b/internal/linters/util.go deleted file mode 100644 index 6357d797..00000000 --- a/internal/linters/util.go +++ /dev/null @@ -1,108 +0,0 @@ -package linters - -import ( - "fmt" - "path/filepath" - "regexp" - "strconv" - "strings" - - "github.com/qiniu/x/log" - "github.com/qiniu/x/xlog" -) - -func IsEmpty(args ...string) bool { - for _, arg := range args { - if arg != "" { - return false - } - } - - return true -} - -type FormatLinterLineFunc func(line string) (*LinterOutput, error) - -func FormatLinterOutput(log *xlog.Logger, output []byte, FormatLinter FormatLinterLineFunc) (map[string][]LinterOutput, error) { - lines := strings.Split(string(output), "\n") - - var result = make(map[string][]LinterOutput) - for _, line := range lines { - if line == "" { - continue - } - output, err := FormatLinter(line) - if err != nil { - log.Warnf("unexpected linter check output: %v", line) - // 不直接退出 - continue - } - - if output == nil { - continue - } - - if isGopAutoGeneratedFile(output.File) { - log.Infof("skip auto generated file by go+ : %s", output.File) - continue - } - - if outs, ok := result[output.File]; !ok { - result[output.File] = []LinterOutput{*output} - } else { - // remove duplicate - var existed bool - for _, v := range outs { - if v.File == output.File && v.Line == output.Line && v.Column == output.Column && v.Message == output.Message { - existed = true - break - } - } - - if !existed { - result[output.File] = append(result[output.File], *output) - } - } - } - - return result, nil -} - -// common format LinterLine -func FormatLinterLine(line string) (*LinterOutput, error) { - pattern := `^(.*):(\d+):(\d+): (.*)$` - regex, err := regexp.Compile(pattern) - if err != nil { - log.Errorf("compile regex failed: %v", err) - return nil, err - } - matches := regex.FindStringSubmatch(line) - if len(matches) != 5 { - return nil, fmt.Errorf("unexpected format, original: %s", line) - } - - lineNumber, err := strconv.ParseInt(matches[2], 10, 64) - if err != nil { - return nil, err - } - - columnNumber, err := strconv.ParseInt(matches[3], 10, 64) - if err != nil { - return nil, err - } - - return &LinterOutput{ - File: matches[1], - Line: int(lineNumber), - Column: int(columnNumber), - Message: matches[4], - }, nil -} - -var gop_auto_generated_file_pattern = `^.*_autogen.*.go$` -var gopGeneratedFileRegexp = regexp.MustCompile(gop_auto_generated_file_pattern) - -func isGopAutoGeneratedFile(file string) bool { - // TODO: need a more accurate way to determine whether it is a go+ auto generated file - return gopGeneratedFileRegexp.MatchString(filepath.Base(file)) -} diff --git a/main.go b/main.go index c84c4d76..faaebcef 100644 --- a/main.go +++ b/main.go @@ -30,12 +30,12 @@ import ( gitv2 "k8s.io/test-infra/prow/git/v2" // linters import + _ "github.com/qiniu/reviewbot/internal/linters/c/cppcheck" _ "github.com/qiniu/reviewbot/internal/linters/git-flow/commit-check" _ "github.com/qiniu/reviewbot/internal/linters/go/gofmt" _ "github.com/qiniu/reviewbot/internal/linters/go/golangci_lint" _ "github.com/qiniu/reviewbot/internal/linters/go/staticcheck" _ "github.com/qiniu/reviewbot/internal/linters/lua/luacheck" - _ "github.com/reviewbot/internal/linters/c/cppcheck" ) type options struct { From 00e406032da3dc6918e1ffda7d73fb6cad3d7915 Mon Sep 17 00:00:00 2001 From: jiangpeipei327 <786865644@qq.com> Date: Fri, 15 Mar 2024 16:44:30 +0800 Subject: [PATCH 3/4] fix --- internal/linters/linters.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/linters/linters.go b/internal/linters/linters.go index 6ac9499c..1d0a9e62 100644 --- a/internal/linters/linters.go +++ b/internal/linters/linters.go @@ -297,6 +297,11 @@ func GeneralLineParser(line string) (*LinterOutput, error) { return nil, err } + log.Infof("file is %s", (matches[1])) + log.Info(int(lineNumber)) + log.Info(int(columnNumber)) + log.Infof("message is %s", matches[4]) + return &LinterOutput{ File: matches[1], Line: int(lineNumber), From 997b00b082b6a8a5b959ba814b62e1a822013bf8 Mon Sep 17 00:00:00 2001 From: jiangpeipei327 <786865644@qq.com> Date: Mon, 18 Mar 2024 19:00:51 +0800 Subject: [PATCH 4/4] fix --- internal/linters/c/cppcheck/README.md | 5 ++--- internal/linters/linters.go | 6 +----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/internal/linters/c/cppcheck/README.md b/internal/linters/c/cppcheck/README.md index bc2d85a2..d54c828f 100644 --- a/internal/linters/c/cppcheck/README.md +++ b/internal/linters/c/cppcheck/README.md @@ -1,10 +1,9 @@ # Cppcheck - A tool for static C/C++ code analysis +# cppcheck linter Syntax:
cppcheck [OPTIONS] [files or paths]
-If a directory is given instead of a filename, *.cpp, *.cxx, *.cc, *.c++, *.c, *.ipp, *.ixx, *.tpp, and *.txx files are checked recursively from the given directory.
- -Example usage in this repo:
+in this repo:
Recursively check the current folder, format the error messages as file name:line number:column number: warning message and don't print progress:
cppcheck --quiet --template='{file}:{line}:{column}: {message}' .
diff --git a/internal/linters/linters.go b/internal/linters/linters.go index 1d0a9e62..acc88af2 100644 --- a/internal/linters/linters.go +++ b/internal/linters/linters.go @@ -276,6 +276,7 @@ func Parse(log *xlog.Logger, output []byte, lineParser LineParser) (map[string][ // common format LinterLine func GeneralLineParser(line string) (*LinterOutput, error) { + log.Infof("line is %v", line) pattern := `^(.*):(\d+):(\d+): (.*)$` regex, err := regexp.Compile(pattern) if err != nil { @@ -297,11 +298,6 @@ func GeneralLineParser(line string) (*LinterOutput, error) { return nil, err } - log.Infof("file is %s", (matches[1])) - log.Info(int(lineNumber)) - log.Info(int(columnNumber)) - log.Infof("message is %s", matches[4]) - return &LinterOutput{ File: matches[1], Line: int(lineNumber),