Skip to content

Commit 31fbdb1

Browse files
authored
Fix/677 (#678)
1 parent b981427 commit 31fbdb1

23 files changed

+274
-118
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ build:
1515
@go build -ldflags='$(VERSION_FLAGS)'
1616

1717
test:
18-
@go test -v ./...
18+
@go test -v -race ./...
1919

lint/file.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func (f *File) IsUntypedConst(expr ast.Expr) (defType string, ok bool) {
7777
// Re-evaluate expr outside its context to see if it's untyped.
7878
// (An expr evaluated within, for example, an assignment context will get the type of the LHS.)
7979
exprStr := f.Render(expr)
80-
tv, err := types.Eval(f.Pkg.fset, f.Pkg.TypesPkg, expr.Pos(), exprStr)
80+
tv, err := types.Eval(f.Pkg.fset, f.Pkg.TypesPkg(), expr.Pos(), exprStr)
8181
if err != nil {
8282
return "", false
8383
}

lint/linter.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ func (l *Linter) lintPackage(filenames []string, ruleSet []Rule, config Config,
8181
pkg := &Package{
8282
fset: token.NewFileSet(),
8383
files: map[string]*File{},
84-
mu: sync.Mutex{},
8584
}
8685
for _, filename := range filenames {
8786
content, err := l.readFile(filename)

lint/package.go

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ type Package struct {
1414
fset *token.FileSet
1515
files map[string]*File
1616

17-
TypesPkg *types.Package
18-
TypesInfo *types.Info
17+
typesPkg *types.Package
18+
typesInfo *types.Info
1919

2020
// sortable is the set of types in the package that implement sort.Interface.
21-
Sortable map[string]bool
21+
sortable map[string]bool
2222
// main is whether this is a "main" package.
2323
main int
24-
mu sync.Mutex
24+
sync.RWMutex
2525
}
2626

2727
var newImporter = func(fset *token.FileSet) types.ImporterFrom {
@@ -36,6 +36,9 @@ var (
3636

3737
// IsMain returns if that's the main package.
3838
func (p *Package) IsMain() bool {
39+
p.Lock()
40+
defer p.Unlock()
41+
3942
if p.main == trueValue {
4043
return true
4144
} else if p.main == falseValue {
@@ -51,13 +54,35 @@ func (p *Package) IsMain() bool {
5154
return false
5255
}
5356

57+
// TypesPkg yields information on this package
58+
func (p *Package) TypesPkg() *types.Package {
59+
p.RLock()
60+
defer p.RUnlock()
61+
return p.typesPkg
62+
}
63+
64+
// TypesInfo yields type information of this package identifiers
65+
func (p *Package) TypesInfo() *types.Info {
66+
p.RLock()
67+
defer p.RUnlock()
68+
return p.typesInfo
69+
}
70+
71+
// Sortable yields a map of sortable types in this package
72+
func (p *Package) Sortable() map[string]bool {
73+
p.RLock()
74+
defer p.RUnlock()
75+
return p.sortable
76+
}
77+
5478
// TypeCheck performs type checking for given package.
5579
func (p *Package) TypeCheck() error {
56-
p.mu.Lock()
80+
p.Lock()
81+
defer p.Unlock()
82+
5783
// If type checking has already been performed
5884
// skip it.
59-
if p.TypesInfo != nil || p.TypesPkg != nil {
60-
p.mu.Unlock()
85+
if p.typesInfo != nil || p.typesPkg != nil {
6186
return nil
6287
}
6388
config := &types.Config{
@@ -82,9 +107,9 @@ func (p *Package) TypeCheck() error {
82107

83108
// Remember the typechecking info, even if config.Check failed,
84109
// since we will get partial information.
85-
p.TypesPkg = typesPkg
86-
p.TypesInfo = info
87-
p.mu.Unlock()
110+
p.typesPkg = typesPkg
111+
p.typesInfo = info
112+
88113
return err
89114
}
90115

@@ -104,10 +129,10 @@ func check(config *types.Config, n string, fset *token.FileSet, astFiles []*ast.
104129

105130
// TypeOf returns the type of an expression.
106131
func (p *Package) TypeOf(expr ast.Expr) types.Type {
107-
if p.TypesInfo == nil {
132+
if p.typesInfo == nil {
108133
return nil
109134
}
110-
return p.TypesInfo.TypeOf(expr)
135+
return p.typesInfo.TypeOf(expr)
111136
}
112137

113138
type walker struct {
@@ -129,7 +154,7 @@ func (w *walker) Visit(n ast.Node) ast.Visitor {
129154
}
130155

131156
func (p *Package) scanSortable() {
132-
p.Sortable = make(map[string]bool)
157+
p.sortable = make(map[string]bool)
133158

134159
// bitfield for which methods exist on each type.
135160
const (
@@ -144,7 +169,7 @@ func (p *Package) scanSortable() {
144169
}
145170
for typ, ms := range has {
146171
if ms == Len|Less|Swap {
147-
p.Sortable[typ] = true
172+
p.sortable[typ] = true
148173
}
149174
}
150175
}

rule/add-constant.go

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"go/ast"
66
"strconv"
77
"strings"
8+
"sync"
89

910
"github.com/mgechev/revive/lint"
1011
)
@@ -33,53 +34,12 @@ func (wl whiteList) add(kind, list string) {
3334
type AddConstantRule struct {
3435
whiteList whiteList
3536
strLitLimit int
37+
sync.Mutex
3638
}
3739

3840
// Apply applies the rule to given file.
3941
func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
40-
if r.whiteList == nil {
41-
r.strLitLimit = defaultStrLitLimit
42-
r.whiteList = newWhiteList()
43-
if len(arguments) > 0 {
44-
args, ok := arguments[0].(map[string]interface{})
45-
if !ok {
46-
panic(fmt.Sprintf("Invalid argument to the add-constant rule. Expecting a k,v map, got %T", arguments[0]))
47-
}
48-
for k, v := range args {
49-
kind := ""
50-
switch k {
51-
case "allowFloats":
52-
kind = kindFLOAT
53-
fallthrough
54-
case "allowInts":
55-
if kind == "" {
56-
kind = kindINT
57-
}
58-
fallthrough
59-
case "allowStrs":
60-
if kind == "" {
61-
kind = kindSTRING
62-
}
63-
list, ok := v.(string)
64-
if !ok {
65-
panic(fmt.Sprintf("Invalid argument to the add-constant rule, string expected. Got '%v' (%T)", v, v))
66-
}
67-
r.whiteList.add(kind, list)
68-
case "maxLitCount":
69-
sl, ok := v.(string)
70-
if !ok {
71-
panic(fmt.Sprintf("Invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v' (%T)", v, v))
72-
}
73-
74-
limit, err := strconv.Atoi(sl)
75-
if err != nil {
76-
panic(fmt.Sprintf("Invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v'", v))
77-
}
78-
r.strLitLimit = limit
79-
}
80-
}
81-
}
82-
}
42+
r.configure(arguments)
8343

8444
var failures []lint.Failure
8545

@@ -154,3 +114,52 @@ func (w lintAddConstantRule) checkNumLit(kind string, n *ast.BasicLit) {
154114
Failure: fmt.Sprintf("avoid magic numbers like '%s', create a named constant for it", n.Value),
155115
})
156116
}
117+
118+
func (r *AddConstantRule) configure(arguments lint.Arguments) {
119+
r.Lock()
120+
defer r.Unlock()
121+
122+
if r.whiteList == nil {
123+
r.strLitLimit = defaultStrLitLimit
124+
r.whiteList = newWhiteList()
125+
if len(arguments) > 0 {
126+
args, ok := arguments[0].(map[string]interface{})
127+
if !ok {
128+
panic(fmt.Sprintf("Invalid argument to the add-constant rule. Expecting a k,v map, got %T", arguments[0]))
129+
}
130+
for k, v := range args {
131+
kind := ""
132+
switch k {
133+
case "allowFloats":
134+
kind = kindFLOAT
135+
fallthrough
136+
case "allowInts":
137+
if kind == "" {
138+
kind = kindINT
139+
}
140+
fallthrough
141+
case "allowStrs":
142+
if kind == "" {
143+
kind = kindSTRING
144+
}
145+
list, ok := v.(string)
146+
if !ok {
147+
panic(fmt.Sprintf("Invalid argument to the add-constant rule, string expected. Got '%v' (%T)", v, v))
148+
}
149+
r.whiteList.add(kind, list)
150+
case "maxLitCount":
151+
sl, ok := v.(string)
152+
if !ok {
153+
panic(fmt.Sprintf("Invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v' (%T)", v, v))
154+
}
155+
156+
limit, err := strconv.Atoi(sl)
157+
if err != nil {
158+
panic(fmt.Sprintf("Invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v'", v))
159+
}
160+
r.strLitLimit = limit
161+
}
162+
}
163+
}
164+
}
165+
}

rule/argument-limit.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@ package rule
33
import (
44
"fmt"
55
"go/ast"
6+
"sync"
67

78
"github.com/mgechev/revive/lint"
89
)
910

1011
// ArgumentsLimitRule lints given else constructs.
1112
type ArgumentsLimitRule struct {
1213
total int
14+
sync.Mutex
1315
}
1416

15-
// Apply applies the rule to given file.
16-
func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
17+
func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) {
18+
r.Lock()
1719
if r.total == 0 {
1820
checkNumberOfArguments(1, arguments, r.Name())
1921

@@ -23,14 +25,21 @@ func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []
2325
}
2426
r.total = int(total)
2527
}
28+
r.Unlock()
29+
}
30+
31+
// Apply applies the rule to given file.
32+
func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
33+
r.configure(arguments)
2634

2735
var failures []lint.Failure
36+
onFailure := func(failure lint.Failure) {
37+
failures = append(failures, failure)
38+
}
2839

2940
walker := lintArgsNum{
30-
total: r.total,
31-
onFailure: func(failure lint.Failure) {
32-
failures = append(failures, failure)
33-
},
41+
total: r.total,
42+
onFailure: onFailure,
3443
}
3544

3645
ast.Walk(walker, file.AST)

rule/atomic.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type AtomicRule struct{}
1515
func (r *AtomicRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
1616
var failures []lint.Failure
1717
walker := atomic{
18-
pkgTypesInfo: file.Pkg.TypesInfo,
18+
pkgTypesInfo: file.Pkg.TypesInfo(),
1919
onFailure: func(failure lint.Failure) {
2020
failures = append(failures, failure)
2121
},

rule/banned-characters.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,31 @@ import (
44
"fmt"
55
"go/ast"
66
"strings"
7+
"sync"
78

89
"github.com/mgechev/revive/lint"
910
)
1011

1112
// BannedCharsRule checks if a file contains banned characters.
1213
type BannedCharsRule struct {
1314
bannedCharList []string
15+
sync.Mutex
1416
}
1517

1618
const bannedCharsRuleName = "banned-characters"
1719

18-
// Apply applied the rule to the given file.
19-
func (r *BannedCharsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
20+
func (r *BannedCharsRule) configure(arguments lint.Arguments) {
21+
r.Lock()
2022
if r.bannedCharList == nil {
2123
checkNumberOfArguments(1, arguments, bannedCharsRuleName)
2224
r.bannedCharList = r.getBannedCharsList(arguments)
2325
}
26+
r.Unlock()
27+
}
28+
29+
// Apply applied the rule to the given file.
30+
func (r *BannedCharsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
31+
r.configure(arguments)
2432

2533
var failures []lint.Failure
2634
onFailure := func(failure lint.Failure) {
@@ -31,6 +39,7 @@ func (r *BannedCharsRule) Apply(file *lint.File, arguments lint.Arguments) []lin
3139
bannedChars: r.bannedCharList,
3240
onFailure: onFailure,
3341
}
42+
3443
ast.Walk(w, file.AST)
3544
return failures
3645
}

rule/cognitive-complexity.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"go/ast"
66
"go/token"
7+
"sync"
78

89
"github.com/mgechev/revive/lint"
910
"golang.org/x/tools/go/ast/astutil"
@@ -12,10 +13,11 @@ import (
1213
// CognitiveComplexityRule lints given else constructs.
1314
type CognitiveComplexityRule struct {
1415
maxComplexity int
16+
sync.Mutex
1517
}
1618

17-
// Apply applies the rule to given file.
18-
func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
19+
func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) {
20+
r.Lock()
1921
if r.maxComplexity == 0 {
2022
checkNumberOfArguments(1, arguments, r.Name())
2123

@@ -25,8 +27,15 @@ func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Argument
2527
}
2628
r.maxComplexity = int(complexity)
2729
}
30+
r.Unlock()
31+
}
32+
33+
// Apply applies the rule to given file.
34+
func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
35+
r.configure(arguments)
2836

2937
var failures []lint.Failure
38+
3039
linter := cognitiveComplexityLinter{
3140
file: file,
3241
maxComplexity: r.maxComplexity,

0 commit comments

Comments
 (0)