1
0
mirror of https://github.com/mgechev/revive.git synced 2024-11-19 17:12:55 +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)'
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.
// (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
}

View File

@ -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)

View File

@ -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
}
}
}

View File

@ -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
}
}
}
}
}

View File

@ -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)

View File

@ -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)
},

View File

@ -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
}

View File

@ -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,

View File

@ -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)

View File

@ -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{

View File

@ -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,

View File

@ -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)

View File

@ -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
}
}

View File

@ -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{
{

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -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,