mirror of
https://github.com/mgechev/revive.git
synced 2024-11-21 17:16:40 +02:00
Fix/677 (#678)
This commit is contained in:
parent
b9814276b6
commit
31fbdb1833
2
Makefile
2
Makefile
@ -15,5 +15,5 @@ build:
|
||||
@go build -ldflags='$(VERSION_FLAGS)'
|
||||
|
||||
test:
|
||||
@go test -v ./...
|
||||
@go test -v -race ./...
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
},
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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{
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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{
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user