From 27e76fae2ee2d84dc7db63af1d9ed7358ba35b7a Mon Sep 17 00:00:00 2001 From: Taras Madan Date: Mon, 11 Nov 2024 11:41:38 +0100 Subject: vendor: update --- vendor/github.com/mgechev/revive/config/config.go | 2 + vendor/github.com/mgechev/revive/lint/file.go | 2 +- vendor/github.com/mgechev/revive/lint/linter.go | 65 +++--- vendor/github.com/mgechev/revive/lint/name.go | 133 ++++++++++++ vendor/github.com/mgechev/revive/lint/package.go | 16 +- vendor/github.com/mgechev/revive/lint/utils.go | 133 ------------ .../github.com/mgechev/revive/rule/add-constant.go | 5 +- .../mgechev/revive/rule/argument-limit.go | 61 +++--- .../mgechev/revive/rule/blank-imports.go | 8 +- .../mgechev/revive/rule/bool-literal-in-expr.go | 1 - .../mgechev/revive/rule/cognitive-complexity.go | 22 +- .../mgechev/revive/rule/comment-spacings.go | 17 +- .../mgechev/revive/rule/comments-density.go | 3 +- .../mgechev/revive/rule/constant-logical-expr.go | 5 +- .../github.com/mgechev/revive/rule/cyclomatic.go | 58 +++--- vendor/github.com/mgechev/revive/rule/datarace.go | 4 +- vendor/github.com/mgechev/revive/rule/deep-exit.go | 5 +- vendor/github.com/mgechev/revive/rule/defer.go | 10 +- .../github.com/mgechev/revive/rule/dot-imports.go | 25 +-- .../github.com/mgechev/revive/rule/early-return.go | 12 +- .../mgechev/revive/rule/enforce-map-style.go | 5 +- .../revive/rule/enforce-repeated-arg-type-style.go | 24 +-- .../mgechev/revive/rule/enforce-slice-style.go | 17 +- vendor/github.com/mgechev/revive/rule/exported.go | 222 +++++++++++++++------ .../github.com/mgechev/revive/rule/file-header.go | 20 +- .../mgechev/revive/rule/file-length-limit.go | 138 +++++++++++++ .../mgechev/revive/rule/filename-format.go | 87 ++++++++ .../mgechev/revive/rule/function-length.go | 20 +- .../mgechev/revive/rule/function-result-limit.go | 37 ++-- .../github.com/mgechev/revive/rule/get-return.go | 22 +- .../mgechev/revive/rule/identical-branches.go | 15 +- .../mgechev/revive/rule/import-alias-naming.go | 2 +- .../mgechev/revive/rule/indent-error-flow.go | 12 +- .../mgechev/revive/rule/line-length-limit.go | 22 +- .../mgechev/revive/rule/max-control-nesting.go | 6 +- .../mgechev/revive/rule/max-public-structs.go | 24 ++- .../mgechev/revive/rule/receiver-naming.go | 62 +++++- .../mgechev/revive/rule/redefines-builtin-id.go | 57 +++++- .../mgechev/revive/rule/string-format.go | 129 ++++++------ .../github.com/mgechev/revive/rule/struct-tag.go | 46 +++-- .../mgechev/revive/rule/superfluous-else.go | 13 +- .../github.com/mgechev/revive/rule/time-equal.go | 19 +- .../github.com/mgechev/revive/rule/time-naming.go | 5 +- .../revive/rule/unchecked-type-assertion.go | 28 +-- .../mgechev/revive/rule/unconditional-recursion.go | 7 +- .../mgechev/revive/rule/unhandled-error.go | 41 ++-- vendor/github.com/mgechev/revive/rule/use-any.go | 2 +- .../mgechev/revive/rule/var-declarations.go | 16 +- .../github.com/mgechev/revive/rule/var-naming.go | 35 ++-- .../mgechev/revive/rule/waitgroup-by-value.go | 2 +- 50 files changed, 1117 insertions(+), 605 deletions(-) create mode 100644 vendor/github.com/mgechev/revive/lint/name.go delete mode 100644 vendor/github.com/mgechev/revive/lint/utils.go create mode 100644 vendor/github.com/mgechev/revive/rule/file-length-limit.go create mode 100644 vendor/github.com/mgechev/revive/rule/filename-format.go (limited to 'vendor/github.com/mgechev') diff --git a/vendor/github.com/mgechev/revive/config/config.go b/vendor/github.com/mgechev/revive/config/config.go index fed1d1913..16559f5ec 100644 --- a/vendor/github.com/mgechev/revive/config/config.go +++ b/vendor/github.com/mgechev/revive/config/config.go @@ -96,6 +96,8 @@ var allRules = append([]lint.Rule{ &rule.EnforceSliceStyleRule{}, &rule.MaxControlNestingRule{}, &rule.CommentsDensityRule{}, + &rule.FileLengthLimitRule{}, + &rule.FilenameFormatRule{}, }, defaultRules...) var allFormatters = []lint.Formatter{ diff --git a/vendor/github.com/mgechev/revive/lint/file.go b/vendor/github.com/mgechev/revive/lint/file.go index 23255304c..e34f8b7f4 100644 --- a/vendor/github.com/mgechev/revive/lint/file.go +++ b/vendor/github.com/mgechev/revive/lint/file.go @@ -188,7 +188,7 @@ func (f *File) disabledIntervals(rules []Rule, mustSpecifyDisableReason bool, fa enabledDisabledRulesMap[name] = existing } - handleRules := func(filename, modifier string, isEnabled bool, line int, ruleNames []string) []DisabledInterval { + handleRules := func(_, modifier string, isEnabled bool, line int, ruleNames []string) []DisabledInterval { var result []DisabledInterval for _, name := range ruleNames { if modifier == "line" { diff --git a/vendor/github.com/mgechev/revive/lint/linter.go b/vendor/github.com/mgechev/revive/lint/linter.go index 3c97f306f..56036e83d 100644 --- a/vendor/github.com/mgechev/revive/lint/linter.go +++ b/vendor/github.com/mgechev/revive/lint/linter.go @@ -3,11 +3,9 @@ package lint import ( "bufio" "bytes" - "encoding/json" "fmt" "go/token" "os" - "os/exec" "path/filepath" "regexp" "strconv" @@ -15,6 +13,7 @@ import ( "sync" goversion "github.com/hashicorp/go-version" + "golang.org/x/mod/modfile" ) // ReadFile defines an abstraction for reading files. @@ -55,8 +54,9 @@ func (l Linter) readFile(path string) (result []byte, err error) { } var ( - genHdr = []byte("// Code generated ") - genFtr = []byte(" DO NOT EDIT.") + genHdr = []byte("// Code generated ") + genFtr = []byte(" DO NOT EDIT.") + defaultGoVersion = goversion.Must(goversion.NewVersion("1.0")) ) // Lint lints a set of files with the specified rule. @@ -93,7 +93,9 @@ func (l *Linter) Lint(packages [][]string, ruleSet []Rule, config Config) (<-cha d, v, err := detectGoMod(dir) if err != nil { - return nil, err + // No luck finding the go.mod file thus set the default Go version + v = defaultGoVersion + d = dir } perModVersions[d] = v perPkgVersions[n] = v @@ -156,37 +158,42 @@ func (l *Linter) lintPackage(filenames []string, gover *goversion.Version, ruleS } func detectGoMod(dir string) (rootDir string, ver *goversion.Version, err error) { - // https://github.com/golang/go/issues/44753#issuecomment-790089020 - cmd := exec.Command("go", "list", "-m", "-json") - cmd.Dir = dir + modFileName, err := retrieveModFile(dir) + if err != nil { + return "", nil, fmt.Errorf("%q doesn't seem to be part of a Go module", dir) + } - out, err := cmd.Output() + mod, err := os.ReadFile(modFileName) if err != nil { - return "", nil, fmt.Errorf("command go list: %w", err) + return "", nil, fmt.Errorf("failed to read %q, got %v", modFileName, err) } - // NOTE: A package may be part of a go workspace. In this case `go list -m` - // lists all modules in the workspace, so we need to go through them all. - d := json.NewDecoder(bytes.NewBuffer(out)) - for d.More() { - var v struct { - GoMod string `json:"GoMod"` - GoVersion string `json:"GoVersion"` - Dir string `json:"Dir"` - } - if err = d.Decode(&v); err != nil { - return "", nil, err - } - if v.GoMod == "" { - return "", nil, fmt.Errorf("not part of a module: %q", dir) + modAst, err := modfile.ParseLax(modFileName, mod, nil) + if err != nil { + return "", nil, fmt.Errorf("failed to parse %q, got %v", modFileName, err) + } + + ver, err = goversion.NewVersion(modAst.Go.Version) + return filepath.Dir(modFileName), ver, err +} + +func retrieveModFile(dir string) (string, error) { + const lookingForFile = "go.mod" + for { + if dir == "." || dir == "/" { + return "", fmt.Errorf("did not found %q file", lookingForFile) } - if v.Dir != "" && strings.HasPrefix(dir, v.Dir) { - rootDir = v.Dir - ver, err = goversion.NewVersion(strings.TrimPrefix(v.GoVersion, "go")) - return rootDir, ver, err + + lookingForFilePath := filepath.Join(dir, lookingForFile) + info, err := os.Stat(lookingForFilePath) + if err != nil || info.IsDir() { + // lets check the parent dir + dir = filepath.Dir(dir) + continue } + + return lookingForFilePath, nil } - return "", nil, fmt.Errorf("not part of a module: %q", dir) } // isGenerated reports whether the source file is generated code diff --git a/vendor/github.com/mgechev/revive/lint/name.go b/vendor/github.com/mgechev/revive/lint/name.go new file mode 100644 index 000000000..6ccfb0ef2 --- /dev/null +++ b/vendor/github.com/mgechev/revive/lint/name.go @@ -0,0 +1,133 @@ +package lint + +import ( + "strings" + "unicode" +) + +// Name returns a different name if it should be different. +func Name(name string, allowlist, blocklist []string) (should string) { + // Fast path for simple cases: "_" and all lowercase. + if name == "_" { + return name + } + allLower := true + for _, r := range name { + if !unicode.IsLower(r) { + allLower = false + break + } + } + if allLower { + return name + } + + // Split camelCase at any lower->upper transition, and split on underscores. + // Check each word for common initialisms. + runes := []rune(name) + w, i := 0, 0 // index of start of word, scan + for i+1 <= len(runes) { + eow := false // whether we hit the end of a word + if i+1 == len(runes) { + eow = true + } else if runes[i+1] == '_' { + // underscore; shift the remainder forward over any run of underscores + eow = true + n := 1 + for i+n+1 < len(runes) && runes[i+n+1] == '_' { + n++ + } + + // Leave at most one underscore if the underscore is between two digits + if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) { + n-- + } + + copy(runes[i+1:], runes[i+n+1:]) + runes = runes[:len(runes)-n] + } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) { + // lower->non-lower + eow = true + } + i++ + if !eow { + continue + } + + // [w,i) is a word. + word := string(runes[w:i]) + ignoreInitWarnings := map[string]bool{} + for _, i := range allowlist { + ignoreInitWarnings[i] = true + } + + extraInits := map[string]bool{} + for _, i := range blocklist { + extraInits[i] = true + } + + if u := strings.ToUpper(word); (commonInitialisms[u] || extraInits[u]) && !ignoreInitWarnings[u] { + // Keep consistent case, which is lowercase only at the start. + if w == 0 && unicode.IsLower(runes[w]) { + u = strings.ToLower(u) + } + // Keep lowercase s for IDs + if u == "IDS" { + u = "IDs" + } + // All the common initialisms are ASCII, + // so we can replace the bytes exactly. + copy(runes[w:], []rune(u)) + } else if w > 0 && strings.ToLower(word) == word { + // already all lowercase, and not the first word, so uppercase the first character. + runes[w] = unicode.ToUpper(runes[w]) + } + w = i + } + return string(runes) +} + +// commonInitialisms is a set of common initialisms. +// Only add entries that are highly unlikely to be non-initialisms. +// For instance, "ID" is fine (Freudian code is rare), but "AND" is not. +var commonInitialisms = map[string]bool{ + "ACL": true, + "API": true, + "ASCII": true, + "CPU": true, + "CSS": true, + "DNS": true, + "EOF": true, + "GUID": true, + "HTML": true, + "HTTP": true, + "HTTPS": true, + "ID": true, + "IDS": true, + "IP": true, + "JSON": true, + "LHS": true, + "QPS": true, + "RAM": true, + "RHS": true, + "RPC": true, + "SLA": true, + "SMTP": true, + "SQL": true, + "SSH": true, + "TCP": true, + "TLS": true, + "TTL": true, + "UDP": true, + "UI": true, + "UID": true, + "UUID": true, + "URI": true, + "URL": true, + "UTF8": true, + "VM": true, + "XML": true, + "XMPP": true, + "XSRF": true, + "XSS": true, +} diff --git a/vendor/github.com/mgechev/revive/lint/package.go b/vendor/github.com/mgechev/revive/lint/package.go index b4a0a72c7..2ab035f16 100644 --- a/vendor/github.com/mgechev/revive/lint/package.go +++ b/vendor/github.com/mgechev/revive/lint/package.go @@ -33,6 +33,7 @@ var ( falseValue = 2 notSet = 3 + go121 = goversion.Must(goversion.NewVersion("1.21")) go122 = goversion.Must(goversion.NewVersion("1.22")) ) @@ -165,17 +166,17 @@ func (p *Package) scanSortable() { // bitfield for which methods exist on each type. const ( - Len = 1 << iota - Less - Swap + bfLen = 1 << iota + bfLess + bfSwap ) - nmap := map[string]int{"Len": Len, "Less": Less, "Swap": Swap} + nmap := map[string]int{"Len": bfLen, "Less": bfLess, "Swap": bfSwap} has := make(map[string]int) for _, f := range p.files { ast.Walk(&walker{nmap, has}, f.AST) } for typ, ms := range has { - if ms == Len|Less|Swap { + if ms == bfLen|bfLess|bfSwap { p.sortable[typ] = true } } @@ -194,6 +195,11 @@ func (p *Package) lint(rules []Rule, config Config, failures chan Failure) { wg.Wait() } +// IsAtLeastGo121 returns true if the Go version for this package is 1.21 or higher, false otherwise +func (p *Package) IsAtLeastGo121() bool { + return p.goVersion.GreaterThanOrEqual(go121) +} + // IsAtLeastGo122 returns true if the Go version for this package is 1.22 or higher, false otherwise func (p *Package) IsAtLeastGo122() bool { return p.goVersion.GreaterThanOrEqual(go122) diff --git a/vendor/github.com/mgechev/revive/lint/utils.go b/vendor/github.com/mgechev/revive/lint/utils.go deleted file mode 100644 index 6ccfb0ef2..000000000 --- a/vendor/github.com/mgechev/revive/lint/utils.go +++ /dev/null @@ -1,133 +0,0 @@ -package lint - -import ( - "strings" - "unicode" -) - -// Name returns a different name if it should be different. -func Name(name string, allowlist, blocklist []string) (should string) { - // Fast path for simple cases: "_" and all lowercase. - if name == "_" { - return name - } - allLower := true - for _, r := range name { - if !unicode.IsLower(r) { - allLower = false - break - } - } - if allLower { - return name - } - - // Split camelCase at any lower->upper transition, and split on underscores. - // Check each word for common initialisms. - runes := []rune(name) - w, i := 0, 0 // index of start of word, scan - for i+1 <= len(runes) { - eow := false // whether we hit the end of a word - if i+1 == len(runes) { - eow = true - } else if runes[i+1] == '_' { - // underscore; shift the remainder forward over any run of underscores - eow = true - n := 1 - for i+n+1 < len(runes) && runes[i+n+1] == '_' { - n++ - } - - // Leave at most one underscore if the underscore is between two digits - if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) { - n-- - } - - copy(runes[i+1:], runes[i+n+1:]) - runes = runes[:len(runes)-n] - } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) { - // lower->non-lower - eow = true - } - i++ - if !eow { - continue - } - - // [w,i) is a word. - word := string(runes[w:i]) - ignoreInitWarnings := map[string]bool{} - for _, i := range allowlist { - ignoreInitWarnings[i] = true - } - - extraInits := map[string]bool{} - for _, i := range blocklist { - extraInits[i] = true - } - - if u := strings.ToUpper(word); (commonInitialisms[u] || extraInits[u]) && !ignoreInitWarnings[u] { - // Keep consistent case, which is lowercase only at the start. - if w == 0 && unicode.IsLower(runes[w]) { - u = strings.ToLower(u) - } - // Keep lowercase s for IDs - if u == "IDS" { - u = "IDs" - } - // All the common initialisms are ASCII, - // so we can replace the bytes exactly. - copy(runes[w:], []rune(u)) - } else if w > 0 && strings.ToLower(word) == word { - // already all lowercase, and not the first word, so uppercase the first character. - runes[w] = unicode.ToUpper(runes[w]) - } - w = i - } - return string(runes) -} - -// commonInitialisms is a set of common initialisms. -// Only add entries that are highly unlikely to be non-initialisms. -// For instance, "ID" is fine (Freudian code is rare), but "AND" is not. -var commonInitialisms = map[string]bool{ - "ACL": true, - "API": true, - "ASCII": true, - "CPU": true, - "CSS": true, - "DNS": true, - "EOF": true, - "GUID": true, - "HTML": true, - "HTTP": true, - "HTTPS": true, - "ID": true, - "IDS": true, - "IP": true, - "JSON": true, - "LHS": true, - "QPS": true, - "RAM": true, - "RHS": true, - "RPC": true, - "SLA": true, - "SMTP": true, - "SQL": true, - "SSH": true, - "TCP": true, - "TLS": true, - "TTL": true, - "UDP": true, - "UI": true, - "UID": true, - "UUID": true, - "URI": true, - "URL": true, - "UTF8": true, - "VM": true, - "XML": true, - "XMPP": true, - "XSRF": true, - "XSS": true, -} diff --git a/vendor/github.com/mgechev/revive/rule/add-constant.go b/vendor/github.com/mgechev/revive/rule/add-constant.go index 73dfa932c..233f1d848 100644 --- a/vendor/github.com/mgechev/revive/rule/add-constant.go +++ b/vendor/github.com/mgechev/revive/rule/add-constant.go @@ -160,12 +160,15 @@ func (w *lintAddConstantRule) isIgnoredFunc(fName string) bool { } func (w *lintAddConstantRule) checkStrLit(n *ast.BasicLit) { + const ignoreMarker = -1 + if w.allowList[kindSTRING][n.Value] { return } count := w.strLits[n.Value] - if count >= 0 { + mustCheck := count > ignoreMarker + if mustCheck { w.strLits[n.Value] = count + 1 if w.strLits[n.Value] > w.strLitLimit { w.onFailure(lint.Failure{ diff --git a/vendor/github.com/mgechev/revive/rule/argument-limit.go b/vendor/github.com/mgechev/revive/rule/argument-limit.go index 8120288fd..b6ce0e81a 100644 --- a/vendor/github.com/mgechev/revive/rule/argument-limit.go +++ b/vendor/github.com/mgechev/revive/rule/argument-limit.go @@ -10,7 +10,7 @@ import ( // ArgumentsLimitRule lints given else constructs. type ArgumentsLimitRule struct { - total int + max int sync.Mutex } @@ -19,18 +19,20 @@ const defaultArgumentsLimit = 8 func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() - if r.total == 0 { - if len(arguments) < 1 { - r.total = defaultArgumentsLimit - return - } + if r.max != 0 { + return + } - total, ok := arguments[0].(int64) // Alt. non panicking version - if !ok { - panic(`invalid value passed as argument number to the "argument-limit" rule`) - } - r.total = int(total) + if len(arguments) < 1 { + r.max = defaultArgumentsLimit + return } + + maxArguments, ok := arguments[0].(int64) // Alt. non panicking version + if !ok { + panic(`invalid value passed as argument number to the "argument-limit" rule`) + } + r.max = int(maxArguments) } // Apply applies the rule to given file. @@ -43,7 +45,7 @@ func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) [] } walker := lintArgsNum{ - total: r.total, + max: r.max, onFailure: onFailure, } @@ -58,27 +60,30 @@ func (*ArgumentsLimitRule) Name() string { } type lintArgsNum struct { - total int + max int onFailure func(lint.Failure) } func (w lintArgsNum) Visit(n ast.Node) ast.Visitor { node, ok := n.(*ast.FuncDecl) - if ok { - num := 0 - for _, l := range node.Type.Params.List { - for range l.Names { - num++ - } - } - if num > w.total { - w.onFailure(lint.Failure{ - Confidence: 1, - Failure: fmt.Sprintf("maximum number of arguments per function exceeded; max %d but got %d", w.total, num), - Node: node.Type, - }) - return w + if !ok { + return w + } + + num := 0 + for _, l := range node.Type.Params.List { + for range l.Names { + num++ } } - return w + + if num > w.max { + w.onFailure(lint.Failure{ + Confidence: 1, + Failure: fmt.Sprintf("maximum number of arguments per function exceeded; max %d but got %d", w.max, num), + Node: node.Type, + }) + } + + return nil // skip visiting the body of the function } diff --git a/vendor/github.com/mgechev/revive/rule/blank-imports.go b/vendor/github.com/mgechev/revive/rule/blank-imports.go index a3d50b4f7..0ddb4aad2 100644 --- a/vendor/github.com/mgechev/revive/rule/blank-imports.go +++ b/vendor/github.com/mgechev/revive/rule/blank-imports.go @@ -22,9 +22,8 @@ func (r *BlankImportsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failu } const ( - message = "a blank import should be only in a main or test package, or have a comment justifying it" - category = "imports" - + message = "a blank import should be only in a main or test package, or have a comment justifying it" + category = "imports" embedImportPath = `"embed"` ) @@ -39,7 +38,8 @@ func (r *BlankImportsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failu continue // Ignore non-blank imports. } - if i > 0 { + isNotFirstElement := i > 0 + if isNotFirstElement { prev := file.AST.Imports[i-1] prevPos := file.ToPosition(prev.Pos()) diff --git a/vendor/github.com/mgechev/revive/rule/bool-literal-in-expr.go b/vendor/github.com/mgechev/revive/rule/bool-literal-in-expr.go index d6150339b..71551e55a 100644 --- a/vendor/github.com/mgechev/revive/rule/bool-literal-in-expr.go +++ b/vendor/github.com/mgechev/revive/rule/bool-literal-in-expr.go @@ -45,7 +45,6 @@ func (w *lintBoolLiteral) Visit(node ast.Node) ast.Visitor { lexeme, ok := isExprABooleanLit(n.X) if !ok { lexeme, ok = isExprABooleanLit(n.Y) - if !ok { return w } diff --git a/vendor/github.com/mgechev/revive/rule/cognitive-complexity.go b/vendor/github.com/mgechev/revive/rule/cognitive-complexity.go index 1973faef8..83640fd3d 100644 --- a/vendor/github.com/mgechev/revive/rule/cognitive-complexity.go +++ b/vendor/github.com/mgechev/revive/rule/cognitive-complexity.go @@ -21,19 +21,21 @@ const defaultMaxCognitiveComplexity = 7 func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() - if r.maxComplexity == 0 { + if r.maxComplexity != 0 { + return // already configured + } - if len(arguments) < 1 { - r.maxComplexity = defaultMaxCognitiveComplexity - return - } + if len(arguments) < 1 { + r.maxComplexity = defaultMaxCognitiveComplexity + return + } - complexity, ok := arguments[0].(int64) - if !ok { - panic(fmt.Sprintf("invalid argument type for cognitive-complexity, expected int64, got %T", arguments[0])) - } - r.maxComplexity = int(complexity) + complexity, ok := arguments[0].(int64) + if !ok { + panic(fmt.Sprintf("invalid argument type for cognitive-complexity, expected int64, got %T", arguments[0])) } + + r.maxComplexity = int(complexity) } // Apply applies the rule to given file. diff --git a/vendor/github.com/mgechev/revive/rule/comment-spacings.go b/vendor/github.com/mgechev/revive/rule/comment-spacings.go index bfb7eaf23..f72151301 100644 --- a/vendor/github.com/mgechev/revive/rule/comment-spacings.go +++ b/vendor/github.com/mgechev/revive/rule/comment-spacings.go @@ -18,16 +18,17 @@ type CommentSpacingsRule struct { func (r *CommentSpacingsRule) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() + if r.allowList != nil { + return // already configured + } - if r.allowList == nil { - r.allowList = []string{} - for _, arg := range arguments { - allow, ok := arg.(string) // Alt. non panicking version - if !ok { - panic(fmt.Sprintf("invalid argument %v for %s; expected string but got %T", arg, r.Name(), arg)) - } - r.allowList = append(r.allowList, `//`+allow) + r.allowList = []string{} + for _, arg := range arguments { + allow, ok := arg.(string) // Alt. non panicking version + if !ok { + panic(fmt.Sprintf("invalid argument %v for %s; expected string but got %T", arg, r.Name(), arg)) } + r.allowList = append(r.allowList, `//`+allow) } } diff --git a/vendor/github.com/mgechev/revive/rule/comments-density.go b/vendor/github.com/mgechev/revive/rule/comments-density.go index 5956fea23..c5298ea07 100644 --- a/vendor/github.com/mgechev/revive/rule/comments-density.go +++ b/vendor/github.com/mgechev/revive/rule/comments-density.go @@ -53,7 +53,8 @@ func (r *CommentsDensityRule) Apply(file *lint.File, arguments lint.Arguments) [ { Node: file.AST, Confidence: 1, - Failure: fmt.Sprintf("the file has a comment density of %2.f%% (%d comment lines for %d code lines) but expected a minimum of %d%%", density, commentsLines, statementsCount, r.minimumCommentsDensity), + Failure: fmt.Sprintf("the file has a comment density of %2.f%% (%d comment lines for %d code lines) but expected a minimum of %d%%", + density, commentsLines, statementsCount, r.minimumCommentsDensity), }, } } diff --git a/vendor/github.com/mgechev/revive/rule/constant-logical-expr.go b/vendor/github.com/mgechev/revive/rule/constant-logical-expr.go index 36cd641f7..9e34d3d16 100644 --- a/vendor/github.com/mgechev/revive/rule/constant-logical-expr.go +++ b/vendor/github.com/mgechev/revive/rule/constant-logical-expr.go @@ -41,8 +41,9 @@ func (w *lintConstantLogicalExpr) Visit(node ast.Node) ast.Visitor { return w } - if gofmt(n.X) != gofmt(n.Y) { // check if subexpressions are the same - return w + subExpressionsAreNotEqual := gofmt(n.X) != gofmt(n.Y) + if subExpressionsAreNotEqual { + return w // nothing to say } // Handles cases like: a <= a, a == a, a >= a diff --git a/vendor/github.com/mgechev/revive/rule/cyclomatic.go b/vendor/github.com/mgechev/revive/rule/cyclomatic.go index 9f6d50043..10413de24 100644 --- a/vendor/github.com/mgechev/revive/rule/cyclomatic.go +++ b/vendor/github.com/mgechev/revive/rule/cyclomatic.go @@ -22,18 +22,20 @@ const defaultMaxCyclomaticComplexity = 10 func (r *CyclomaticRule) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() - if r.maxComplexity == 0 { - if len(arguments) < 1 { - r.maxComplexity = defaultMaxCyclomaticComplexity - return - } + if r.maxComplexity != 0 { + return // already configured + } - complexity, ok := arguments[0].(int64) // Alt. non panicking version - if !ok { - panic(fmt.Sprintf("invalid argument for cyclomatic complexity; expected int but got %T", arguments[0])) - } - r.maxComplexity = int(complexity) + if len(arguments) < 1 { + r.maxComplexity = defaultMaxCyclomaticComplexity + return + } + + complexity, ok := arguments[0].(int64) // Alt. non panicking version + if !ok { + panic(fmt.Sprintf("invalid argument for cyclomatic complexity; expected int but got %T", arguments[0])) } + r.maxComplexity = int(complexity) } // Apply applies the rule to given file. @@ -70,31 +72,35 @@ type lintCyclomatic struct { func (w lintCyclomatic) Visit(_ ast.Node) ast.Visitor { f := w.file for _, decl := range f.AST.Decls { - if fn, ok := decl.(*ast.FuncDecl); ok { - c := complexity(fn) - if c > w.complexity { - w.onFailure(lint.Failure{ - Confidence: 1, - Category: "maintenance", - Failure: fmt.Sprintf("function %s has cyclomatic complexity %d (> max enabled %d)", - funcName(fn), c, w.complexity), - Node: fn, - }) - } + fn, ok := decl.(*ast.FuncDecl) + if !ok { + continue + } + + c := complexity(fn) + if c > w.complexity { + w.onFailure(lint.Failure{ + Confidence: 1, + Category: "maintenance", + Failure: fmt.Sprintf("function %s has cyclomatic complexity %d (> max enabled %d)", + funcName(fn), c, w.complexity), + Node: fn, + }) } } + return nil } // funcName returns the name representation of a function or method: // "(Type).Name" for methods or simply "Name" for functions. func funcName(fn *ast.FuncDecl) string { - if fn.Recv != nil { - if fn.Recv.NumFields() > 0 { - typ := fn.Recv.List[0].Type - return fmt.Sprintf("(%s).%s", recvString(typ), fn.Name) - } + declarationHasReceiver := fn.Recv != nil && fn.Recv.NumFields() > 0 + if declarationHasReceiver { + typ := fn.Recv.List[0].Type + return fmt.Sprintf("(%s).%s", recvString(typ), fn.Name) } + return fn.Name.Name } diff --git a/vendor/github.com/mgechev/revive/rule/datarace.go b/vendor/github.com/mgechev/revive/rule/datarace.go index 86ec6e113..21a7a706e 100644 --- a/vendor/github.com/mgechev/revive/rule/datarace.go +++ b/vendor/github.com/mgechev/revive/rule/datarace.go @@ -80,7 +80,7 @@ func (w lintFunctionForDataRaces) Visit(node ast.Node) ast.Visitor { return nil } - getIds := func(exprs ...ast.Expr) []*ast.Ident { + getIDs := func(exprs ...ast.Expr) []*ast.Ident { r := []*ast.Ident{} for _, expr := range exprs { if id, ok := expr.(*ast.Ident); ok { @@ -90,7 +90,7 @@ func (w lintFunctionForDataRaces) Visit(node ast.Node) ast.Visitor { return r } - ids := getIds(n.Key, n.Value) + ids := getIDs(n.Key, n.Value) for _, id := range ids { w.rangeIDs[id.Obj] = struct{}{} } diff --git a/vendor/github.com/mgechev/revive/rule/deep-exit.go b/vendor/github.com/mgechev/revive/rule/deep-exit.go index 918d4294a..7b3dd0f82 100644 --- a/vendor/github.com/mgechev/revive/rule/deep-exit.go +++ b/vendor/github.com/mgechev/revive/rule/deep-exit.go @@ -73,9 +73,10 @@ func (w lintDeepExit) Visit(node ast.Node) ast.Visitor { return w } - fn := fc.Sel.Name pkg := id.Name - if w.exitFunctions[pkg] != nil && w.exitFunctions[pkg][fn] { // it's a call to an exit function + fn := fc.Sel.Name + isACallToExitFunction := w.exitFunctions[pkg] != nil && w.exitFunctions[pkg][fn] + if isACallToExitFunction { w.onFailure(lint.Failure{ Confidence: 1, Node: ce, diff --git a/vendor/github.com/mgechev/revive/rule/defer.go b/vendor/github.com/mgechev/revive/rule/defer.go index adc6478ae..3c31d507b 100644 --- a/vendor/github.com/mgechev/revive/rule/defer.go +++ b/vendor/github.com/mgechev/revive/rule/defer.go @@ -16,10 +16,12 @@ type DeferRule struct { func (r *DeferRule) configure(arguments lint.Arguments) { r.Lock() - if r.allow == nil { - r.allow = r.allowFromArgs(arguments) + defer r.Unlock() + if r.allow != nil { + return // already configured } - r.Unlock() + + r.allow = r.allowFromArgs(arguments) } // Apply applies the rule to given file. @@ -111,7 +113,7 @@ func (w lintDeferRule) Visit(node ast.Node) ast.Visitor { // but it is very likely to be a misunderstanding of defer's behavior around arguments. w.newFailure("recover must be called inside a deferred function, this is executing recover immediately", n, 1, "logic", "immediate-recover") } - + return nil // no need to analyze the arguments of the function call case *ast.DeferStmt: if isIdent(n.Call.Fun, "recover") { // defer recover() diff --git a/vendor/github.com/mgechev/revive/rule/dot-imports.go b/vendor/github.com/mgechev/revive/rule/dot-imports.go index 6b877677d..df0b2a7f4 100644 --- a/vendor/github.com/mgechev/revive/rule/dot-imports.go +++ b/vendor/github.com/mgechev/revive/rule/dot-imports.go @@ -59,17 +59,17 @@ func (r *DotImportsRule) configure(arguments lint.Arguments) { } if allowedPkgArg, ok := args["allowedPackages"]; ok { - if pkgs, ok := allowedPkgArg.([]any); ok { - for _, p := range pkgs { - if pkg, ok := p.(string); ok { - r.allowedPackages.add(pkg) - } else { - panic(fmt.Sprintf("Invalid argument to the dot-imports rule, string expected. Got '%v' (%T)", p, p)) - } - } - } else { + pkgs, ok := allowedPkgArg.([]any) + if !ok { panic(fmt.Sprintf("Invalid argument to the dot-imports rule, []string expected. Got '%v' (%T)", allowedPkgArg, allowedPkgArg)) } + for _, p := range pkgs { + pkg, ok := p.(string) + if !ok { + panic(fmt.Sprintf("Invalid argument to the dot-imports rule, string expected. Got '%v' (%T)", p, p)) + } + r.allowedPackages.add(pkg) + } } } @@ -81,12 +81,13 @@ type lintImports struct { } func (w lintImports) Visit(_ ast.Node) ast.Visitor { - for _, is := range w.fileAst.Imports { - if is.Name != nil && is.Name.Name == "." && !w.allowPackages.isAllowedPackage(is.Path.Value) { + for _, importSpec := range w.fileAst.Imports { + isDotImport := importSpec.Name != nil && importSpec.Name.Name == "." + if isDotImport && !w.allowPackages.isAllowedPackage(importSpec.Path.Value) { w.onFailure(lint.Failure{ Confidence: 1, Failure: "should not use dot imports", - Node: is, + Node: importSpec, Category: "imports", }) } diff --git a/vendor/github.com/mgechev/revive/rule/early-return.go b/vendor/github.com/mgechev/revive/rule/early-return.go index 9c04a1dbe..62d491f27 100644 --- a/vendor/github.com/mgechev/revive/rule/early-return.go +++ b/vendor/github.com/mgechev/revive/rule/early-return.go @@ -21,27 +21,27 @@ func (*EarlyReturnRule) Name() string { return "early-return" } -// CheckIfElse evaluates the rule against an ifelse.Chain. -func (*EarlyReturnRule) CheckIfElse(chain ifelse.Chain, args ifelse.Args) (failMsg string) { +// CheckIfElse evaluates the rule against an ifelse.Chain and returns a failure message if applicable. +func (*EarlyReturnRule) CheckIfElse(chain ifelse.Chain, args ifelse.Args) string { if !chain.Else.Deviates() { // this rule only applies if the else-block deviates control flow - return + return "" } if chain.HasPriorNonDeviating && !chain.If.IsEmpty() { // if we de-indent this block then a previous branch // might flow into it, affecting program behaviour - return + return "" } if chain.If.Deviates() { // avoid overlapping with superfluous-else - return + return "" } if args.PreserveScope && !chain.AtBlockEnd && (chain.HasInitializer || chain.If.HasDecls) { // avoid increasing variable scope - return + return "" } if chain.If.IsEmpty() { diff --git a/vendor/github.com/mgechev/revive/rule/enforce-map-style.go b/vendor/github.com/mgechev/revive/rule/enforce-map-style.go index 36ac2374c..c698c40ed 100644 --- a/vendor/github.com/mgechev/revive/rule/enforce-map-style.go +++ b/vendor/github.com/mgechev/revive/rule/enforce-map-style.go @@ -65,7 +65,6 @@ func (r *EnforceMapStyleRule) configure(arguments lint.Arguments) { var err error r.enforceMapStyle, err = mapStyleFromString(enforceMapStyle) - if err != nil { panic(fmt.Sprintf("Invalid argument to the enforce-map-style rule: %v", err)) } @@ -94,8 +93,8 @@ func (r *EnforceMapStyleRule) Apply(file *lint.File, arguments lint.Arguments) [ return true } - if len(v.Elts) > 0 { - // not an empty map + isEmptyMap := len(v.Elts) > 0 + if isEmptyMap { return true } diff --git a/vendor/github.com/mgechev/revive/rule/enforce-repeated-arg-type-style.go b/vendor/github.com/mgechev/revive/rule/enforce-repeated-arg-type-style.go index 067082b1b..a435ee186 100644 --- a/vendor/github.com/mgechev/revive/rule/enforce-repeated-arg-type-style.go +++ b/vendor/github.com/mgechev/revive/rule/enforce-repeated-arg-type-style.go @@ -3,7 +3,6 @@ package rule import ( "fmt" "go/ast" - "go/types" "sync" "github.com/mgechev/revive/lint" @@ -104,13 +103,6 @@ func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, arguments lint. var failures []lint.Failure - err := file.Pkg.TypeCheck() - if err != nil { - // the file has other issues - return nil - } - typesInfo := file.Pkg.TypesInfo() - astFile := file.AST ast.Inspect(astFile, func(n ast.Node) bool { switch fn := n.(type) { @@ -134,12 +126,14 @@ func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, arguments lint. var prevType ast.Expr if fn.Type.Params != nil { for _, field := range fn.Type.Params.List { - if types.Identical(typesInfo.Types[field.Type].Type, typesInfo.Types[prevType].Type) { + prevTypeStr := gofmt(prevType) + currentTypeStr := gofmt(field.Type) + if currentTypeStr == prevTypeStr { failures = append(failures, lint.Failure{ Confidence: 1, - Node: field, + Node: prevType, Category: "style", - Failure: "repeated argument type can be omitted", + Failure: fmt.Sprintf("repeated argument type %q can be omitted", prevTypeStr), }) } prevType = field.Type @@ -166,12 +160,14 @@ func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, arguments lint. var prevType ast.Expr if fn.Type.Results != nil { for _, field := range fn.Type.Results.List { - if field.Names != nil && types.Identical(typesInfo.Types[field.Type].Type, typesInfo.Types[prevType].Type) { + prevTypeStr := gofmt(prevType) + currentTypeStr := gofmt(field.Type) + if field.Names != nil && currentTypeStr == prevTypeStr { failures = append(failures, lint.Failure{ Confidence: 1, - Node: field, + Node: prevType, Category: "style", - Failure: "repeated return type can be omitted", + Failure: fmt.Sprintf("repeated return type %q can be omitted", prevTypeStr), }) } prevType = field.Type diff --git a/vendor/github.com/mgechev/revive/rule/enforce-slice-style.go b/vendor/github.com/mgechev/revive/rule/enforce-slice-style.go index 60d8ac066..14be25893 100644 --- a/vendor/github.com/mgechev/revive/rule/enforce-slice-style.go +++ b/vendor/github.com/mgechev/revive/rule/enforce-slice-style.go @@ -69,7 +69,6 @@ func (r *EnforceSliceStyleRule) configure(arguments lint.Arguments) { var err error r.enforceSliceStyle, err = sliceStyleFromString(enforceSliceStyle) - if err != nil { panic(fmt.Sprintf("Invalid argument to the enforce-slice-style rule: %v", err)) } @@ -101,8 +100,8 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments) return true } - if len(v.Elts) > 0 { - // not an empty slice + isNotEmptySlice := len(v.Elts) > 0 + if isNotEmptySlice { return true } @@ -132,8 +131,8 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments) return true } - if len(v.Args) < 2 { - // skip invalid make declarations + isInvalidMakeDeclaration := len(v.Args) < 2 + if isInvalidMakeDeclaration { return true } @@ -148,8 +147,8 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments) return true } - if arg.Value != "0" { - // skip slice with non-zero size + isSliceSizeNotZero := arg.Value != "0" + if isSliceSizeNotZero { return true } @@ -160,8 +159,8 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments) return true } - if arg.Value != "0" { - // skip non-zero capacity slice + isNonZeroCapacitySlice := arg.Value != "0" + if isNonZeroCapacitySlice { return true } } diff --git a/vendor/github.com/mgechev/revive/rule/exported.go b/vendor/github.com/mgechev/revive/rule/exported.go index b8663c48c..e3972d40e 100644 --- a/vendor/github.com/mgechev/revive/rule/exported.go +++ b/vendor/github.com/mgechev/revive/rule/exported.go @@ -13,28 +13,93 @@ import ( "github.com/mgechev/revive/lint" ) +// disabledChecks store ignored warnings types +type disabledChecks struct { + Const bool + Function bool + Method bool + PrivateReceivers bool + PublicInterfaces bool + Stuttering bool + Type bool + Var bool +} + +const checkNamePrivateReceivers = "privateReceivers" +const checkNamePublicInterfaces = "publicInterfaces" +const checkNameStuttering = "stuttering" + +// isDisabled returns true if the given check is disabled, false otherwise +func (dc *disabledChecks) isDisabled(checkName string) bool { + switch checkName { + case "var": + return dc.Var + case "const": + return dc.Const + case "function": + return dc.Function + case "method": + return dc.Method + case checkNamePrivateReceivers: + return dc.PrivateReceivers + case checkNamePublicInterfaces: + return dc.PublicInterfaces + case checkNameStuttering: + return dc.Stuttering + case "type": + return dc.Type + default: + return false + } +} + // ExportedRule lints given else constructs. type ExportedRule struct { - configured bool - checkPrivateReceivers bool - disableStutteringCheck bool - stuttersMsg string + configured bool + stuttersMsg string + disabledChecks disabledChecks sync.Mutex } func (r *ExportedRule) configure(arguments lint.Arguments) { r.Lock() - if !r.configured { - var sayRepetitiveInsteadOfStutters bool - r.checkPrivateReceivers, r.disableStutteringCheck, sayRepetitiveInsteadOfStutters = r.getConf(arguments) - r.stuttersMsg = "stutters" - if sayRepetitiveInsteadOfStutters { - r.stuttersMsg = "is repetitive" - } + defer r.Unlock() + if r.configured { + return + } + r.configured = true - r.configured = true + r.disabledChecks = disabledChecks{PrivateReceivers: true, PublicInterfaces: true} + r.stuttersMsg = "stutters" + for _, flag := range arguments { + switch flag := flag.(type) { + case string: + switch flag { + case "checkPrivateReceivers": + r.disabledChecks.PrivateReceivers = false + case "disableStutteringCheck": + r.disabledChecks.Stuttering = true + case "sayRepetitiveInsteadOfStutters": + r.stuttersMsg = "is repetitive" + case "checkPublicInterface": + r.disabledChecks.PublicInterfaces = false + case "disableChecksOnConstants": + r.disabledChecks.Const = true + case "disableChecksOnFunctions": + r.disabledChecks.Function = true + case "disableChecksOnMethods": + r.disabledChecks.Method = true + case "disableChecksOnTypes": + r.disabledChecks.Type = true + case "disableChecksOnVariables": + r.disabledChecks.Var = true + default: + panic(fmt.Sprintf("Unknown configuration flag %s for %s rule", flag, r.Name())) + } + default: + panic(fmt.Sprintf("Invalid argument for the %s rule: expecting a string, got %T", r.Name(), flag)) + } } - r.Unlock() } // Apply applies the rule to given file. @@ -55,9 +120,8 @@ func (r *ExportedRule) Apply(file *lint.File, args lint.Arguments) []lint.Failur failures = append(failures, failure) }, genDeclMissingComments: make(map[*ast.GenDecl]bool), - checkPrivateReceivers: r.checkPrivateReceivers, - disableStutteringCheck: r.disableStutteringCheck, stuttersMsg: r.stuttersMsg, + disabledChecks: r.disabledChecks, } ast.Walk(&walker, fileAst) @@ -70,61 +134,36 @@ func (*ExportedRule) Name() string { return "exported" } -func (r *ExportedRule) getConf(args lint.Arguments) (checkPrivateReceivers, disableStutteringCheck, sayRepetitiveInsteadOfStutters bool) { - // if any, we expect a slice of strings as configuration - if len(args) < 1 { - return - } - for _, flag := range args { - flagStr, ok := flag.(string) - if !ok { - panic(fmt.Sprintf("Invalid argument for the %s rule: expecting a string, got %T", r.Name(), flag)) - } - - switch flagStr { - case "checkPrivateReceivers": - checkPrivateReceivers = true - case "disableStutteringCheck": - disableStutteringCheck = true - case "sayRepetitiveInsteadOfStutters": - sayRepetitiveInsteadOfStutters = true - default: - panic(fmt.Sprintf("Unknown configuration flag %s for %s rule", flagStr, r.Name())) - } - } - - return -} - type lintExported struct { file *lint.File fileAst *ast.File lastGen *ast.GenDecl genDeclMissingComments map[*ast.GenDecl]bool onFailure func(lint.Failure) - checkPrivateReceivers bool - disableStutteringCheck bool stuttersMsg string + disabledChecks disabledChecks } func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) { if !ast.IsExported(fn.Name.Name) { - // func is unexported - return + return // func is unexported, nothing to do } + kind := "function" name := fn.Name.Name - if fn.Recv != nil && len(fn.Recv.List) > 0 { - // method + isMethod := fn.Recv != nil && len(fn.Recv.List) > 0 + if isMethod { kind = "method" recv := typeparams.ReceiverType(fn) - if !w.checkPrivateReceivers && !ast.IsExported(recv) { - // receiver is unexported + + if !ast.IsExported(recv) && w.disabledChecks.PrivateReceivers { return } + if commonMethods[name] { return } + switch name { case "Len", "Less", "Swap": sortables := w.file.Pkg.Sortable() @@ -134,6 +173,11 @@ func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) { } name = recv + "." + name } + + if w.disabledChecks.isDisabled(kind) { + return + } + if fn.Doc == nil { w.onFailure(lint.Failure{ Node: fn, @@ -143,6 +187,7 @@ func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) { }) return } + s := normalizeText(fn.Doc.Text()) prefix := fn.Name.Name + " " if !strings.HasPrefix(s, prefix) { @@ -156,7 +201,7 @@ func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) { } func (w *lintExported) checkStutter(id *ast.Ident, thing string) { - if w.disableStutteringCheck { + if w.disabledChecks.Stuttering { return } @@ -190,9 +235,14 @@ func (w *lintExported) checkStutter(id *ast.Ident, thing string) { } func (w *lintExported) lintTypeDoc(t *ast.TypeSpec, doc *ast.CommentGroup) { + if w.disabledChecks.isDisabled("type") { + return + } + if !ast.IsExported(t.Name.Name) { return } + if doc == nil { w.onFailure(lint.Failure{ Node: t, @@ -214,14 +264,19 @@ func (w *lintExported) lintTypeDoc(t *ast.TypeSpec, doc *ast.CommentGroup) { break } } - if !strings.HasPrefix(s, t.Name.Name+" ") { - w.onFailure(lint.Failure{ - Node: doc, - Confidence: 1, - Category: "comments", - Failure: fmt.Sprintf(`comment on exported type %v should be of the form "%v ..." (with optional leading article)`, t.Name, t.Name), - }) + + // if comment starts with name of type and has some text after - it's ok + expectedPrefix := t.Name.Name + " " + if strings.HasPrefix(s, expectedPrefix) { + return } + + w.onFailure(lint.Failure{ + Node: doc, + Confidence: 1, + Category: "comments", + Failure: fmt.Sprintf(`comment on exported type %v should be of the form "%s..." (with optional leading article)`, t.Name, expectedPrefix), + }) } func (w *lintExported) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genDeclMissingComments map[*ast.GenDecl]bool) { @@ -230,6 +285,10 @@ func (w *lintExported) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genD kind = "const" } + if w.disabledChecks.isDisabled(kind) { + return + } + if len(vs.Names) > 1 { // Check that none are exported except for the first. for _, n := range vs.Names[1:] { @@ -251,7 +310,7 @@ func (w *lintExported) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genD return } - if vs.Doc == nil && vs.Comment == nil && gd.Doc == nil { + if vs.Doc == nil && gd.Doc == nil { if genDeclMissingComments[gd] { return } @@ -301,7 +360,7 @@ func (w *lintExported) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genD // // This function is needed because ast.CommentGroup.Text() does not handle //-style and /*-style comments uniformly func normalizeText(t string) string { - return strings.TrimPrefix(t, " ") + return strings.TrimSpace(t) } func (w *lintExported) Visit(n ast.Node) ast.Visitor { @@ -330,7 +389,15 @@ func (w *lintExported) Visit(n ast.Node) ast.Visitor { } w.lintTypeDoc(v, doc) w.checkStutter(v.Name, "type") - // Don't proceed inside types. + + if !w.disabledChecks.PublicInterfaces { + if iface, ok := v.Type.(*ast.InterfaceType); ok { + if ast.IsExported(v.Name.Name) { + w.doCheckPublicInterface(v.Name.Name, iface) + } + } + } + return nil case *ast.ValueSpec: w.lintValueSpecDoc(v, w.lastGen, w.genDeclMissingComments) @@ -338,3 +405,38 @@ func (w *lintExported) Visit(n ast.Node) ast.Visitor { } return w } + +func (w *lintExported) doCheckPublicInterface(typeName string, iface *ast.InterfaceType) { + for _, m := range iface.Methods.List { + w.lintInterfaceMethod(typeName, m) + } +} + +func (w *lintExported) lintInterfaceMethod(typeName string, m *ast.Field) { + if len(m.Names) == 0 { + return + } + if !ast.IsExported(m.Names[0].Name) { + return + } + name := m.Names[0].Name + if m.Doc == nil { + w.onFailure(lint.Failure{ + Node: m, + Confidence: 1, + Category: "comments", + Failure: fmt.Sprintf("public interface method %s.%s should be commented", typeName, name), + }) + return + } + s := normalizeText(m.Doc.Text()) + expectedPrefix := m.Names[0].Name + " " + if !strings.HasPrefix(s, expectedPrefix) { + w.onFailure(lint.Failure{ + Node: m.Doc, + Confidence: 0.8, + Category: "comments", + Failure: fmt.Sprintf(`comment on exported interface method %s.%s should be of the form "%s..."`, typeName, name, expectedPrefix), + }) + } +} diff --git a/vendor/github.com/mgechev/revive/rule/file-header.go b/vendor/github.com/mgechev/revive/rule/file-header.go index a7d69ff2b..0dcb57746 100644 --- a/vendor/github.com/mgechev/revive/rule/file-header.go +++ b/vendor/github.com/mgechev/revive/rule/file-header.go @@ -22,16 +22,18 @@ var ( func (r *FileHeaderRule) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() - if r.header == "" { - if len(arguments) < 1 { - return - } + if r.header != "" { + return // already configured + } - var ok bool - r.header, ok = arguments[0].(string) - if !ok { - panic(fmt.Sprintf("invalid argument for \"file-header\" rule: argument should be a string, got %T", arguments[0])) - } + if len(arguments) < 1 { + return + } + + var ok bool + r.header, ok = arguments[0].(string) + if !ok { + panic(fmt.Sprintf("invalid argument for \"file-header\" rule: argument should be a string, got %T", arguments[0])) } } diff --git a/vendor/github.com/mgechev/revive/rule/file-length-limit.go b/vendor/github.com/mgechev/revive/rule/file-length-limit.go new file mode 100644 index 000000000..c5a5641f4 --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/file-length-limit.go @@ -0,0 +1,138 @@ +package rule + +import ( + "bufio" + "bytes" + "fmt" + "go/ast" + "go/token" + "strings" + "sync" + + "github.com/mgechev/revive/lint" +) + +// FileLengthLimitRule lints the number of lines in a file. +type FileLengthLimitRule struct { + // max is the maximum number of lines allowed in a file. 0 means the rule is disabled. + max int + // skipComments indicates whether to skip comment lines when counting lines. + skipComments bool + // skipBlankLines indicates whether to skip blank lines when counting lines. + skipBlankLines bool + sync.Mutex +} + +// Apply applies the rule to given file. +func (r *FileLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) + + if r.max <= 0 { + // when max is negative or 0 the rule is disabled + return nil + } + + all := 0 + blank := 0 + scanner := bufio.NewScanner(bytes.NewReader(file.Content())) + for scanner.Scan() { + all++ + if len(bytes.TrimSpace(scanner.Bytes())) == 0 { + blank++ + } + } + + if err := scanner.Err(); err != nil { + panic(err.Error()) + } + + lines := all + if r.skipComments { + lines -= countCommentLines(file.AST.Comments) + } + + if r.skipBlankLines { + lines -= blank + } + + if lines <= r.max { + return nil + } + + return []lint.Failure{ + { + Category: "code-style", + Confidence: 1, + Position: lint.FailurePosition{ + Start: token.Position{ + Filename: file.Name, + Line: all, + }, + }, + Failure: fmt.Sprintf("file length is %d lines, which exceeds the limit of %d", lines, r.max), + }, + } +} + +func (r *FileLengthLimitRule) configure(arguments lint.Arguments) { + r.Lock() + defer r.Unlock() + + if r.max != 0 { + return // already configured + } + + if len(arguments) < 1 { + return // use default + } + + argKV, ok := arguments[0].(map[string]any) + if !ok { + panic(fmt.Sprintf(`invalid argument to the "file-length-limit" rule. Expecting a k,v map, got %T`, arguments[0])) + } + for k, v := range argKV { + switch k { + case "max": + maxLines, ok := v.(int64) + if !ok || maxLines < 0 { + panic(fmt.Sprintf(`invalid configuration value for max lines in "file-length-limit" rule; need positive int64 but got %T`, arguments[0])) + } + r.max = int(maxLines) + case "skipComments": + skipComments, ok := v.(bool) + if !ok { + panic(fmt.Sprintf(`invalid configuration value for skip comments in "file-length-limit" rule; need bool but got %T`, arguments[1])) + } + r.skipComments = skipComments + case "skipBlankLines": + skipBlankLines, ok := v.(bool) + if !ok { + panic(fmt.Sprintf(`invalid configuration value for skip blank lines in "file-length-limit" rule; need bool but got %T`, arguments[2])) + } + r.skipBlankLines = skipBlankLines + } + } +} + +// Name returns the rule name. +func (*FileLengthLimitRule) Name() string { + return "file-length-limit" +} + +func countCommentLines(comments []*ast.CommentGroup) int { + count := 0 + for _, cg := range comments { + for _, comment := range cg.List { + if len(comment.Text) < 2 { + continue + } + switch comment.Text[1] { + case '/': // single-line comment + count++ + case '*': // multi-line comment + count += strings.Count(comment.Text, "\n") + 1 + } + } + } + return count +} diff --git a/vendor/github.com/mgechev/revive/rule/filename-format.go b/vendor/github.com/mgechev/revive/rule/filename-format.go new file mode 100644 index 000000000..49fdf9c3e --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/filename-format.go @@ -0,0 +1,87 @@ +package rule + +import ( + "fmt" + "path/filepath" + "regexp" + "sync" + "unicode" + + "github.com/mgechev/revive/lint" +) + +// FilenameFormatRule lints source filenames according to a set of regular expressions given as arguments +type FilenameFormatRule struct { + format *regexp.Regexp + sync.Mutex +} + +// Apply applies the rule to the given file. +func (r *FilenameFormatRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) + + filename := filepath.Base(file.Name) + if r.format.MatchString(filename) { + return nil + } + + failureMsg := fmt.Sprintf("Filename %s is not of the format %s.%s", filename, r.format.String(), r.getMsgForNonASCIIChars(filename)) + return []lint.Failure{{ + Confidence: 1, + Failure: failureMsg, + RuleName: r.Name(), + Node: file.AST.Name, + }} +} + +func (r *FilenameFormatRule) getMsgForNonASCIIChars(str string) string { + result := "" + for _, c := range str { + if c <= unicode.MaxASCII { + continue + } + + result += fmt.Sprintf(" Non ASCII character %c (%U) found.", c, c) + } + + return result +} + +// Name returns the rule name. +func (*FilenameFormatRule) Name() string { + return "filename-format" +} + +var defaultFormat = regexp.MustCompile("^[_A-Za-z0-9][_A-Za-z0-9-]*.go$") + +func (r *FilenameFormatRule) configure(arguments lint.Arguments) { + r.Lock() + defer r.Unlock() + + if r.format != nil { + return + } + + argsCount := len(arguments) + if argsCount == 0 { + r.format = defaultFormat + return + } + + if argsCount > 1 { + panic(fmt.Sprintf("rule %q expects only one argument, got %d %v", r.Name(), argsCount, arguments)) + } + + arg := arguments[0] + str, ok := arg.(string) + if !ok { + panic(fmt.Sprintf("rule %q expects a string argument, got %v of type %T", r.Name(), arg, arg)) + } + + format, err := regexp.Compile(str) + if err != nil { + panic(fmt.Sprintf("rule %q expects a valid regexp argument, got %v for %s", r.Name(), err, arg)) + } + + r.format = format +} diff --git a/vendor/github.com/mgechev/revive/rule/function-length.go b/vendor/github.com/mgechev/revive/rule/function-length.go index fd65884e9..30402313d 100644 --- a/vendor/github.com/mgechev/revive/rule/function-length.go +++ b/vendor/github.com/mgechev/revive/rule/function-length.go @@ -20,12 +20,14 @@ type FunctionLength struct { func (r *FunctionLength) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() - if !r.configured { - maxStmt, maxLines := r.parseArguments(arguments) - r.maxStmt = int(maxStmt) - r.maxLines = int(maxLines) - r.configured = true + if r.configured { + return } + + r.configured = true + maxStmt, maxLines := r.parseArguments(arguments) + r.maxStmt = int(maxStmt) + r.maxLines = int(maxLines) } // Apply applies the rule to given file. @@ -61,8 +63,9 @@ func (*FunctionLength) parseArguments(arguments lint.Arguments) (maxStmt, maxLin return defaultFuncStmtsLimit, defaultFuncLinesLimit } - if len(arguments) != 2 { - panic(fmt.Sprintf(`invalid configuration for "function-length" rule, expected 2 arguments but got %d`, len(arguments))) + const minArguments = 2 + if len(arguments) != minArguments { + panic(fmt.Sprintf(`invalid configuration for "function-length" rule, expected %d arguments but got %d`, minArguments, len(arguments))) } maxStmt, maxStmtOk := arguments[0].(int64) @@ -98,7 +101,8 @@ func (w lintFuncLength) Visit(n ast.Node) ast.Visitor { } body := node.Body - if body == nil || len(node.Body.List) == 0 { + emptyBody := body == nil || len(node.Body.List) == 0 + if emptyBody { return nil } diff --git a/vendor/github.com/mgechev/revive/rule/function-result-limit.go b/vendor/github.com/mgechev/revive/rule/function-result-limit.go index 6a0748011..23474b5ee 100644 --- a/vendor/github.com/mgechev/revive/rule/function-result-limit.go +++ b/vendor/github.com/mgechev/revive/rule/function-result-limit.go @@ -19,20 +19,24 @@ const defaultResultsLimit = 3 func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() - if r.max == 0 { - if len(arguments) < 1 { - r.max = defaultResultsLimit - return - } - max, ok := arguments[0].(int64) // Alt. non panicking version - if !ok { - panic(fmt.Sprintf(`invalid value passed as return results number to the "function-result-limit" rule; need int64 but got %T`, arguments[0])) - } - if max < 0 { - panic(`the value passed as return results number to the "function-result-limit" rule cannot be negative`) - } - r.max = int(max) + if r.max != 0 { + return // already configured } + + if len(arguments) < 1 { + r.max = defaultResultsLimit + return + } + + maxResults, ok := arguments[0].(int64) // Alt. non panicking version + if !ok { + panic(fmt.Sprintf(`invalid value passed as return results number to the "function-result-limit" rule; need int64 but got %T`, arguments[0])) + } + if maxResults < 0 { + panic(`the value passed as return results number to the "function-result-limit" rule cannot be negative`) + } + + r.max = int(maxResults) } // Apply applies the rule to given file. @@ -67,7 +71,8 @@ func (w lintFunctionResultsNum) Visit(n ast.Node) ast.Visitor { node, ok := n.(*ast.FuncDecl) if ok { num := 0 - if node.Type.Results != nil { + hasResults := node.Type.Results != nil + if hasResults { num = node.Type.Results.NumFields() } if num > w.max { @@ -76,8 +81,10 @@ func (w lintFunctionResultsNum) Visit(n ast.Node) ast.Visitor { Failure: fmt.Sprintf("maximum number of return results per function exceeded; max %d but got %d", w.max, num), Node: node.Type, }) - return w } + + return nil // skip visiting function's body } + return w } diff --git a/vendor/github.com/mgechev/revive/rule/get-return.go b/vendor/github.com/mgechev/revive/rule/get-return.go index 600a40fac..06323a087 100644 --- a/vendor/github.com/mgechev/revive/rule/get-return.go +++ b/vendor/github.com/mgechev/revive/rule/get-return.go @@ -33,15 +33,25 @@ type lintReturnRule struct { onFailure func(lint.Failure) } +const getterPrefix = "GET" + +var lenGetterPrefix = len(getterPrefix) + func isGetter(name string) bool { - if strings.HasPrefix(strings.ToUpper(name), "GET") { - if len(name) > 3 { - c := name[3] - return !(c >= 'a' && c <= 'z') - } + nameHasGetterPrefix := strings.HasPrefix(strings.ToUpper(name), getterPrefix) + if !nameHasGetterPrefix { + return false } - return false + isJustGet := len(name) == lenGetterPrefix + if isJustGet { + return false + } + + c := name[lenGetterPrefix] + lowerCaseAfterGetterPrefix := c >= 'a' && c <= 'z' + + return !lowerCaseAfterGetterPrefix } func hasResults(rs *ast.FieldList) bool { diff --git a/vendor/github.com/mgechev/revive/rule/identical-branches.go b/vendor/github.com/mgechev/revive/rule/identical-branches.go index 9222c8a9c..c6008925f 100644 --- a/vendor/github.com/mgechev/revive/rule/identical-branches.go +++ b/vendor/github.com/mgechev/revive/rule/identical-branches.go @@ -39,9 +39,11 @@ func (w *lintIdenticalBranches) Visit(node ast.Node) ast.Visitor { return w } - if n.Else == nil { + noElseBranch := n.Else == nil + if noElseBranch { return w } + branches := []*ast.BlockStmt{n.Body} elseBranch, ok := n.Else.(*ast.BlockStmt) @@ -59,14 +61,15 @@ func (w *lintIdenticalBranches) Visit(node ast.Node) ast.Visitor { func (lintIdenticalBranches) identicalBranches(branches []*ast.BlockStmt) bool { if len(branches) < 2 { - return false + return false // only one branch to compare thus we return } - ref := gofmt(branches[0]) - refSize := len(branches[0].List) + referenceBranch := gofmt(branches[0]) + referenceBranchSize := len(branches[0].List) for i := 1; i < len(branches); i++ { - currentSize := len(branches[i].List) - if currentSize != refSize || gofmt(branches[i]) != ref { + currentBranch := branches[i] + currentBranchSize := len(currentBranch.List) + if currentBranchSize != referenceBranchSize || gofmt(currentBranch) != referenceBranch { return false } } diff --git a/vendor/github.com/mgechev/revive/rule/import-alias-naming.go b/vendor/github.com/mgechev/revive/rule/import-alias-naming.go index a6d096c8b..48d22566a 100644 --- a/vendor/github.com/mgechev/revive/rule/import-alias-naming.go +++ b/vendor/github.com/mgechev/revive/rule/import-alias-naming.go @@ -68,7 +68,7 @@ func (r *ImportAliasNamingRule) Apply(file *lint.File, arguments lint.Arguments) } alias := is.Name - if alias == nil || alias.Name == "_" || alias.Name == "." { // "_" and "." are special types of import aiases and should be processed by another linter rule + if alias == nil || alias.Name == "_" || alias.Name == "." { // "_" and "." are special types of import aliases and should be processed by another linter rule continue } diff --git a/vendor/github.com/mgechev/revive/rule/indent-error-flow.go b/vendor/github.com/mgechev/revive/rule/indent-error-flow.go index 294ceef84..ebc1e793a 100644 --- a/vendor/github.com/mgechev/revive/rule/indent-error-flow.go +++ b/vendor/github.com/mgechev/revive/rule/indent-error-flow.go @@ -18,27 +18,27 @@ func (*IndentErrorFlowRule) Name() string { return "indent-error-flow" } -// CheckIfElse evaluates the rule against an ifelse.Chain. -func (*IndentErrorFlowRule) CheckIfElse(chain ifelse.Chain, args ifelse.Args) (failMsg string) { +// CheckIfElse evaluates the rule against an ifelse.Chain and returns a failure message if applicable. +func (*IndentErrorFlowRule) CheckIfElse(chain ifelse.Chain, args ifelse.Args) string { if !chain.If.Deviates() { // this rule only applies if the if-block deviates control flow - return + return "" } if chain.HasPriorNonDeviating { // if we de-indent the "else" block then a previous branch // might flow into it, affecting program behaviour - return + return "" } if !chain.If.Returns() { // avoid overlapping with superfluous-else - return + return "" } if args.PreserveScope && !chain.AtBlockEnd && (chain.HasInitializer || chain.Else.HasDecls) { // avoid increasing variable scope - return + return "" } return "if block ends with a return statement, so drop this else and outdent its block" diff --git a/vendor/github.com/mgechev/revive/rule/line-length-limit.go b/vendor/github.com/mgechev/revive/rule/line-length-limit.go index 1a414f691..a154b7aec 100644 --- a/vendor/github.com/mgechev/revive/rule/line-length-limit.go +++ b/vendor/github.com/mgechev/revive/rule/line-length-limit.go @@ -23,19 +23,21 @@ const defaultLineLengthLimit = 80 func (r *LineLengthLimitRule) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() - if r.max == 0 { - if len(arguments) < 1 { - r.max = defaultLineLengthLimit - return - } + if r.max != 0 { + return // already configured + } - max, ok := arguments[0].(int64) // Alt. non panicking version - if !ok || max < 0 { - panic(`invalid value passed as argument number to the "line-length-limit" rule`) - } + if len(arguments) < 1 { + r.max = defaultLineLengthLimit + return + } - r.max = int(max) + maxLength, ok := arguments[0].(int64) // Alt. non panicking version + if !ok || maxLength < 0 { + panic(`invalid value passed as argument number to the "line-length-limit" rule`) } + + r.max = int(maxLength) } // Apply applies the rule to given file. diff --git a/vendor/github.com/mgechev/revive/rule/max-control-nesting.go b/vendor/github.com/mgechev/revive/rule/max-control-nesting.go index c4eb36193..5dbb1eefa 100644 --- a/vendor/github.com/mgechev/revive/rule/max-control-nesting.go +++ b/vendor/github.com/mgechev/revive/rule/max-control-nesting.go @@ -110,7 +110,7 @@ func (r *MaxControlNestingRule) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() if !(r.max < 1) { - return // max already set + return // max already configured } if len(arguments) < 1 { @@ -120,9 +120,9 @@ func (r *MaxControlNestingRule) configure(arguments lint.Arguments) { checkNumberOfArguments(1, arguments, r.Name()) - max, ok := arguments[0].(int64) // Alt. non panicking version + maxNesting, ok := arguments[0].(int64) // Alt. non panicking version if !ok { panic(`invalid value passed as argument number to the "max-control-nesting" rule`) } - r.max = max + r.max = maxNesting } diff --git a/vendor/github.com/mgechev/revive/rule/max-public-structs.go b/vendor/github.com/mgechev/revive/rule/max-public-structs.go index 25be3e676..70840e734 100644 --- a/vendor/github.com/mgechev/revive/rule/max-public-structs.go +++ b/vendor/github.com/mgechev/revive/rule/max-public-structs.go @@ -19,20 +19,22 @@ const defaultMaxPublicStructs = 5 func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() - if r.max < 1 { - if len(arguments) < 1 { - r.max = defaultMaxPublicStructs - return - } + if r.max == 0 { + return // already configured + } - checkNumberOfArguments(1, arguments, r.Name()) + if len(arguments) < 1 { + r.max = defaultMaxPublicStructs + return + } - max, ok := arguments[0].(int64) // Alt. non panicking version - if !ok { - panic(`invalid value passed as argument number to the "max-public-structs" rule`) - } - r.max = max + checkNumberOfArguments(1, arguments, r.Name()) + + maxStructs, ok := arguments[0].(int64) // Alt. non panicking version + if !ok { + panic(`invalid value passed as argument number to the "max-public-structs" rule`) } + r.max = maxStructs } // Apply applies the rule to given file. diff --git a/vendor/github.com/mgechev/revive/rule/receiver-naming.go b/vendor/github.com/mgechev/revive/rule/receiver-naming.go index d79bb9fe8..afcd99b8f 100644 --- a/vendor/github.com/mgechev/revive/rule/receiver-naming.go +++ b/vendor/github.com/mgechev/revive/rule/receiver-naming.go @@ -3,16 +3,55 @@ package rule import ( "fmt" "go/ast" + "sync" "github.com/mgechev/revive/internal/typeparams" "github.com/mgechev/revive/lint" ) // ReceiverNamingRule lints given else constructs. -type ReceiverNamingRule struct{} +type ReceiverNamingRule struct { + receiverNameMaxLength int + sync.Mutex +} + +const defaultReceiverNameMaxLength = -1 // thus will not check + +func (r *ReceiverNamingRule) configure(arguments lint.Arguments) { + r.Lock() + defer r.Unlock() + if r.receiverNameMaxLength != 0 { + return + } + + r.receiverNameMaxLength = defaultReceiverNameMaxLength + if len(arguments) < 1 { + return + } + + args, ok := arguments[0].(map[string]any) + if !ok { + panic(fmt.Sprintf("Unable to get arguments for rule %s. Expected object of key-value-pairs.", r.Name())) + } + + for k, v := range args { + switch k { + case "maxLength": + value, ok := v.(int64) + if !ok { + panic(fmt.Sprintf("Invalid value %v for argument %s of rule %s, expected integer value got %T", v, k, r.Name(), v)) + } + r.receiverNameMaxLength = int(value) + default: + panic(fmt.Sprintf("Unknown argument %s for %s rule.", k, r.Name())) + } + } +} // Apply applies the rule to given file. -func (*ReceiverNamingRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { +func (r *ReceiverNamingRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { + r.configure(args) + var failures []lint.Failure fileAst := file.AST @@ -20,7 +59,8 @@ func (*ReceiverNamingRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failu onFailure: func(failure lint.Failure) { failures = append(failures, failure) }, - typeReceiver: map[string]string{}, + typeReceiver: map[string]string{}, + receiverNameMaxLength: r.receiverNameMaxLength, } ast.Walk(walker, fileAst) @@ -34,8 +74,9 @@ func (*ReceiverNamingRule) Name() string { } type lintReceiverName struct { - onFailure func(lint.Failure) - typeReceiver map[string]string + onFailure func(lint.Failure) + typeReceiver map[string]string + receiverNameMaxLength int } func (w lintReceiverName) Visit(n ast.Node) ast.Visitor { @@ -66,6 +107,17 @@ func (w lintReceiverName) Visit(n ast.Node) ast.Visitor { }) return w } + + if w.receiverNameMaxLength > 0 && len([]rune(name)) > w.receiverNameMaxLength { + w.onFailure(lint.Failure{ + Node: n, + Confidence: 1, + Category: "naming", + Failure: fmt.Sprintf("receiver name %s is longer than %d characters", name, w.receiverNameMaxLength), + }) + return w + } + recv := typeparams.ReceiverType(fn) if prev, ok := w.typeReceiver[recv]; ok && prev != name { w.onFailure(lint.Failure{ diff --git a/vendor/github.com/mgechev/revive/rule/redefines-builtin-id.go b/vendor/github.com/mgechev/revive/rule/redefines-builtin-id.go index b3ff08456..10ea16ae1 100644 --- a/vendor/github.com/mgechev/revive/rule/redefines-builtin-id.go +++ b/vendor/github.com/mgechev/revive/rule/redefines-builtin-id.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" "go/token" + "maps" "github.com/mgechev/revive/lint" ) @@ -33,6 +34,12 @@ var builtFunctions = map[string]bool{ "recover": true, } +var builtFunctionsAfterGo121 = map[string]bool{ + "clear": true, + "max": true, + "min": true, +} + var builtInTypes = map[string]bool{ "bool": true, "byte": true, @@ -69,7 +76,17 @@ func (*RedefinesBuiltinIDRule) Apply(file *lint.File, _ lint.Arguments) []lint.F } astFile := file.AST - w := &lintRedefinesBuiltinID{onFailure} + + builtFuncs := maps.Clone(builtFunctions) + if file.Pkg.IsAtLeastGo121() { + maps.Copy(builtFuncs, builtFunctionsAfterGo121) + } + w := &lintRedefinesBuiltinID{ + onFailure: onFailure, + builtInConstAndVars: builtInConstAndVars, + builtFunctions: builtFuncs, + builtInTypes: builtInTypes, + } ast.Walk(w, astFile) return failures @@ -81,7 +98,10 @@ func (*RedefinesBuiltinIDRule) Name() string { } type lintRedefinesBuiltinID struct { - onFailure func(lint.Failure) + onFailure func(lint.Failure) + builtInConstAndVars map[string]bool + builtFunctions map[string]bool + builtInTypes map[string]bool } func (w *lintRedefinesBuiltinID) Visit(node ast.Node) ast.Visitor { @@ -125,6 +145,31 @@ func (w *lintRedefinesBuiltinID) Visit(node ast.Node) ast.Visitor { if ok, bt := w.isBuiltIn(id); ok { w.addFailure(n, fmt.Sprintf("redefinition of the built-in %s %s", bt, id)) } + case *ast.FuncType: + var fields []*ast.Field + if n.TypeParams != nil { + fields = append(fields, n.TypeParams.List...) + } + if n.Params != nil { + fields = append(fields, n.Params.List...) + } + if n.Results != nil { + fields = append(fields, n.Results.List...) + } + for _, field := range fields { + for _, name := range field.Names { + obj := name.Obj + isTypeOrName := obj != nil && (obj.Kind == ast.Var || obj.Kind == ast.Typ) + if !isTypeOrName { + continue + } + + id := obj.Name + if ok, bt := w.isBuiltIn(id); ok { + w.addFailure(name, fmt.Sprintf("redefinition of the built-in %s %s", bt, id)) + } + } + } case *ast.AssignStmt: for _, e := range n.Lhs { id, ok := e.(*ast.Ident) @@ -162,16 +207,16 @@ func (w lintRedefinesBuiltinID) addFailure(node ast.Node, msg string) { }) } -func (lintRedefinesBuiltinID) isBuiltIn(id string) (r bool, builtInKind string) { - if builtFunctions[id] { +func (w *lintRedefinesBuiltinID) isBuiltIn(id string) (r bool, builtInKind string) { + if w.builtFunctions[id] { return true, "function" } - if builtInConstAndVars[id] { + if w.builtInConstAndVars[id] { return true, "constant or variable" } - if builtInTypes[id] { + if w.builtInTypes[id] { return true, "type" } diff --git a/vendor/github.com/mgechev/revive/rule/string-format.go b/vendor/github.com/mgechev/revive/rule/string-format.go index 70edf7387..ecac3fa7c 100644 --- a/vendor/github.com/mgechev/revive/rule/string-format.go +++ b/vendor/github.com/mgechev/revive/rule/string-format.go @@ -6,6 +6,7 @@ import ( "go/token" "regexp" "strconv" + "strings" "github.com/mgechev/revive/lint" ) @@ -66,12 +67,14 @@ type lintStringFormatRule struct { type stringFormatSubrule struct { parent *lintStringFormatRule - scope stringFormatSubruleScope + scopes stringFormatSubruleScopes regexp *regexp.Regexp negated bool errorMessage string } +type stringFormatSubruleScopes []*stringFormatSubruleScope + type stringFormatSubruleScope struct { funcName string // Function name the rule is scoped to argument int // (optional) Which argument in calls to the function is checked against the rule (the first argument is checked by default) @@ -90,10 +93,10 @@ var parseStringFormatScope = regexp.MustCompile( func (w *lintStringFormatRule) parseArguments(arguments lint.Arguments) { for i, argument := range arguments { - scope, regex, negated, errorMessage := w.parseArgument(argument, i) + scopes, regex, negated, errorMessage := w.parseArgument(argument, i) w.rules = append(w.rules, stringFormatSubrule{ parent: w, - scope: scope, + scopes: scopes, regexp: regex, negated: negated, errorMessage: errorMessage, @@ -101,7 +104,7 @@ func (w *lintStringFormatRule) parseArguments(arguments lint.Arguments) { } } -func (w lintStringFormatRule) parseArgument(argument any, ruleNum int) (scope stringFormatSubruleScope, regex *regexp.Regexp, negated bool, errorMessage string) { +func (w lintStringFormatRule) parseArgument(argument any, ruleNum int) (scopes stringFormatSubruleScopes, regex *regexp.Regexp, negated bool, errorMessage string) { g, ok := argument.([]any) // Cast to generic slice first if !ok { w.configError("argument is not a slice", ruleNum, 0) @@ -125,26 +128,39 @@ func (w lintStringFormatRule) parseArgument(argument any, ruleNum int) (scope st w.configError("regex is too small (regexes should begin and end with '/')", ruleNum, 1) } - // Parse rule scope - scope = stringFormatSubruleScope{} - matches := parseStringFormatScope.FindStringSubmatch(rule[0]) - if matches == nil { - // The rule's scope didn't match the parsing regex at all, probably a configuration error - w.parseError("unable to parse rule scope", ruleNum, 0) - } else if len(matches) != 4 { - // The rule's scope matched the parsing regex, but an unexpected number of submatches was returned, probably a bug - w.parseError(fmt.Sprintf("unexpected number of submatches when parsing scope: %d, expected 4", len(matches)), ruleNum, 0) - } - scope.funcName = matches[1] - if len(matches[2]) > 0 { - var err error - scope.argument, err = strconv.Atoi(matches[2]) - if err != nil { - w.parseError("unable to parse argument number in rule scope", ruleNum, 0) + // Parse rule scopes + rawScopes := strings.Split(rule[0], ",") + + scopes = make([]*stringFormatSubruleScope, 0, len(rawScopes)) + for scopeNum, rawScope := range rawScopes { + rawScope = strings.TrimSpace(rawScope) + + if len(rawScope) == 0 { + w.parseScopeError("empty scope in rule scopes:", ruleNum, 0, scopeNum) } - } - if len(matches[3]) > 0 { - scope.field = matches[3] + + scope := stringFormatSubruleScope{} + matches := parseStringFormatScope.FindStringSubmatch(rawScope) + if matches == nil { + // The rule's scope didn't match the parsing regex at all, probably a configuration error + w.parseScopeError("unable to parse rule scope", ruleNum, 0, scopeNum) + } else if len(matches) != 4 { + // The rule's scope matched the parsing regex, but an unexpected number of submatches was returned, probably a bug + w.parseScopeError(fmt.Sprintf("unexpected number of submatches when parsing scope: %d, expected 4", len(matches)), ruleNum, 0, scopeNum) + } + scope.funcName = matches[1] + if len(matches[2]) > 0 { + var err error + scope.argument, err = strconv.Atoi(matches[2]) + if err != nil { + w.parseScopeError("unable to parse argument number in rule scope", ruleNum, 0, scopeNum) + } + } + if len(matches[3]) > 0 { + scope.field = matches[3] + } + + scopes = append(scopes, &scope) } // Strip / characters from the beginning and end of rule[1] before compiling @@ -162,7 +178,7 @@ func (w lintStringFormatRule) parseArgument(argument any, ruleNum int) (scope st if len(rule) == 3 { errorMessage = rule[2] } - return scope, regex, negated, errorMessage + return scopes, regex, negated, errorMessage } // Report an invalid config, this is specifically the user's fault @@ -175,6 +191,11 @@ func (lintStringFormatRule) parseError(msg string, ruleNum, option int) { panic(fmt.Sprintf("failed to parse configuration for string-format: %s [argument %d, option %d]", msg, ruleNum, option)) } +// Report a general scope config parsing failure, this may be the user's fault, but it isn't known for certain +func (lintStringFormatRule) parseScopeError(msg string, ruleNum, option, scopeNum int) { + panic(fmt.Sprintf("failed to parse configuration for string-format: %s [argument %d, option %d, scope index %d]", msg, ruleNum, option, scopeNum)) +} + // #endregion // #region Node traversal @@ -193,8 +214,10 @@ func (w lintStringFormatRule) Visit(node ast.Node) ast.Visitor { } for _, rule := range w.rules { - if rule.scope.funcName == callName { - rule.Apply(call) + for _, scope := range rule.scopes { + if scope.funcName == callName { + rule.apply(call, scope) + } } } @@ -228,15 +251,15 @@ func (lintStringFormatRule) getCallName(call *ast.CallExpr) (callName string, ok // #region Linting logic -// Apply a single format rule to a call expression (should be done after verifying the that the call expression matches the rule's scope) -func (r *stringFormatSubrule) Apply(call *ast.CallExpr) { - if len(call.Args) <= r.scope.argument { +// apply a single format rule to a call expression (should be done after verifying the that the call expression matches the rule's scope) +func (r *stringFormatSubrule) apply(call *ast.CallExpr, scope *stringFormatSubruleScope) { + if len(call.Args) <= scope.argument { return } - arg := call.Args[r.scope.argument] + arg := call.Args[scope.argument] var lit *ast.BasicLit - if len(r.scope.field) > 0 { + if len(scope.field) > 0 { // Try finding the scope's Field, treating arg as a composite literal composite, ok := arg.(*ast.CompositeLit) if !ok { @@ -248,7 +271,7 @@ func (r *stringFormatSubrule) Apply(call *ast.CallExpr) { continue } key, ok := kv.Key.(*ast.Ident) - if !ok || key.Name != r.scope.field { + if !ok || key.Name != scope.field { continue } @@ -268,39 +291,33 @@ func (r *stringFormatSubrule) Apply(call *ast.CallExpr) { } // Unquote the string literal before linting unquoted := lit.Value[1 : len(lit.Value)-1] - r.lintMessage(unquoted, lit) + if r.stringIsOK(unquoted) { + return + } + + r.generateFailure(lit) } -func (r *stringFormatSubrule) lintMessage(s string, node ast.Node) { +func (r *stringFormatSubrule) stringIsOK(s string) bool { + matches := r.regexp.MatchString(s) if r.negated { - if !r.regexp.MatchString(s) { - return - } - // Fail if the string does match the user's regex - var failure string - if len(r.errorMessage) > 0 { - failure = r.errorMessage - } else { - failure = fmt.Sprintf("string literal matches user defined regex /%s/", r.regexp.String()) - } - r.parent.onFailure(lint.Failure{ - Confidence: 1, - Failure: failure, - Node: node, - }) - return + return !matches } - // Fail if the string does NOT match the user's regex - if r.regexp.MatchString(s) { - return - } + return matches +} + +func (r *stringFormatSubrule) generateFailure(node ast.Node) { var failure string - if len(r.errorMessage) > 0 { + switch { + case len(r.errorMessage) > 0: failure = r.errorMessage - } else { + case r.negated: + failure = fmt.Sprintf("string literal matches user defined regex /%s/", r.regexp.String()) + case !r.negated: failure = fmt.Sprintf("string literal doesn't match user defined regex /%s/", r.regexp.String()) } + r.parent.onFailure(lint.Failure{ Confidence: 1, Failure: failure, diff --git a/vendor/github.com/mgechev/revive/rule/struct-tag.go b/vendor/github.com/mgechev/revive/rule/struct-tag.go index f6ee47a73..ec3f0c7cf 100644 --- a/vendor/github.com/mgechev/revive/rule/struct-tag.go +++ b/vendor/github.com/mgechev/revive/rule/struct-tag.go @@ -20,23 +20,27 @@ type StructTagRule struct { func (r *StructTagRule) configure(arguments lint.Arguments) { r.Lock() defer r.Unlock() - if r.userDefined == nil && len(arguments) > 0 { - checkNumberOfArguments(1, arguments, r.Name()) - r.userDefined = make(map[string][]string, len(arguments)) - for _, arg := range arguments { - item, ok := arg.(string) - if !ok { - panic(fmt.Sprintf("Invalid argument to the %s rule. Expecting a string, got %v (of type %T)", r.Name(), arg, arg)) - } - parts := strings.Split(item, ",") - if len(parts) < 2 { - panic(fmt.Sprintf("Invalid argument to the %s rule. Expecting a string of the form key[,option]+, got %s", r.Name(), item)) - } - key := strings.TrimSpace(parts[0]) - for i := 1; i < len(parts); i++ { - option := strings.TrimSpace(parts[i]) - r.userDefined[key] = append(r.userDefined[key], option) - } + + mustConfigure := r.userDefined == nil && len(arguments) > 0 + if !mustConfigure { + return + } + + checkNumberOfArguments(1, arguments, r.Name()) + r.userDefined = make(map[string][]string, len(arguments)) + for _, arg := range arguments { + item, ok := arg.(string) + if !ok { + panic(fmt.Sprintf("Invalid argument to the %s rule. Expecting a string, got %v (of type %T)", r.Name(), arg, arg)) + } + parts := strings.Split(item, ",") + if len(parts) < 2 { + panic(fmt.Sprintf("Invalid argument to the %s rule. Expecting a string of the form key[,option]+, got %s", r.Name(), item)) + } + key := strings.TrimSpace(parts[0]) + for i := 1; i < len(parts); i++ { + option := strings.TrimSpace(parts[i]) + r.userDefined[key] = append(r.userDefined[key], option) } } } @@ -75,11 +79,13 @@ type lintStructTagRule struct { func (w lintStructTagRule) Visit(node ast.Node) ast.Visitor { switch n := node.(type) { case *ast.StructType: - if n.Fields == nil || n.Fields.NumFields() < 1 { + isEmptyStruct := n.Fields == nil || n.Fields.NumFields() < 1 + if isEmptyStruct { return nil // skip empty structs } - w.usedTagNbr = map[int]bool{} // init - w.usedTagName = map[string]bool{} // init + + w.usedTagNbr = map[int]bool{} + w.usedTagName = map[string]bool{} for _, f := range n.Fields.List { if f.Tag != nil { w.checkTaggedField(f) diff --git a/vendor/github.com/mgechev/revive/rule/superfluous-else.go b/vendor/github.com/mgechev/revive/rule/superfluous-else.go index 2aa1b6b2c..18e8f3bdd 100644 --- a/vendor/github.com/mgechev/revive/rule/superfluous-else.go +++ b/vendor/github.com/mgechev/revive/rule/superfluous-else.go @@ -2,6 +2,7 @@ package rule import ( "fmt" + "github.com/mgechev/revive/internal/ifelse" "github.com/mgechev/revive/lint" ) @@ -19,27 +20,27 @@ func (*SuperfluousElseRule) Name() string { return "superfluous-else" } -// CheckIfElse evaluates the rule against an ifelse.Chain. -func (*SuperfluousElseRule) CheckIfElse(chain ifelse.Chain, args ifelse.Args) (failMsg string) { +// CheckIfElse evaluates the rule against an ifelse.Chain and returns a failure message if applicable. +func (*SuperfluousElseRule) CheckIfElse(chain ifelse.Chain, args ifelse.Args) string { if !chain.If.Deviates() { // this rule only applies if the if-block deviates control flow - return + return "" } if chain.HasPriorNonDeviating { // if we de-indent the "else" block then a previous branch // might flow into it, affecting program behaviour - return + return "" } if chain.If.Returns() { // avoid overlapping with indent-error-flow - return + return "" } if args.PreserveScope && !chain.AtBlockEnd && (chain.HasInitializer || chain.Else.HasDecls) { // avoid increasing variable scope - return + return "" } return fmt.Sprintf("if block ends with %v, so drop this else and outdent its block", chain.If.LongString()) diff --git a/vendor/github.com/mgechev/revive/rule/time-equal.go b/vendor/github.com/mgechev/revive/rule/time-equal.go index 3b85e18a8..a4fab88b3 100644 --- a/vendor/github.com/mgechev/revive/rule/time-equal.go +++ b/vendor/github.com/mgechev/revive/rule/time-equal.go @@ -50,26 +50,23 @@ func (l *lintTimeEqual) Visit(node ast.Node) ast.Visitor { return l } - xtyp := l.file.Pkg.TypeOf(expr.X) - ytyp := l.file.Pkg.TypeOf(expr.Y) - - if !isNamedType(xtyp, "time", "Time") || !isNamedType(ytyp, "time", "Time") { + typeOfX := l.file.Pkg.TypeOf(expr.X) + typeOfY := l.file.Pkg.TypeOf(expr.Y) + bothAreOfTimeType := isNamedType(typeOfX, "time", "Time") && isNamedType(typeOfY, "time", "Time") + if !bothAreOfTimeType { return l } - var failure string - switch expr.Op { - case token.EQL: - failure = fmt.Sprintf("use %s.Equal(%s) instead of %q operator", gofmt(expr.X), gofmt(expr.Y), expr.Op) - case token.NEQ: - failure = fmt.Sprintf("use !%s.Equal(%s) instead of %q operator", gofmt(expr.X), gofmt(expr.Y), expr.Op) + negateStr := "" + if token.NEQ == expr.Op { + negateStr = "!" } l.onFailure(lint.Failure{ Category: "time", Confidence: 1, Node: node, - Failure: failure, + Failure: fmt.Sprintf("use %s%s.Equal(%s) instead of %q operator", negateStr, gofmt(expr.X), gofmt(expr.Y), expr.Op), }) return l diff --git a/vendor/github.com/mgechev/revive/rule/time-naming.go b/vendor/github.com/mgechev/revive/rule/time-naming.go index cea452e61..5bccf8a7a 100644 --- a/vendor/github.com/mgechev/revive/rule/time-naming.go +++ b/vendor/github.com/mgechev/revive/rule/time-naming.go @@ -90,6 +90,7 @@ func isNamedType(typ types.Type, importPath, name string) bool { if !ok { return false } - tn := n.Obj() - return tn != nil && tn.Pkg() != nil && tn.Pkg().Path() == importPath && tn.Name() == name + + typeName := n.Obj() + return typeName != nil && typeName.Pkg() != nil && typeName.Pkg().Path() == importPath && typeName.Name() == name } diff --git a/vendor/github.com/mgechev/revive/rule/unchecked-type-assertion.go b/vendor/github.com/mgechev/revive/rule/unchecked-type-assertion.go index df27743cb..eea344060 100644 --- a/vendor/github.com/mgechev/revive/rule/unchecked-type-assertion.go +++ b/vendor/github.com/mgechev/revive/rule/unchecked-type-assertion.go @@ -13,7 +13,7 @@ const ( ruleUTAMessageIgnored = "type assertion result ignored" ) -// UncheckedTypeAssertionRule lints missing or ignored `ok`-value in danymic type casts. +// UncheckedTypeAssertionRule lints missing or ignored `ok`-value in dynamic type casts. type UncheckedTypeAssertionRule struct { sync.Mutex acceptIgnoredAssertionResult bool @@ -54,7 +54,7 @@ func (u *UncheckedTypeAssertionRule) Apply(file *lint.File, args lint.Arguments) var failures []lint.Failure - walker := &lintUnchekedTypeAssertion{ + walker := &lintUncheckedTypeAssertion{ onFailure: func(failure lint.Failure) { failures = append(failures, failure) }, @@ -71,7 +71,7 @@ func (*UncheckedTypeAssertionRule) Name() string { return "unchecked-type-assertion" } -type lintUnchekedTypeAssertion struct { +type lintUncheckedTypeAssertion struct { onFailure func(lint.Failure) acceptIgnoredTypeAssertionResult bool } @@ -89,14 +89,14 @@ func isTypeSwitch(e *ast.TypeAssertExpr) bool { return e.Type == nil } -func (w *lintUnchekedTypeAssertion) requireNoTypeAssert(expr ast.Expr) { +func (w *lintUncheckedTypeAssertion) requireNoTypeAssert(expr ast.Expr) { e, ok := expr.(*ast.TypeAssertExpr) if ok && !isTypeSwitch(e) { w.addFailure(e, ruleUTAMessagePanic) } } -func (w *lintUnchekedTypeAssertion) handleIfStmt(n *ast.IfStmt) { +func (w *lintUncheckedTypeAssertion) handleIfStmt(n *ast.IfStmt) { ifCondition, ok := n.Cond.(*ast.BinaryExpr) if ok { w.requireNoTypeAssert(ifCondition.X) @@ -104,7 +104,7 @@ func (w *lintUnchekedTypeAssertion) handleIfStmt(n *ast.IfStmt) { } } -func (w *lintUnchekedTypeAssertion) requireBinaryExpressionWithoutTypeAssertion(expr ast.Expr) { +func (w *lintUncheckedTypeAssertion) requireBinaryExpressionWithoutTypeAssertion(expr ast.Expr) { binaryExpr, ok := expr.(*ast.BinaryExpr) if ok { w.requireNoTypeAssert(binaryExpr.X) @@ -112,19 +112,19 @@ func (w *lintUnchekedTypeAssertion) requireBinaryExpressionWithoutTypeAssertion( } } -func (w *lintUnchekedTypeAssertion) handleCaseClause(n *ast.CaseClause) { +func (w *lintUncheckedTypeAssertion) handleCaseClause(n *ast.CaseClause) { for _, expr := range n.List { w.requireNoTypeAssert(expr) w.requireBinaryExpressionWithoutTypeAssertion(expr) } } -func (w *lintUnchekedTypeAssertion) handleSwitch(n *ast.SwitchStmt) { +func (w *lintUncheckedTypeAssertion) handleSwitch(n *ast.SwitchStmt) { w.requireNoTypeAssert(n.Tag) w.requireBinaryExpressionWithoutTypeAssertion(n.Tag) } -func (w *lintUnchekedTypeAssertion) handleAssignment(n *ast.AssignStmt) { +func (w *lintUncheckedTypeAssertion) handleAssignment(n *ast.AssignStmt) { if len(n.Rhs) == 0 { return } @@ -148,21 +148,21 @@ func (w *lintUnchekedTypeAssertion) handleAssignment(n *ast.AssignStmt) { } // handles "return foo(.*bar)" - one of them is enough to fail as golang does not forward the type cast tuples in return statements -func (w *lintUnchekedTypeAssertion) handleReturn(n *ast.ReturnStmt) { +func (w *lintUncheckedTypeAssertion) handleReturn(n *ast.ReturnStmt) { for _, r := range n.Results { w.requireNoTypeAssert(r) } } -func (w *lintUnchekedTypeAssertion) handleRange(n *ast.RangeStmt) { +func (w *lintUncheckedTypeAssertion) handleRange(n *ast.RangeStmt) { w.requireNoTypeAssert(n.X) } -func (w *lintUnchekedTypeAssertion) handleChannelSend(n *ast.SendStmt) { +func (w *lintUncheckedTypeAssertion) handleChannelSend(n *ast.SendStmt) { w.requireNoTypeAssert(n.Value) } -func (w *lintUnchekedTypeAssertion) Visit(node ast.Node) ast.Visitor { +func (w *lintUncheckedTypeAssertion) Visit(node ast.Node) ast.Visitor { switch n := node.(type) { case *ast.RangeStmt: w.handleRange(n) @@ -183,7 +183,7 @@ func (w *lintUnchekedTypeAssertion) Visit(node ast.Node) ast.Visitor { return w } -func (w *lintUnchekedTypeAssertion) addFailure(n *ast.TypeAssertExpr, why string) { +func (w *lintUncheckedTypeAssertion) addFailure(n *ast.TypeAssertExpr, why string) { s := fmt.Sprintf("type cast result is unchecked in %v - %s", gofmt(n), why) w.onFailure(lint.Failure{ Category: "bad practice", diff --git a/vendor/github.com/mgechev/revive/rule/unconditional-recursion.go b/vendor/github.com/mgechev/revive/rule/unconditional-recursion.go index 9ac2648cd..d806b6757 100644 --- a/vendor/github.com/mgechev/revive/rule/unconditional-recursion.go +++ b/vendor/github.com/mgechev/revive/rule/unconditional-recursion.go @@ -185,9 +185,10 @@ func (lintUnconditionalRecursionRule) hasControlExit(node ast.Node) bool { return false } - fn := se.Sel.Name - pkg := id.Name - if exitFunctions[pkg] != nil && exitFunctions[pkg][fn] { // it's a call to an exit function + functionName := se.Sel.Name + pkgName := id.Name + isCallToExitFunction := exitFunctions[pkgName] != nil && exitFunctions[pkgName][functionName] + if isCallToExitFunction { return true } } diff --git a/vendor/github.com/mgechev/revive/rule/unhandled-error.go b/vendor/github.com/mgechev/revive/rule/unhandled-error.go index ce6fa3864..95ba56180 100644 --- a/vendor/github.com/mgechev/revive/rule/unhandled-error.go +++ b/vendor/github.com/mgechev/revive/rule/unhandled-error.go @@ -19,27 +19,30 @@ type UnhandledErrorRule struct { func (r *UnhandledErrorRule) configure(arguments lint.Arguments) { r.Lock() - if r.ignoreList == nil { - for _, arg := range arguments { - argStr, ok := arg.(string) - if !ok { - panic(fmt.Sprintf("Invalid argument to the unhandled-error rule. Expecting a string, got %T", arg)) - } + defer r.Unlock() - argStr = strings.Trim(argStr, " ") - if argStr == "" { - panic("Invalid argument to the unhandled-error rule, expected regular expression must not be empty.") - } + if r.ignoreList != nil { + return // already configured + } - exp, err := regexp.Compile(argStr) - if err != nil { - panic(fmt.Sprintf("Invalid argument to the unhandled-error rule: regexp %q does not compile: %v", argStr, err)) - } + for _, arg := range arguments { + argStr, ok := arg.(string) + if !ok { + panic(fmt.Sprintf("Invalid argument to the unhandled-error rule. Expecting a string, got %T", arg)) + } - r.ignoreList = append(r.ignoreList, exp) + argStr = strings.Trim(argStr, " ") + if argStr == "" { + panic("Invalid argument to the unhandled-error rule, expected regular expression must not be empty.") } + + exp, err := regexp.Compile(argStr) + if err != nil { + panic(fmt.Sprintf("Invalid argument to the unhandled-error rule: regexp %q does not compile: %v", argStr, err)) + } + + r.ignoreList = append(r.ignoreList, exp) } - r.Unlock() } // Apply applies the rule to given file. @@ -130,9 +133,9 @@ func (w *lintUnhandledErrors) funcName(call *ast.CallExpr) string { } name := fn.FullName() - name = strings.Replace(name, "(", "", -1) - name = strings.Replace(name, ")", "", -1) - name = strings.Replace(name, "*", "", -1) + name = strings.ReplaceAll(name, "(", "") + name = strings.ReplaceAll(name, ")", "") + name = strings.ReplaceAll(name, "*", "") return name } diff --git a/vendor/github.com/mgechev/revive/rule/use-any.go b/vendor/github.com/mgechev/revive/rule/use-any.go index bdf3c936d..88160c2fa 100644 --- a/vendor/github.com/mgechev/revive/rule/use-any.go +++ b/vendor/github.com/mgechev/revive/rule/use-any.go @@ -47,7 +47,7 @@ func (w lintUseAny) Visit(n ast.Node) ast.Visitor { Node: n, Confidence: 1, Category: "naming", - Failure: "since GO 1.18 'interface{}' can be replaced by 'any'", + Failure: "since Go 1.18 'interface{}' can be replaced by 'any'", }) return w diff --git a/vendor/github.com/mgechev/revive/rule/var-declarations.go b/vendor/github.com/mgechev/revive/rule/var-declarations.go index a15ff1eb4..3f9d7068a 100644 --- a/vendor/github.com/mgechev/revive/rule/var-declarations.go +++ b/vendor/github.com/mgechev/revive/rule/var-declarations.go @@ -46,13 +46,15 @@ type lintVarDeclarations struct { func (w *lintVarDeclarations) Visit(node ast.Node) ast.Visitor { switch v := node.(type) { case *ast.GenDecl: - if v.Tok != token.CONST && v.Tok != token.VAR { + isVarOrConstDeclaration := v.Tok == token.CONST || v.Tok == token.VAR + if !isVarOrConstDeclaration { return nil } w.lastGen = v return w case *ast.ValueSpec: - if w.lastGen.Tok == token.CONST { + isConstDeclaration := w.lastGen.Tok == token.CONST + if isConstDeclaration { return nil } if len(v.Names) > 1 || v.Type == nil || len(v.Values) == 0 { @@ -64,14 +66,14 @@ func (w *lintVarDeclarations) Visit(node ast.Node) ast.Visitor { if isIdent(v.Names[0], "_") { return nil } - // If the RHS is a zero value, suggest dropping it. - zero := false + // If the RHS is a isZero value, suggest dropping it. + isZero := false if lit, ok := rhs.(*ast.BasicLit); ok { - zero = zeroLiteral[lit.Value] + isZero = zeroLiteral[lit.Value] } else if isIdent(rhs, "nil") { - zero = true + isZero = true } - if zero { + if isZero { w.onFailure(lint.Failure{ Confidence: 0.9, Node: rhs, diff --git a/vendor/github.com/mgechev/revive/rule/var-naming.go b/vendor/github.com/mgechev/revive/rule/var-naming.go index e91c22dc2..5a4d0dc24 100644 --- a/vendor/github.com/mgechev/revive/rule/var-naming.go +++ b/vendor/github.com/mgechev/revive/rule/var-naming.go @@ -19,9 +19,9 @@ var upperCaseConstRE = regexp.MustCompile(`^_?[A-Z][A-Z\d]*(_[A-Z\d]+)*$`) // VarNamingRule lints given else constructs. type VarNamingRule struct { configured bool - allowlist []string - blocklist []string - upperCaseConst bool // if true - allows to use UPPER_SOME_NAMES for constants + allowList []string + blockList []string + allowUpperCaseConst bool // if true - allows to use UPPER_SOME_NAMES for constants skipPackageNameChecks bool sync.Mutex } @@ -35,11 +35,11 @@ func (r *VarNamingRule) configure(arguments lint.Arguments) { r.configured = true if len(arguments) >= 1 { - r.allowlist = getList(arguments[0], "allowlist") + r.allowList = getList(arguments[0], "allowlist") } if len(arguments) >= 2 { - r.blocklist = getList(arguments[1], "blocklist") + r.blockList = getList(arguments[1], "blocklist") } if len(arguments) >= 3 { @@ -56,7 +56,7 @@ func (r *VarNamingRule) configure(arguments lint.Arguments) { if !ok { panic(fmt.Sprintf("Invalid third argument to the var-naming rule. Expecting a %s of type slice, of len==1, with map, but %T", "options", asSlice[0])) } - r.upperCaseConst = fmt.Sprint(args["upperCaseConst"]) == "true" + r.allowUpperCaseConst = fmt.Sprint(args["upperCaseConst"]) == "true" r.skipPackageNameChecks = fmt.Sprint(args["skipPackageNameChecks"]) == "true" } } @@ -79,7 +79,6 @@ func (r *VarNamingRule) applyPackageCheckRules(walker *lintNames) { Category: "naming", }) } - } // Apply applies the rule to given file. @@ -93,12 +92,12 @@ func (r *VarNamingRule) Apply(file *lint.File, arguments lint.Arguments) []lint. walker := lintNames{ file: file, fileAst: fileAst, - allowlist: r.allowlist, - blocklist: r.blocklist, + allowList: r.allowList, + blockList: r.blockList, onFailure: func(failure lint.Failure) { failures = append(failures, failure) }, - upperCaseConst: r.upperCaseConst, + upperCaseConst: r.allowUpperCaseConst, } if !r.skipPackageNameChecks { @@ -151,7 +150,7 @@ func (w *lintNames) check(id *ast.Ident, thing string) { return } - should := lint.Name(id.Name, w.allowlist, w.blocklist) + should := lint.Name(id.Name, w.allowList, w.blockList) if id.Name == should { return } @@ -177,8 +176,8 @@ type lintNames struct { file *lint.File fileAst *ast.File onFailure func(lint.Failure) - allowlist []string - blocklist []string + allowList []string + blockList []string upperCaseConst bool } @@ -265,17 +264,17 @@ func (w *lintNames) Visit(n ast.Node) ast.Visitor { } func getList(arg any, argName string) []string { - temp, ok := arg.([]any) + args, ok := arg.([]any) if !ok { panic(fmt.Sprintf("Invalid argument to the var-naming rule. Expecting a %s of type slice with initialisms, got %T", argName, arg)) } var list []string - for _, v := range temp { - if val, ok := v.(string); ok { - list = append(list, val) - } else { + for _, v := range args { + val, ok := v.(string) + if !ok { panic(fmt.Sprintf("Invalid %s values of the var-naming rule. Expecting slice of strings but got element of type %T", val, arg)) } + list = append(list, val) } return list } diff --git a/vendor/github.com/mgechev/revive/rule/waitgroup-by-value.go b/vendor/github.com/mgechev/revive/rule/waitgroup-by-value.go index 98644f41c..a2d304ae5 100644 --- a/vendor/github.com/mgechev/revive/rule/waitgroup-by-value.go +++ b/vendor/github.com/mgechev/revive/rule/waitgroup-by-value.go @@ -51,7 +51,7 @@ func (w lintWaitGroupByValueRule) Visit(node ast.Node) ast.Visitor { }) } - return nil + return nil // skip visiting function body } func (lintWaitGroupByValueRule) isWaitGroup(ft ast.Expr) bool { -- cgit mrf-deployment