Skip to content

Should go-critic climb directories looking for ruleguard rules?  #1143

@thockin

Description

@thockin

Coming back to this, I have set up a trivial demonstration of the problem(s): https://github.com/thockin/ruleguard-multi-modules

There are errors in both subdir/file.go and submod/file.go.

$ golangci-lint run
subdir/file.go:6:2: ruleguard: prefer mynet.ParseIPSloppy() (gocritic)
	net.ParseIP("foobar")
	^

but

$ golangci-lint run ./submod/
ERRO [linters context] typechecking error: main module (example.com/root) does not contain package example.com/root/submod

I know this is a problem with Go's own handling of multi-repo. Try the usual workaround:

$ cd submod/; golangci-lint run; cd - >/dev/null

No output.

$ cd submod/; golangci-lint -v  run; cd - >/dev/null
INFO [config_reader] Config search paths: [./ /home/thockin/src/go/src/github.com/thockin/ruleguard-multi-modules/submod /home/thockin/src/go/src/github.com/thockin/ruleguard-multi-modules /home/thockin/src/go/src/github.com/thockin /home/thockin/src/go/src/github.com /home/thockin/src/go/src /home/thockin/src/go /home/thockin/src /home/thockin /home /] 
INFO [config_reader] Used config file ../.golangci.yaml 
INFO [lintersdb] Active 1 linters: [gocritic]     
INFO [loader] Go packages loading at mode 575 (compiled_files|files|name|deps|exports_file|imports|types_sizes) took 70.889764ms 
INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 94.267µs 
INFO [linters context/goanalysis] analyzers took 0s with no stages 
INFO [runner] processing took 3.34µs with stages: max_same_issues: 551ns, nolint: 523ns, skip_dirs: 257ns, cgo: 241ns, skip_files: 217ns, max_from_linter: 217ns, filename_unadjuster: 212ns, diff: 143ns, path_prettifier: 135ns, identifier_marker: 131ns, uniq_by_line: 130ns, autogenerated_exclude: 129ns, exclude: 124ns, max_per_file_from_linter: 53ns, path_shortener: 51ns, source_code: 50ns, sort_results: 49ns, severity-rules: 44ns, exclude-rules: 42ns, path_prefixer: 41ns 
INFO [runner] linters took 16.305039ms with stages: gocritic: 16.238387ms 
INFO File cache stats: 0 entries of total size 0B 
INFO Memory: 2 samples, avg is 71.7MB, max is 71.8MB 
INFO Execution took 92.837517ms                   

It found the golangi-lint config in the parent dir, but not the rules file. But it didn't complain in any way, making me thing it actually passed, when it didn't.

What would you think about go-critic ascending directories, looking for the rules file?

Something like:

--- a/go-critic/go-critic/checkers/ruleguard_checker.go
+++ b/go-critic/go-critic/checkers/ruleguard_checker.go
@@ -71,14 +71,32 @@ func newRuleguardChecker(info *linter.CheckerInfo, ctx *linter.CheckerContext) (
        }
 
        loaded := 0
+       keepSearching := true
+       prefix := ""
+       for keepSearching {
+               relnames := 0
                for _, filePattern := range filePatterns {
+                       if !filepath.IsAbs(filePattern) {
+                               relnames++
+                               filePattern = prefix + filePattern
+                       }
                        filenames, err := filepath.Glob(strings.TrimSpace(filePattern))
                        if err != nil {
                                // The only possible returned error is ErrBadPattern, when pattern is malformed.
                                log.Printf("ruleguard init error: %+v", err)
+                               keepSearching = false
+                               continue
+                       }
+                       if len(filenames) > 0 {
+                               // Any match stops the search.
+                               keepSearching = false
+                       } else {
+                               // No match - ascend.
+                               prefix += "../"
                                continue
                        }
                        for _, filename := range filenames {
+                               log.Printf("ruleguard init: reading rule file %s", filename)
                                data, err := ioutil.ReadFile(filename)
                                if err != nil {
                                        if failOnErrorFlag {
@@ -97,6 +115,8 @@ func newRuleguardChecker(info *linter.CheckerInfo, ctx *linter.CheckerContext) (
                                loaded++
                        }
                }
+       }
+       log.Printf("ruleguard init: loaded %d rule files", loaded)
 
        if loaded != 0 {
                c.engine = engine

This still produces an error could not import github.com/quasilyte/go-ruleguard/dsl (can't find import: "github.com/quasilyte/go-ruleguard/dsl") but it feels like progress...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions