diff options
Diffstat (limited to 'vendor/github.com/mgechev/revive/rule/redefines-builtin-id.go')
-rw-r--r-- | vendor/github.com/mgechev/revive/rule/redefines-builtin-id.go | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/vendor/github.com/mgechev/revive/rule/redefines-builtin-id.go b/vendor/github.com/mgechev/revive/rule/redefines-builtin-id.go new file mode 100644 index 0000000000..947b8aac7c --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/redefines-builtin-id.go @@ -0,0 +1,145 @@ +package rule + +import ( + "fmt" + "github.com/mgechev/revive/lint" + "go/ast" + "go/token" +) + +// RedefinesBuiltinIDRule warns when a builtin identifier is shadowed. +type RedefinesBuiltinIDRule struct{} + +// Apply applies the rule to given file. +func (r *RedefinesBuiltinIDRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { + var failures []lint.Failure + + var builtInConstAndVars = map[string]bool{ + "true": true, + "false": true, + "iota": true, + "nil": true, + } + + var builtFunctions = map[string]bool{ + "append": true, + "cap": true, + "close": true, + "complex": true, + "copy": true, + "delete": true, + "imag": true, + "len": true, + "make": true, + "new": true, + "panic": true, + "print": true, + "println": true, + "real": true, + "recover": true, + } + + var builtInTypes = map[string]bool{ + "ComplexType": true, + "FloatType": true, + "IntegerType": true, + "Type": true, + "Type1": true, + "bool": true, + "byte": true, + "complex128": true, + "complex64": true, + "error": true, + "float32": true, + "float64": true, + "int": true, + "int16": true, + "int32": true, + "int64": true, + "int8": true, + "rune": true, + "string": true, + "uint": true, + "uint16": true, + "uint32": true, + "uint64": true, + "uint8": true, + "uintptr": true, + } + + onFailure := func(failure lint.Failure) { + failures = append(failures, failure) + } + + astFile := file.AST + w := &lintRedefinesBuiltinID{builtInConstAndVars, builtFunctions, builtInTypes, onFailure} + ast.Walk(w, astFile) + + return failures +} + +// Name returns the rule name. +func (r *RedefinesBuiltinIDRule) Name() string { + return "redefines-builtin-id" +} + +type lintRedefinesBuiltinID struct { + constsAndVars map[string]bool + funcs map[string]bool + types map[string]bool + onFailure func(lint.Failure) +} + +func (w *lintRedefinesBuiltinID) Visit(node ast.Node) ast.Visitor { + switch n := node.(type) { + case *ast.GenDecl: + if n.Tok != token.TYPE { + return nil // skip if not type declaration + } + typeSpec, ok := n.Specs[0].(*ast.TypeSpec) + if !ok { + return nil + } + id := typeSpec.Name.Name + if w.types[id] { + w.addFailure(n, fmt.Sprintf("redefinition of the built-in type %s", id)) + } + case *ast.FuncDecl: + if n.Recv != nil { + return w // skip methods + } + + id := n.Name.Name + if w.funcs[id] { + w.addFailure(n, fmt.Sprintf("redefinition of the built-in function %s", id)) + } + case *ast.AssignStmt: + for _, e := range n.Lhs { + id, ok := e.(*ast.Ident) + if !ok { + continue + } + + if w.constsAndVars[id.Name] { + var msg string + if n.Tok == token.DEFINE { + msg = fmt.Sprintf("assignment creates a shadow of built-in identifier %s", id.Name) + } else { + msg = fmt.Sprintf("assignment modifies built-in identifier %s", id.Name) + } + w.addFailure(n, msg) + } + } + } + + return w +} + +func (w lintRedefinesBuiltinID) addFailure(node ast.Node, msg string) { + w.onFailure(lint.Failure{ + Confidence: 1, + Node: node, + Category: "logic", + Failure: msg, + }) +} |