1
0
mirror of https://github.com/mgechev/revive.git synced 2024-11-21 17:16:40 +02:00
This commit is contained in:
chavacava 2022-04-10 09:06:59 +02:00 committed by GitHub
parent b9814276b6
commit 31fbdb1833
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 275 additions and 119 deletions

View File

@ -15,5 +15,5 @@ build:
@go build -ldflags='$(VERSION_FLAGS)' @go build -ldflags='$(VERSION_FLAGS)'
test: test:
@go test -v ./... @go test -v -race ./...

View File

@ -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. // 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.) // (An expr evaluated within, for example, an assignment context will get the type of the LHS.)
exprStr := f.Render(expr) 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 { if err != nil {
return "", false return "", false
} }

View File

@ -81,7 +81,6 @@ func (l *Linter) lintPackage(filenames []string, ruleSet []Rule, config Config,
pkg := &Package{ pkg := &Package{
fset: token.NewFileSet(), fset: token.NewFileSet(),
files: map[string]*File{}, files: map[string]*File{},
mu: sync.Mutex{},
} }
for _, filename := range filenames { for _, filename := range filenames {
content, err := l.readFile(filename) content, err := l.readFile(filename)

View File

@ -14,14 +14,14 @@ type Package struct {
fset *token.FileSet fset *token.FileSet
files map[string]*File files map[string]*File
TypesPkg *types.Package typesPkg *types.Package
TypesInfo *types.Info typesInfo *types.Info
// sortable is the set of types in the package that implement sort.Interface. // 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 is whether this is a "main" package.
main int main int
mu sync.Mutex sync.RWMutex
} }
var newImporter = func(fset *token.FileSet) types.ImporterFrom { var newImporter = func(fset *token.FileSet) types.ImporterFrom {
@ -36,6 +36,9 @@ var (
// IsMain returns if that's the main package. // IsMain returns if that's the main package.
func (p *Package) IsMain() bool { func (p *Package) IsMain() bool {
p.Lock()
defer p.Unlock()
if p.main == trueValue { if p.main == trueValue {
return true return true
} else if p.main == falseValue { } else if p.main == falseValue {
@ -51,13 +54,35 @@ func (p *Package) IsMain() bool {
return false 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. // TypeCheck performs type checking for given package.
func (p *Package) TypeCheck() error { func (p *Package) TypeCheck() error {
p.mu.Lock() p.Lock()
defer p.Unlock()
// If type checking has already been performed // If type checking has already been performed
// skip it. // skip it.
if p.TypesInfo != nil || p.TypesPkg != nil { if p.typesInfo != nil || p.typesPkg != nil {
p.mu.Unlock()
return nil return nil
} }
config := &types.Config{ config := &types.Config{
@ -82,9 +107,9 @@ func (p *Package) TypeCheck() error {
// Remember the typechecking info, even if config.Check failed, // Remember the typechecking info, even if config.Check failed,
// since we will get partial information. // since we will get partial information.
p.TypesPkg = typesPkg p.typesPkg = typesPkg
p.TypesInfo = info p.typesInfo = info
p.mu.Unlock()
return err 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. // TypeOf returns the type of an expression.
func (p *Package) TypeOf(expr ast.Expr) types.Type { func (p *Package) TypeOf(expr ast.Expr) types.Type {
if p.TypesInfo == nil { if p.typesInfo == nil {
return nil return nil
} }
return p.TypesInfo.TypeOf(expr) return p.typesInfo.TypeOf(expr)
} }
type walker struct { type walker struct {
@ -129,7 +154,7 @@ func (w *walker) Visit(n ast.Node) ast.Visitor {
} }
func (p *Package) scanSortable() { func (p *Package) scanSortable() {
p.Sortable = make(map[string]bool) p.sortable = make(map[string]bool)
// bitfield for which methods exist on each type. // bitfield for which methods exist on each type.
const ( const (
@ -144,7 +169,7 @@ func (p *Package) scanSortable() {
} }
for typ, ms := range has { for typ, ms := range has {
if ms == Len|Less|Swap { if ms == Len|Less|Swap {
p.Sortable[typ] = true p.sortable[typ] = true
} }
} }
} }

View File

@ -5,6 +5,7 @@ import (
"go/ast" "go/ast"
"strconv" "strconv"
"strings" "strings"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -33,53 +34,12 @@ func (wl whiteList) add(kind, list string) {
type AddConstantRule struct { type AddConstantRule struct {
whiteList whiteList whiteList whiteList
strLitLimit int strLitLimit int
sync.Mutex
} }
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
if r.whiteList == nil { r.configure(arguments)
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
}
}
}
}
var failures []lint.Failure 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), 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
}
}
}
}
}

View File

@ -3,6 +3,7 @@ package rule
import ( import (
"fmt" "fmt"
"go/ast" "go/ast"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -10,10 +11,11 @@ import (
// ArgumentsLimitRule lints given else constructs. // ArgumentsLimitRule lints given else constructs.
type ArgumentsLimitRule struct { type ArgumentsLimitRule struct {
total int total int
sync.Mutex
} }
// Apply applies the rule to given file. func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) {
func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
if r.total == 0 { if r.total == 0 {
checkNumberOfArguments(1, arguments, r.Name()) checkNumberOfArguments(1, arguments, r.Name())
@ -23,14 +25,21 @@ func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []
} }
r.total = int(total) 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 var failures []lint.Failure
onFailure := func(failure lint.Failure) {
failures = append(failures, failure)
}
walker := lintArgsNum{ walker := lintArgsNum{
total: r.total, total: r.total,
onFailure: func(failure lint.Failure) { onFailure: onFailure,
failures = append(failures, failure)
},
} }
ast.Walk(walker, file.AST) ast.Walk(walker, file.AST)

View File

@ -15,7 +15,7 @@ type AtomicRule struct{}
func (r *AtomicRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { func (r *AtomicRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
var failures []lint.Failure var failures []lint.Failure
walker := atomic{ walker := atomic{
pkgTypesInfo: file.Pkg.TypesInfo, pkgTypesInfo: file.Pkg.TypesInfo(),
onFailure: func(failure lint.Failure) { onFailure: func(failure lint.Failure) {
failures = append(failures, failure) failures = append(failures, failure)
}, },

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"go/ast" "go/ast"
"strings" "strings"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -11,16 +12,23 @@ import (
// BannedCharsRule checks if a file contains banned characters. // BannedCharsRule checks if a file contains banned characters.
type BannedCharsRule struct { type BannedCharsRule struct {
bannedCharList []string bannedCharList []string
sync.Mutex
} }
const bannedCharsRuleName = "banned-characters" const bannedCharsRuleName = "banned-characters"
// Apply applied the rule to the given file. func (r *BannedCharsRule) configure(arguments lint.Arguments) {
func (r *BannedCharsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
if r.bannedCharList == nil { if r.bannedCharList == nil {
checkNumberOfArguments(1, arguments, bannedCharsRuleName) checkNumberOfArguments(1, arguments, bannedCharsRuleName)
r.bannedCharList = r.getBannedCharsList(arguments) 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 var failures []lint.Failure
onFailure := func(failure 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, bannedChars: r.bannedCharList,
onFailure: onFailure, onFailure: onFailure,
} }
ast.Walk(w, file.AST) ast.Walk(w, file.AST)
return failures return failures
} }

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"go/ast" "go/ast"
"go/token" "go/token"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
"golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/ast/astutil"
@ -12,10 +13,11 @@ import (
// CognitiveComplexityRule lints given else constructs. // CognitiveComplexityRule lints given else constructs.
type CognitiveComplexityRule struct { type CognitiveComplexityRule struct {
maxComplexity int maxComplexity int
sync.Mutex
} }
// Apply applies the rule to given file. func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) {
func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
if r.maxComplexity == 0 { if r.maxComplexity == 0 {
checkNumberOfArguments(1, arguments, r.Name()) checkNumberOfArguments(1, arguments, r.Name())
@ -25,8 +27,15 @@ func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Argument
} }
r.maxComplexity = int(complexity) 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 var failures []lint.Failure
linter := cognitiveComplexityLinter{ linter := cognitiveComplexityLinter{
file: file, file: file,
maxComplexity: r.maxComplexity, maxComplexity: r.maxComplexity,

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"go/ast" "go/ast"
"strings" "strings"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -11,21 +12,27 @@ import (
// ContextAsArgumentRule lints given else constructs. // ContextAsArgumentRule lints given else constructs.
type ContextAsArgumentRule struct { type ContextAsArgumentRule struct {
allowTypesLUT map[string]struct{} allowTypesLUT map[string]struct{}
sync.Mutex
} }
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *ContextAsArgumentRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { func (r *ContextAsArgumentRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
r.Lock()
if r.allowTypesLUT == nil { if r.allowTypesLUT == nil {
r.allowTypesLUT = getAllowTypesFromArguments(args) r.allowTypesLUT = getAllowTypesFromArguments(args)
} }
r.Unlock()
var failures []lint.Failure var failures []lint.Failure
r.Lock()
walker := lintContextArguments{ walker := lintContextArguments{
allowTypesLUT: r.allowTypesLUT, allowTypesLUT: r.allowTypesLUT,
onFailure: func(failure lint.Failure) { onFailure: func(failure lint.Failure) {
failures = append(failures, failure) failures = append(failures, failure)
}, },
} }
r.Unlock()
ast.Walk(walker, file.AST) ast.Walk(walker, file.AST)

View File

@ -68,7 +68,7 @@ func checkContextKeyType(w lintContextKeyTypes, x *ast.CallExpr) {
if len(x.Args) != 3 { if len(x.Args) != 3 {
return 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 { if ktyp, ok := key.Type.(*types.Basic); ok && ktyp.Kind() != types.Invalid {
w.onFailure(lint.Failure{ w.onFailure(lint.Failure{

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"go/ast" "go/ast"
"go/token" "go/token"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -13,10 +14,11 @@ import (
// CyclomaticRule lints given else constructs. // CyclomaticRule lints given else constructs.
type CyclomaticRule struct { type CyclomaticRule struct {
maxComplexity int maxComplexity int
sync.Mutex
} }
// Apply applies the rule to given file. func (r *CyclomaticRule) configure(arguments lint.Arguments) {
func (r *CyclomaticRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
if r.maxComplexity == 0 { if r.maxComplexity == 0 {
checkNumberOfArguments(1, arguments, r.Name()) 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.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 var failures []lint.Failure
fileAst := file.AST fileAst := file.AST
walker := lintCyclomatic{ walker := lintCyclomatic{
file: file, file: file,
complexity: r.maxComplexity, complexity: r.maxComplexity,

View File

@ -3,6 +3,7 @@ package rule
import ( import (
"fmt" "fmt"
"go/ast" "go/ast"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -10,18 +11,25 @@ import (
// DeferRule lints unused params in functions. // DeferRule lints unused params in functions.
type DeferRule struct { type DeferRule struct {
allow map[string]bool 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. // Apply applies the rule to given file.
func (r *DeferRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *DeferRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
if r.allow == nil { r.configure(arguments)
r.allow = r.allowFromArgs(arguments)
}
var failures []lint.Failure var failures []lint.Failure
onFailure := func(failure lint.Failure) { onFailure := func(failure lint.Failure) {
failures = append(failures, failure) failures = append(failures, failure)
} }
w := lintDeferRule{onFailure: onFailure, allow: r.allow} w := lintDeferRule{onFailure: onFailure, allow: r.allow}
ast.Walk(w, file.AST) ast.Walk(w, file.AST)

View File

@ -5,6 +5,7 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
"strings" "strings"
"sync"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
@ -17,19 +18,14 @@ type ExportedRule struct {
checkPrivateReceivers bool checkPrivateReceivers bool
disableStutteringCheck bool disableStutteringCheck bool
stuttersMsg string stuttersMsg string
sync.Mutex
} }
// Apply applies the rule to given file. func (r *ExportedRule) configure(arguments lint.Arguments) {
func (r *ExportedRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { r.Lock()
var failures []lint.Failure
if file.IsTest() {
return failures
}
if !r.configured { if !r.configured {
var sayRepetitiveInsteadOfStutters bool var sayRepetitiveInsteadOfStutters bool
r.checkPrivateReceivers, r.disableStutteringCheck, sayRepetitiveInsteadOfStutters = r.getConf(args) r.checkPrivateReceivers, r.disableStutteringCheck, sayRepetitiveInsteadOfStutters = r.getConf(arguments)
r.stuttersMsg = "stutters" r.stuttersMsg = "stutters"
if sayRepetitiveInsteadOfStutters { if sayRepetitiveInsteadOfStutters {
r.stuttersMsg = "is repetitive" r.stuttersMsg = "is repetitive"
@ -37,8 +33,20 @@ func (r *ExportedRule) Apply(file *lint.File, args lint.Arguments) []lint.Failur
r.configured = true 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 fileAst := file.AST
walker := lintExported{ walker := lintExported{
file: file, file: file,
fileAst: fileAst, fileAst: fileAst,
@ -118,7 +126,8 @@ func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) {
} }
switch name { switch name {
case "Len", "Less", "Swap": case "Len", "Less", "Swap":
if w.file.Pkg.Sortable[recv] { sortables := w.file.Pkg.Sortable()
if sortables[recv] {
return return
} }
} }

View File

@ -3,6 +3,7 @@ package rule
import ( import (
"fmt" "fmt"
"regexp" "regexp"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -10,6 +11,7 @@ import (
// FileHeaderRule lints given else constructs. // FileHeaderRule lints given else constructs.
type FileHeaderRule struct { type FileHeaderRule struct {
header string header string
sync.Mutex
} }
var ( var (
@ -17,8 +19,8 @@ var (
singleRegexp = regexp.MustCompile("^//") singleRegexp = regexp.MustCompile("^//")
) )
// Apply applies the rule to given file. func (r *FileHeaderRule) configure(arguments lint.Arguments) {
func (r *FileHeaderRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
if r.header == "" { if r.header == "" {
checkNumberOfArguments(1, arguments, r.Name()) checkNumberOfArguments(1, arguments, r.Name())
var ok bool 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])) 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{ failure := []lint.Failure{
{ {

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"go/ast" "go/ast"
"reflect" "reflect"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -12,15 +13,22 @@ import (
type FunctionLength struct { type FunctionLength struct {
maxStmt int maxStmt int
maxLines int maxLines int
sync.Mutex
} }
// Apply applies the rule to given file. func (r *FunctionLength) configure(arguments lint.Arguments) {
func (r *FunctionLength) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
if r.maxLines == 0 { if r.maxLines == 0 {
maxStmt, maxLines := r.parseArguments(arguments) maxStmt, maxLines := r.parseArguments(arguments)
r.maxStmt = int(maxStmt) r.maxStmt = int(maxStmt)
r.maxLines = int(maxLines) 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 var failures []lint.Failure

View File

@ -3,6 +3,7 @@ package rule
import ( import (
"fmt" "fmt"
"go/ast" "go/ast"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -10,10 +11,11 @@ import (
// FunctionResultsLimitRule lints given else constructs. // FunctionResultsLimitRule lints given else constructs.
type FunctionResultsLimitRule struct { type FunctionResultsLimitRule struct {
max int max int
sync.Mutex
} }
// Apply applies the rule to given file. func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) {
func (r *FunctionResultsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
if r.max == 0 { if r.max == 0 {
checkNumberOfArguments(1, arguments, r.Name()) checkNumberOfArguments(1, arguments, r.Name())
@ -26,6 +28,12 @@ func (r *FunctionResultsLimitRule) Apply(file *lint.File, arguments lint.Argumen
} }
r.max = int(max) 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 var failures []lint.Failure

View File

@ -2,6 +2,7 @@ package rule
import ( import (
"fmt" "fmt"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -9,16 +10,11 @@ import (
// ImportsBlacklistRule lints given else constructs. // ImportsBlacklistRule lints given else constructs.
type ImportsBlacklistRule struct { type ImportsBlacklistRule struct {
blacklist map[string]bool blacklist map[string]bool
sync.Mutex
} }
// Apply applies the rule to given file. func (r *ImportsBlacklistRule) configure(arguments lint.Arguments) {
func (r *ImportsBlacklistRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
var failures []lint.Failure
if file.IsTest() {
return failures // skip, test file
}
if r.blacklist == nil { if r.blacklist == nil {
r.blacklist = make(map[string]bool, len(arguments)) 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.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 { for _, is := range file.AST.Imports {
path := is.Path path := is.Path

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"go/token" "go/token"
"strings" "strings"
"sync"
"unicode/utf8" "unicode/utf8"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
@ -14,10 +15,11 @@ import (
// LineLengthLimitRule lints given else constructs. // LineLengthLimitRule lints given else constructs.
type LineLengthLimitRule struct { type LineLengthLimitRule struct {
max int max int
sync.Mutex
} }
// Apply applies the rule to given file. func (r *LineLengthLimitRule) configure(arguments lint.Arguments) {
func (r *LineLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
if r.max == 0 { if r.max == 0 {
checkNumberOfArguments(1, arguments, r.Name()) checkNumberOfArguments(1, arguments, r.Name())
@ -28,8 +30,15 @@ func (r *LineLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) [
r.max = int(max) 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 var failures []lint.Failure
checker := lintLineLengthNum{ checker := lintLineLengthNum{
max: r.max, max: r.max,
file: file, file: file,

View File

@ -3,6 +3,7 @@ package rule
import ( import (
"go/ast" "go/ast"
"strings" "strings"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -10,10 +11,11 @@ import (
// MaxPublicStructsRule lints given else constructs. // MaxPublicStructsRule lints given else constructs.
type MaxPublicStructsRule struct { type MaxPublicStructsRule struct {
max int64 max int64
sync.Mutex
} }
// Apply applies the rule to given file. func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) {
func (r *MaxPublicStructsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
if r.max < 1 { if r.max < 1 {
checkNumberOfArguments(1, arguments, r.Name()) checkNumberOfArguments(1, arguments, r.Name())
@ -23,10 +25,17 @@ func (r *MaxPublicStructsRule) Apply(file *lint.File, arguments lint.Arguments)
} }
r.max = max 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 var failures []lint.Failure
fileAst := file.AST fileAst := file.AST
walker := &lintMaxPublicStructs{ walker := &lintMaxPublicStructs{
fileAst: fileAst, fileAst: fileAst,
onFailure: func(failure lint.Failure) { onFailure: func(failure lint.Failure) {

View File

@ -10,13 +10,9 @@ import (
type NestedStructs struct{} type NestedStructs struct{}
// Apply applies the rule to given file. // 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 var failures []lint.Failure
if len(arguments) > 0 {
panic(r.Name() + " doesn't take any arguments")
}
walker := &lintNestedStructs{ walker := &lintNestedStructs{
fileAST: file.AST, fileAST: file.AST,
onFailure: func(failure lint.Failure) { onFailure: func(failure lint.Failure) {

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"go/ast" "go/ast"
"go/types" "go/types"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -11,16 +12,17 @@ import (
// UnhandledErrorRule lints given else constructs. // UnhandledErrorRule lints given else constructs.
type UnhandledErrorRule struct { type UnhandledErrorRule struct {
ignoreList ignoreListType ignoreList ignoreListType
sync.Mutex
} }
type ignoreListType map[string]struct{} type ignoreListType map[string]struct{}
// Apply applies the rule to given file. func (r *UnhandledErrorRule) configure(arguments lint.Arguments) {
func (r *UnhandledErrorRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { r.Lock()
if r.ignoreList == nil { 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) argStr, ok := arg.(string)
if !ok { if !ok {
panic(fmt.Sprintf("Invalid argument to the unhandled-error rule. Expecting a string, got %T", arg)) 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.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 var failures []lint.Failure

View File

@ -5,6 +5,7 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
"strings" "strings"
"sync"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
@ -14,12 +15,11 @@ type VarNamingRule struct {
configured bool configured bool
whitelist []string whitelist []string
blacklist []string blacklist []string
sync.Mutex
} }
// Apply applies the rule to given file. func (r *VarNamingRule) configure(arguments lint.Arguments) {
func (r *VarNamingRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { r.Lock()
var failures []lint.Failure
if !r.configured { if !r.configured {
if len(arguments) >= 1 { if len(arguments) >= 1 {
r.whitelist = getList(arguments[0], "whitelist") 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.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 fileAst := file.AST
walker := lintNames{ walker := lintNames{
file: file, file: file,
fileAst: fileAst, fileAst: fileAst,