Skip to content

Commit fa939ad

Browse files
authored
Adds support for new type alias any in the rule redefines-built-in (#659)
* adds support for any type alias * adds more representative tests
1 parent 5f6f0eb commit fa939ad

File tree

2 files changed

+121
-75
lines changed

2 files changed

+121
-75
lines changed

rule/redefines-builtin-id.go

+111-75
Original file line numberDiff line numberDiff line change
@@ -8,72 +8,73 @@ import (
88
"github.com/mgechev/revive/lint"
99
)
1010

11+
var builtInConstAndVars = map[string]bool{
12+
"true": true,
13+
"false": true,
14+
"iota": true,
15+
"nil": true,
16+
}
17+
18+
var builtFunctions = map[string]bool{
19+
"append": true,
20+
"cap": true,
21+
"close": true,
22+
"complex": true,
23+
"copy": true,
24+
"delete": true,
25+
"imag": true,
26+
"len": true,
27+
"make": true,
28+
"new": true,
29+
"panic": true,
30+
"print": true,
31+
"println": true,
32+
"real": true,
33+
"recover": true,
34+
}
35+
36+
var builtInTypes = map[string]bool{
37+
"ComplexType": true,
38+
"FloatType": true,
39+
"IntegerType": true,
40+
"Type": true,
41+
"Type1": true,
42+
"bool": true,
43+
"byte": true,
44+
"complex128": true,
45+
"complex64": true,
46+
"error": true,
47+
"float32": true,
48+
"float64": true,
49+
"int": true,
50+
"int16": true,
51+
"int32": true,
52+
"int64": true,
53+
"int8": true,
54+
"rune": true,
55+
"string": true,
56+
"uint": true,
57+
"uint16": true,
58+
"uint32": true,
59+
"uint64": true,
60+
"uint8": true,
61+
"uintptr": true,
62+
"any": true,
63+
}
64+
1165
// RedefinesBuiltinIDRule warns when a builtin identifier is shadowed.
1266
type RedefinesBuiltinIDRule struct{}
1367

1468
// Apply applies the rule to given file.
1569
func (r *RedefinesBuiltinIDRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
1670
var failures []lint.Failure
1771

18-
builtInConstAndVars := map[string]bool{
19-
"true": true,
20-
"false": true,
21-
"iota": true,
22-
"nil": true,
23-
}
24-
25-
builtFunctions := map[string]bool{
26-
"append": true,
27-
"cap": true,
28-
"close": true,
29-
"complex": true,
30-
"copy": true,
31-
"delete": true,
32-
"imag": true,
33-
"len": true,
34-
"make": true,
35-
"new": true,
36-
"panic": true,
37-
"print": true,
38-
"println": true,
39-
"real": true,
40-
"recover": true,
41-
}
42-
43-
builtInTypes := map[string]bool{
44-
"ComplexType": true,
45-
"FloatType": true,
46-
"IntegerType": true,
47-
"Type": true,
48-
"Type1": true,
49-
"bool": true,
50-
"byte": true,
51-
"complex128": true,
52-
"complex64": true,
53-
"error": true,
54-
"float32": true,
55-
"float64": true,
56-
"int": true,
57-
"int16": true,
58-
"int32": true,
59-
"int64": true,
60-
"int8": true,
61-
"rune": true,
62-
"string": true,
63-
"uint": true,
64-
"uint16": true,
65-
"uint32": true,
66-
"uint64": true,
67-
"uint8": true,
68-
"uintptr": true,
69-
}
70-
7172
onFailure := func(failure lint.Failure) {
7273
failures = append(failures, failure)
7374
}
7475

7576
astFile := file.AST
76-
w := &lintRedefinesBuiltinID{builtInConstAndVars, builtFunctions, builtInTypes, onFailure}
77+
w := &lintRedefinesBuiltinID{onFailure}
7778
ast.Walk(w, astFile)
7879

7980
return failures
@@ -85,34 +86,46 @@ func (r *RedefinesBuiltinIDRule) Name() string {
8586
}
8687

8788
type lintRedefinesBuiltinID struct {
88-
constsAndVars map[string]bool
89-
funcs map[string]bool
90-
types map[string]bool
91-
onFailure func(lint.Failure)
89+
onFailure func(lint.Failure)
9290
}
9391

9492
func (w *lintRedefinesBuiltinID) Visit(node ast.Node) ast.Visitor {
9593
switch n := node.(type) {
9694
case *ast.GenDecl:
97-
if n.Tok != token.TYPE {
98-
return nil // skip if not type declaration
99-
}
100-
typeSpec, ok := n.Specs[0].(*ast.TypeSpec)
101-
if !ok {
102-
return nil
103-
}
104-
id := typeSpec.Name.Name
105-
if w.types[id] {
106-
w.addFailure(n, fmt.Sprintf("redefinition of the built-in type %s", id))
95+
switch n.Tok {
96+
case token.TYPE:
97+
typeSpec, ok := n.Specs[0].(*ast.TypeSpec)
98+
if !ok {
99+
return nil
100+
}
101+
id := typeSpec.Name.Name
102+
if ok, bt := w.isBuiltIn(id); ok {
103+
w.addFailure(n, fmt.Sprintf("redefinition of the built-in %s %s", bt, id))
104+
}
105+
case token.VAR, token.CONST:
106+
for _, vs := range n.Specs {
107+
valSpec, ok := vs.(*ast.ValueSpec)
108+
if !ok {
109+
continue
110+
}
111+
for _, name := range valSpec.Names {
112+
if ok, bt := w.isBuiltIn(name.Name); ok {
113+
w.addFailure(n, fmt.Sprintf("redefinition of the built-in %s %s", bt, name))
114+
}
115+
}
116+
}
117+
default:
118+
return nil // skip if not type/var/const declaration
107119
}
120+
108121
case *ast.FuncDecl:
109122
if n.Recv != nil {
110123
return w // skip methods
111124
}
112125

113126
id := n.Name.Name
114-
if w.funcs[id] {
115-
w.addFailure(n, fmt.Sprintf("redefinition of the built-in function %s", id))
127+
if ok, bt := w.isBuiltIn(id); ok {
128+
w.addFailure(n, fmt.Sprintf("redefinition of the built-in %s %s", bt, id))
116129
}
117130
case *ast.AssignStmt:
118131
for _, e := range n.Lhs {
@@ -121,13 +134,20 @@ func (w *lintRedefinesBuiltinID) Visit(node ast.Node) ast.Visitor {
121134
continue
122135
}
123136

124-
if w.constsAndVars[id.Name] {
137+
if ok, bt := w.isBuiltIn(id.Name); ok {
125138
var msg string
126-
if n.Tok == token.DEFINE {
127-
msg = fmt.Sprintf("assignment creates a shadow of built-in identifier %s", id.Name)
128-
} else {
129-
msg = fmt.Sprintf("assignment modifies built-in identifier %s", id.Name)
139+
println(bt, id.Name)
140+
switch bt {
141+
case "constant or variable":
142+
if n.Tok == token.DEFINE {
143+
msg = fmt.Sprintf("assignment creates a shadow of built-in identifier %s", id.Name)
144+
} else {
145+
msg = fmt.Sprintf("assignment modifies built-in identifier %s", id.Name)
146+
}
147+
default:
148+
msg = fmt.Sprintf("redefinition of the built-in %s %s", bt, id)
130149
}
150+
131151
w.addFailure(n, msg)
132152
}
133153
}
@@ -144,3 +164,19 @@ func (w lintRedefinesBuiltinID) addFailure(node ast.Node, msg string) {
144164
Failure: msg,
145165
})
146166
}
167+
168+
func (w lintRedefinesBuiltinID) isBuiltIn(id string) (r bool, builtInKind string) {
169+
if builtFunctions[id] {
170+
return true, "function"
171+
}
172+
173+
if builtInConstAndVars[id] {
174+
return true, "constant or variable"
175+
}
176+
177+
if builtInTypes[id] {
178+
return true, "type"
179+
}
180+
181+
return false, ""
182+
}

testdata/redefines-builtin-id.go

+10
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,13 @@ func delete(set []int64, i int) (y []int64) { // MATCH /redefinition of the buil
1919
}
2020
return
2121
}
22+
23+
type any int // MATCH /redefinition of the built-in type any/
24+
25+
func any() {} // MATCH /redefinition of the built-in type any/
26+
27+
var any int // MATCH /redefinition of the built-in type any/
28+
29+
const any = 1 // MATCH /redefinition of the built-in type any/
30+
31+
var i, copy int // MATCH /redefinition of the built-in function copy/

0 commit comments

Comments
 (0)