From 31fbdb18332df7d1db76f8223e5dfb0285cd46aa Mon Sep 17 00:00:00 2001 From: chavacava Date: Sun, 10 Apr 2022 09:06:59 +0200 Subject: [PATCH] Fix/677 (#678) --- Makefile | 2 +- lint/file.go | 2 +- lint/linter.go | 1 - lint/package.go | 53 +++++++++++++------ rule/add-constant.go | 95 +++++++++++++++++++---------------- rule/argument-limit.go | 21 +++++--- rule/atomic.go | 2 +- rule/banned-characters.go | 13 ++++- rule/cognitive-complexity.go | 13 ++++- rule/context-as-argument.go | 7 +++ rule/context-keys-type.go | 2 +- rule/cyclomatic.go | 13 ++++- rule/defer.go | 16 ++++-- rule/exported.go | 29 +++++++---- rule/file-header.go | 12 ++++- rule/function-length.go | 12 ++++- rule/function-result-limit.go | 12 ++++- rule/imports-blacklist.go | 24 ++++++--- rule/line-length-limit.go | 13 ++++- rule/max-public-structs.go | 13 ++++- rule/nested-structs.go | 6 +-- rule/unhandled-error.go | 16 ++++-- rule/var-naming.go | 17 +++++-- 23 files changed, 275 insertions(+), 119 deletions(-) diff --git a/Makefile b/Makefile index 6def06e..645a2db 100644 --- a/Makefile +++ b/Makefile @@ -15,5 +15,5 @@ build: @go build -ldflags='$(VERSION_FLAGS)' test: - @go test -v ./... + @go test -v -race ./... diff --git a/lint/file.go b/lint/file.go index f859da6..339dcee 100644 --- a/lint/file.go +++ b/lint/file.go @@ -77,7 +77,7 @@ func (f *File) IsUntypedConst(expr ast.Expr) (defType string, ok bool) { // Re-evaluate expr outside its context to see if it's untyped. // (An expr evaluated within, for example, an assignment context will get the type of the LHS.) exprStr := f.Render(expr) - tv, err := types.Eval(f.Pkg.fset, f.Pkg.TypesPkg, expr.Pos(), exprStr) + tv, err := types.Eval(f.Pkg.fset, f.Pkg.TypesPkg(), expr.Pos(), exprStr) if err != nil { return "", false } diff --git a/lint/linter.go b/lint/linter.go index 2743b7d..dddce18 100644 --- a/lint/linter.go +++ b/lint/linter.go @@ -81,7 +81,6 @@ func (l *Linter) lintPackage(filenames []string, ruleSet []Rule, config Config, pkg := &Package{ fset: token.NewFileSet(), files: map[string]*File{}, - mu: sync.Mutex{}, } for _, filename := range filenames { content, err := l.readFile(filename) diff --git a/lint/package.go b/lint/package.go index 7b6046f..7cfcab3 100644 --- a/lint/package.go +++ b/lint/package.go @@ -14,14 +14,14 @@ type Package struct { fset *token.FileSet files map[string]*File - TypesPkg *types.Package - TypesInfo *types.Info + typesPkg *types.Package + typesInfo *types.Info // sortable is the set of types in the package that implement sort.Interface. - Sortable map[string]bool + sortable map[string]bool // main is whether this is a "main" package. main int - mu sync.Mutex + sync.RWMutex } var newImporter = func(fset *token.FileSet) types.ImporterFrom { @@ -36,6 +36,9 @@ var ( // IsMain returns if that's the main package. func (p *Package) IsMain() bool { + p.Lock() + defer p.Unlock() + if p.main == trueValue { return true } else if p.main == falseValue { @@ -51,13 +54,35 @@ func (p *Package) IsMain() bool { return false } +// TypesPkg yields information on this package +func (p *Package) TypesPkg() *types.Package { + p.RLock() + defer p.RUnlock() + return p.typesPkg +} + +// TypesInfo yields type information of this package identifiers +func (p *Package) TypesInfo() *types.Info { + p.RLock() + defer p.RUnlock() + return p.typesInfo +} + +// Sortable yields a map of sortable types in this package +func (p *Package) Sortable() map[string]bool { + p.RLock() + defer p.RUnlock() + return p.sortable +} + // TypeCheck performs type checking for given package. func (p *Package) TypeCheck() error { - p.mu.Lock() + p.Lock() + defer p.Unlock() + // If type checking has already been performed // skip it. - if p.TypesInfo != nil || p.TypesPkg != nil { - p.mu.Unlock() + if p.typesInfo != nil || p.typesPkg != nil { return nil } config := &types.Config{ @@ -82,9 +107,9 @@ func (p *Package) TypeCheck() error { // Remember the typechecking info, even if config.Check failed, // since we will get partial information. - p.TypesPkg = typesPkg - p.TypesInfo = info - p.mu.Unlock() + p.typesPkg = typesPkg + p.typesInfo = info + return err } @@ -104,10 +129,10 @@ func check(config *types.Config, n string, fset *token.FileSet, astFiles []*ast. // TypeOf returns the type of an expression. func (p *Package) TypeOf(expr ast.Expr) types.Type { - if p.TypesInfo == nil { + if p.typesInfo == nil { return nil } - return p.TypesInfo.TypeOf(expr) + return p.typesInfo.TypeOf(expr) } type walker struct { @@ -129,7 +154,7 @@ func (w *walker) Visit(n ast.Node) ast.Visitor { } func (p *Package) scanSortable() { - p.Sortable = make(map[string]bool) + p.sortable = make(map[string]bool) // bitfield for which methods exist on each type. const ( @@ -144,7 +169,7 @@ func (p *Package) scanSortable() { } for typ, ms := range has { if ms == Len|Less|Swap { - p.Sortable[typ] = true + p.sortable[typ] = true } } } diff --git a/rule/add-constant.go b/rule/add-constant.go index 530e2e9..7ffd23f 100644 --- a/rule/add-constant.go +++ b/rule/add-constant.go @@ -5,6 +5,7 @@ import ( "go/ast" "strconv" "strings" + "sync" "github.com/mgechev/revive/lint" ) @@ -33,53 +34,12 @@ func (wl whiteList) add(kind, list string) { type AddConstantRule struct { whiteList whiteList strLitLimit int + sync.Mutex } // Apply applies the rule to given file. func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { - if r.whiteList == nil { - r.strLitLimit = defaultStrLitLimit - r.whiteList = newWhiteList() - if len(arguments) > 0 { - args, ok := arguments[0].(map[string]interface{}) - if !ok { - panic(fmt.Sprintf("Invalid argument to the add-constant rule. Expecting a k,v map, got %T", arguments[0])) - } - for k, v := range args { - kind := "" - switch k { - case "allowFloats": - kind = kindFLOAT - fallthrough - case "allowInts": - if kind == "" { - kind = kindINT - } - fallthrough - case "allowStrs": - if kind == "" { - kind = kindSTRING - } - list, ok := v.(string) - if !ok { - panic(fmt.Sprintf("Invalid argument to the add-constant rule, string expected. Got '%v' (%T)", v, v)) - } - r.whiteList.add(kind, list) - case "maxLitCount": - sl, ok := v.(string) - if !ok { - panic(fmt.Sprintf("Invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v' (%T)", v, v)) - } - - limit, err := strconv.Atoi(sl) - if err != nil { - panic(fmt.Sprintf("Invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v'", v)) - } - r.strLitLimit = limit - } - } - } - } + r.configure(arguments) var failures []lint.Failure @@ -154,3 +114,52 @@ func (w lintAddConstantRule) checkNumLit(kind string, n *ast.BasicLit) { Failure: fmt.Sprintf("avoid magic numbers like '%s', create a named constant for it", n.Value), }) } + +func (r *AddConstantRule) configure(arguments lint.Arguments) { + r.Lock() + defer r.Unlock() + + if r.whiteList == nil { + r.strLitLimit = defaultStrLitLimit + r.whiteList = newWhiteList() + if len(arguments) > 0 { + args, ok := arguments[0].(map[string]interface{}) + if !ok { + panic(fmt.Sprintf("Invalid argument to the add-constant rule. Expecting a k,v map, got %T", arguments[0])) + } + for k, v := range args { + kind := "" + switch k { + case "allowFloats": + kind = kindFLOAT + fallthrough + case "allowInts": + if kind == "" { + kind = kindINT + } + fallthrough + case "allowStrs": + if kind == "" { + kind = kindSTRING + } + list, ok := v.(string) + if !ok { + panic(fmt.Sprintf("Invalid argument to the add-constant rule, string expected. Got '%v' (%T)", v, v)) + } + r.whiteList.add(kind, list) + case "maxLitCount": + sl, ok := v.(string) + if !ok { + panic(fmt.Sprintf("Invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v' (%T)", v, v)) + } + + limit, err := strconv.Atoi(sl) + if err != nil { + panic(fmt.Sprintf("Invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v'", v)) + } + r.strLitLimit = limit + } + } + } + } +} diff --git a/rule/argument-limit.go b/rule/argument-limit.go index b30df3b..f3be2c0 100644 --- a/rule/argument-limit.go +++ b/rule/argument-limit.go @@ -3,6 +3,7 @@ package rule import ( "fmt" "go/ast" + "sync" "github.com/mgechev/revive/lint" ) @@ -10,10 +11,11 @@ import ( // ArgumentsLimitRule lints given else constructs. type ArgumentsLimitRule struct { total int + sync.Mutex } -// Apply applies the rule to given file. -func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { +func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) { + r.Lock() if r.total == 0 { checkNumberOfArguments(1, arguments, r.Name()) @@ -23,14 +25,21 @@ func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) [] } r.total = int(total) } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) var failures []lint.Failure + onFailure := func(failure lint.Failure) { + failures = append(failures, failure) + } walker := lintArgsNum{ - total: r.total, - onFailure: func(failure lint.Failure) { - failures = append(failures, failure) - }, + total: r.total, + onFailure: onFailure, } ast.Walk(walker, file.AST) diff --git a/rule/atomic.go b/rule/atomic.go index 572e141..5238d08 100644 --- a/rule/atomic.go +++ b/rule/atomic.go @@ -15,7 +15,7 @@ type AtomicRule struct{} func (r *AtomicRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { var failures []lint.Failure walker := atomic{ - pkgTypesInfo: file.Pkg.TypesInfo, + pkgTypesInfo: file.Pkg.TypesInfo(), onFailure: func(failure lint.Failure) { failures = append(failures, failure) }, diff --git a/rule/banned-characters.go b/rule/banned-characters.go index 6911574..15c04ef 100644 --- a/rule/banned-characters.go +++ b/rule/banned-characters.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" "strings" + "sync" "github.com/mgechev/revive/lint" ) @@ -11,16 +12,23 @@ import ( // BannedCharsRule checks if a file contains banned characters. type BannedCharsRule struct { bannedCharList []string + sync.Mutex } const bannedCharsRuleName = "banned-characters" -// Apply applied the rule to the given file. -func (r *BannedCharsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { +func (r *BannedCharsRule) configure(arguments lint.Arguments) { + r.Lock() if r.bannedCharList == nil { checkNumberOfArguments(1, arguments, bannedCharsRuleName) r.bannedCharList = r.getBannedCharsList(arguments) } + r.Unlock() +} + +// Apply applied the rule to the given file. +func (r *BannedCharsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) var failures []lint.Failure onFailure := func(failure lint.Failure) { @@ -31,6 +39,7 @@ func (r *BannedCharsRule) Apply(file *lint.File, arguments lint.Arguments) []lin bannedChars: r.bannedCharList, onFailure: onFailure, } + ast.Walk(w, file.AST) return failures } diff --git a/rule/cognitive-complexity.go b/rule/cognitive-complexity.go index ed7481f..94bf000 100644 --- a/rule/cognitive-complexity.go +++ b/rule/cognitive-complexity.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" "go/token" + "sync" "github.com/mgechev/revive/lint" "golang.org/x/tools/go/ast/astutil" @@ -12,10 +13,11 @@ import ( // CognitiveComplexityRule lints given else constructs. type CognitiveComplexityRule struct { maxComplexity int + sync.Mutex } -// Apply applies the rule to given file. -func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { +func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) { + r.Lock() if r.maxComplexity == 0 { checkNumberOfArguments(1, arguments, r.Name()) @@ -25,8 +27,15 @@ func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Argument } r.maxComplexity = int(complexity) } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) var failures []lint.Failure + linter := cognitiveComplexityLinter{ file: file, maxComplexity: r.maxComplexity, diff --git a/rule/context-as-argument.go b/rule/context-as-argument.go index 0942629..6b2c381 100644 --- a/rule/context-as-argument.go +++ b/rule/context-as-argument.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" "strings" + "sync" "github.com/mgechev/revive/lint" ) @@ -11,21 +12,27 @@ import ( // ContextAsArgumentRule lints given else constructs. type ContextAsArgumentRule struct { allowTypesLUT map[string]struct{} + sync.Mutex } // Apply applies the rule to given file. func (r *ContextAsArgumentRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { + + r.Lock() if r.allowTypesLUT == nil { r.allowTypesLUT = getAllowTypesFromArguments(args) } + r.Unlock() var failures []lint.Failure + r.Lock() walker := lintContextArguments{ allowTypesLUT: r.allowTypesLUT, onFailure: func(failure lint.Failure) { failures = append(failures, failure) }, } + r.Unlock() ast.Walk(walker, file.AST) diff --git a/rule/context-keys-type.go b/rule/context-keys-type.go index 9c2f0bb..10e4ff2 100644 --- a/rule/context-keys-type.go +++ b/rule/context-keys-type.go @@ -68,7 +68,7 @@ func checkContextKeyType(w lintContextKeyTypes, x *ast.CallExpr) { if len(x.Args) != 3 { return } - key := f.Pkg.TypesInfo.Types[x.Args[1]] + key := f.Pkg.TypesInfo().Types[x.Args[1]] if ktyp, ok := key.Type.(*types.Basic); ok && ktyp.Kind() != types.Invalid { w.onFailure(lint.Failure{ diff --git a/rule/cyclomatic.go b/rule/cyclomatic.go index bdda5f5..fc372c3 100644 --- a/rule/cyclomatic.go +++ b/rule/cyclomatic.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" "go/token" + "sync" "github.com/mgechev/revive/lint" ) @@ -13,10 +14,11 @@ import ( // CyclomaticRule lints given else constructs. type CyclomaticRule struct { maxComplexity int + sync.Mutex } -// Apply applies the rule to given file. -func (r *CyclomaticRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { +func (r *CyclomaticRule) configure(arguments lint.Arguments) { + r.Lock() if r.maxComplexity == 0 { checkNumberOfArguments(1, arguments, r.Name()) @@ -26,9 +28,16 @@ func (r *CyclomaticRule) Apply(file *lint.File, arguments lint.Arguments) []lint } r.maxComplexity = int(complexity) } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *CyclomaticRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) var failures []lint.Failure fileAst := file.AST + walker := lintCyclomatic{ file: file, complexity: r.maxComplexity, diff --git a/rule/defer.go b/rule/defer.go index 4b62f34..bb87cc6 100644 --- a/rule/defer.go +++ b/rule/defer.go @@ -3,6 +3,7 @@ package rule import ( "fmt" "go/ast" + "sync" "github.com/mgechev/revive/lint" ) @@ -10,18 +11,25 @@ import ( // DeferRule lints unused params in functions. type DeferRule struct { allow map[string]bool + sync.Mutex +} + +func (r *DeferRule) configure(arguments lint.Arguments) { + r.Lock() + if r.allow == nil { + r.allow = r.allowFromArgs(arguments) + } + r.Unlock() } // Apply applies the rule to given file. func (r *DeferRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { - if r.allow == nil { - r.allow = r.allowFromArgs(arguments) - } + r.configure(arguments) + var failures []lint.Failure onFailure := func(failure lint.Failure) { failures = append(failures, failure) } - w := lintDeferRule{onFailure: onFailure, allow: r.allow} ast.Walk(w, file.AST) diff --git a/rule/exported.go b/rule/exported.go index 621fae5..022ce6f 100644 --- a/rule/exported.go +++ b/rule/exported.go @@ -5,6 +5,7 @@ import ( "go/ast" "go/token" "strings" + "sync" "unicode" "unicode/utf8" @@ -17,19 +18,14 @@ type ExportedRule struct { checkPrivateReceivers bool disableStutteringCheck bool stuttersMsg string + sync.Mutex } -// Apply applies the rule to given file. -func (r *ExportedRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { - var failures []lint.Failure - - if file.IsTest() { - return failures - } - +func (r *ExportedRule) configure(arguments lint.Arguments) { + r.Lock() if !r.configured { var sayRepetitiveInsteadOfStutters bool - r.checkPrivateReceivers, r.disableStutteringCheck, sayRepetitiveInsteadOfStutters = r.getConf(args) + r.checkPrivateReceivers, r.disableStutteringCheck, sayRepetitiveInsteadOfStutters = r.getConf(arguments) r.stuttersMsg = "stutters" if sayRepetitiveInsteadOfStutters { r.stuttersMsg = "is repetitive" @@ -37,8 +33,20 @@ func (r *ExportedRule) Apply(file *lint.File, args lint.Arguments) []lint.Failur r.configured = true } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *ExportedRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { + r.configure(args) + + var failures []lint.Failure + if file.IsTest() { + return failures + } fileAst := file.AST + walker := lintExported{ file: file, fileAst: fileAst, @@ -118,7 +126,8 @@ func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) { } switch name { case "Len", "Less", "Swap": - if w.file.Pkg.Sortable[recv] { + sortables := w.file.Pkg.Sortable() + if sortables[recv] { return } } diff --git a/rule/file-header.go b/rule/file-header.go index 17fd9ff..5070ceb 100644 --- a/rule/file-header.go +++ b/rule/file-header.go @@ -3,6 +3,7 @@ package rule import ( "fmt" "regexp" + "sync" "github.com/mgechev/revive/lint" ) @@ -10,6 +11,7 @@ import ( // FileHeaderRule lints given else constructs. type FileHeaderRule struct { header string + sync.Mutex } var ( @@ -17,8 +19,8 @@ var ( singleRegexp = regexp.MustCompile("^//") ) -// Apply applies the rule to given file. -func (r *FileHeaderRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { +func (r *FileHeaderRule) configure(arguments lint.Arguments) { + r.Lock() if r.header == "" { checkNumberOfArguments(1, arguments, r.Name()) var ok bool @@ -27,6 +29,12 @@ func (r *FileHeaderRule) Apply(file *lint.File, arguments lint.Arguments) []lint panic(fmt.Sprintf("invalid argument for \"file-header\" rule: first argument should be a string, got %T", arguments[0])) } } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *FileHeaderRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) failure := []lint.Failure{ { diff --git a/rule/function-length.go b/rule/function-length.go index b213cc4..9621419 100644 --- a/rule/function-length.go +++ b/rule/function-length.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" "reflect" + "sync" "github.com/mgechev/revive/lint" ) @@ -12,15 +13,22 @@ import ( type FunctionLength struct { maxStmt int maxLines int + sync.Mutex } -// Apply applies the rule to given file. -func (r *FunctionLength) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { +func (r *FunctionLength) configure(arguments lint.Arguments) { + r.Lock() if r.maxLines == 0 { maxStmt, maxLines := r.parseArguments(arguments) r.maxStmt = int(maxStmt) r.maxLines = int(maxLines) } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *FunctionLength) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) var failures []lint.Failure diff --git a/rule/function-result-limit.go b/rule/function-result-limit.go index 5f715dd..58606c6 100644 --- a/rule/function-result-limit.go +++ b/rule/function-result-limit.go @@ -3,6 +3,7 @@ package rule import ( "fmt" "go/ast" + "sync" "github.com/mgechev/revive/lint" ) @@ -10,10 +11,11 @@ import ( // FunctionResultsLimitRule lints given else constructs. type FunctionResultsLimitRule struct { max int + sync.Mutex } -// Apply applies the rule to given file. -func (r *FunctionResultsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { +func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) { + r.Lock() if r.max == 0 { checkNumberOfArguments(1, arguments, r.Name()) @@ -26,6 +28,12 @@ func (r *FunctionResultsLimitRule) Apply(file *lint.File, arguments lint.Argumen } r.max = int(max) } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *FunctionResultsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) var failures []lint.Failure diff --git a/rule/imports-blacklist.go b/rule/imports-blacklist.go index 68beb73..8ef74ac 100644 --- a/rule/imports-blacklist.go +++ b/rule/imports-blacklist.go @@ -2,6 +2,7 @@ package rule import ( "fmt" + "sync" "github.com/mgechev/revive/lint" ) @@ -9,16 +10,11 @@ import ( // ImportsBlacklistRule lints given else constructs. type ImportsBlacklistRule struct { blacklist map[string]bool + sync.Mutex } -// Apply applies the rule to given file. -func (r *ImportsBlacklistRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { - var failures []lint.Failure - - if file.IsTest() { - return failures // skip, test file - } - +func (r *ImportsBlacklistRule) configure(arguments lint.Arguments) { + r.Lock() if r.blacklist == nil { r.blacklist = make(map[string]bool, len(arguments)) @@ -34,6 +30,18 @@ func (r *ImportsBlacklistRule) Apply(file *lint.File, arguments lint.Arguments) r.blacklist[argStr] = true } } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *ImportsBlacklistRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) + + var failures []lint.Failure + + if file.IsTest() { + return failures // skip, test file + } for _, is := range file.AST.Imports { path := is.Path diff --git a/rule/line-length-limit.go b/rule/line-length-limit.go index c517732..56beba5 100644 --- a/rule/line-length-limit.go +++ b/rule/line-length-limit.go @@ -6,6 +6,7 @@ import ( "fmt" "go/token" "strings" + "sync" "unicode/utf8" "github.com/mgechev/revive/lint" @@ -14,10 +15,11 @@ import ( // LineLengthLimitRule lints given else constructs. type LineLengthLimitRule struct { max int + sync.Mutex } -// Apply applies the rule to given file. -func (r *LineLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { +func (r *LineLengthLimitRule) configure(arguments lint.Arguments) { + r.Lock() if r.max == 0 { checkNumberOfArguments(1, arguments, r.Name()) @@ -28,8 +30,15 @@ func (r *LineLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) [ r.max = int(max) } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *LineLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) var failures []lint.Failure + checker := lintLineLengthNum{ max: r.max, file: file, diff --git a/rule/max-public-structs.go b/rule/max-public-structs.go index 2a5fa7b..42f4a5a 100644 --- a/rule/max-public-structs.go +++ b/rule/max-public-structs.go @@ -3,6 +3,7 @@ package rule import ( "go/ast" "strings" + "sync" "github.com/mgechev/revive/lint" ) @@ -10,10 +11,11 @@ import ( // MaxPublicStructsRule lints given else constructs. type MaxPublicStructsRule struct { max int64 + sync.Mutex } -// Apply applies the rule to given file. -func (r *MaxPublicStructsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { +func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) { + r.Lock() if r.max < 1 { checkNumberOfArguments(1, arguments, r.Name()) @@ -23,10 +25,17 @@ func (r *MaxPublicStructsRule) Apply(file *lint.File, arguments lint.Arguments) } r.max = max } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *MaxPublicStructsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) var failures []lint.Failure fileAst := file.AST + walker := &lintMaxPublicStructs{ fileAst: fileAst, onFailure: func(failure lint.Failure) { diff --git a/rule/nested-structs.go b/rule/nested-structs.go index deb202e..5bd4972 100644 --- a/rule/nested-structs.go +++ b/rule/nested-structs.go @@ -10,13 +10,9 @@ import ( type NestedStructs struct{} // Apply applies the rule to given file. -func (r *NestedStructs) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { +func (r *NestedStructs) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { var failures []lint.Failure - if len(arguments) > 0 { - panic(r.Name() + " doesn't take any arguments") - } - walker := &lintNestedStructs{ fileAST: file.AST, onFailure: func(failure lint.Failure) { diff --git a/rule/unhandled-error.go b/rule/unhandled-error.go index 4321714..09cc6ca 100644 --- a/rule/unhandled-error.go +++ b/rule/unhandled-error.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" "go/types" + "sync" "github.com/mgechev/revive/lint" ) @@ -11,16 +12,17 @@ import ( // UnhandledErrorRule lints given else constructs. type UnhandledErrorRule struct { ignoreList ignoreListType + sync.Mutex } type ignoreListType map[string]struct{} -// Apply applies the rule to given file. -func (r *UnhandledErrorRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { +func (r *UnhandledErrorRule) configure(arguments lint.Arguments) { + r.Lock() if r.ignoreList == nil { - r.ignoreList = make(ignoreListType, len(args)) + r.ignoreList = make(ignoreListType, len(arguments)) - for _, arg := range args { + 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)) @@ -29,6 +31,12 @@ func (r *UnhandledErrorRule) Apply(file *lint.File, args lint.Arguments) []lint. r.ignoreList[argStr] = struct{}{} } } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *UnhandledErrorRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { + r.configure(args) var failures []lint.Failure diff --git a/rule/var-naming.go b/rule/var-naming.go index 1de8608..3c1478a 100644 --- a/rule/var-naming.go +++ b/rule/var-naming.go @@ -5,6 +5,7 @@ import ( "go/ast" "go/token" "strings" + "sync" "github.com/mgechev/revive/lint" ) @@ -14,12 +15,11 @@ type VarNamingRule struct { configured bool whitelist []string blacklist []string + sync.Mutex } -// Apply applies the rule to given file. -func (r *VarNamingRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { - var failures []lint.Failure - +func (r *VarNamingRule) configure(arguments lint.Arguments) { + r.Lock() if !r.configured { if len(arguments) >= 1 { r.whitelist = getList(arguments[0], "whitelist") @@ -30,8 +30,17 @@ func (r *VarNamingRule) Apply(file *lint.File, arguments lint.Arguments) []lint. } r.configured = true } + r.Unlock() +} + +// Apply applies the rule to given file. +func (r *VarNamingRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + r.configure(arguments) + + var failures []lint.Failure fileAst := file.AST + walker := lintNames{ file: file, fileAst: fileAst,