@@ -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.
1266type RedefinesBuiltinIDRule struct {}
1367
1468// Apply applies the rule to given file.
1569func (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
8788type 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
9492func (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+ }
0 commit comments