aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/nishanths/predeclared
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2021-02-22 20:37:25 +0100
committerDmitry Vyukov <dvyukov@google.com>2021-02-22 21:02:12 +0100
commitfcc6d71be2c3ce7d9305c04fc2e87af554571bac (patch)
treeb01dbb3d1e2988e28ea158d2d543d603ec0b9569 /vendor/github.com/nishanths/predeclared
parent8f23c528ad5a943b9ffec5dcaf332fd0f614006e (diff)
go.mod: update golangci-lint to v1.37
Diffstat (limited to 'vendor/github.com/nishanths/predeclared')
-rw-r--r--vendor/github.com/nishanths/predeclared/LICENSE29
-rw-r--r--vendor/github.com/nishanths/predeclared/passes/predeclared/go18.go9
-rw-r--r--vendor/github.com/nishanths/predeclared/passes/predeclared/pre_go18.go53
-rw-r--r--vendor/github.com/nishanths/predeclared/passes/predeclared/predeclared.go202
4 files changed, 293 insertions, 0 deletions
diff --git a/vendor/github.com/nishanths/predeclared/LICENSE b/vendor/github.com/nishanths/predeclared/LICENSE
new file mode 100644
index 000000000..946212315
--- /dev/null
+++ b/vendor/github.com/nishanths/predeclared/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2017, Nishanth Shanmugham
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/nishanths/predeclared/passes/predeclared/go18.go b/vendor/github.com/nishanths/predeclared/passes/predeclared/go18.go
new file mode 100644
index 000000000..4083efc74
--- /dev/null
+++ b/vendor/github.com/nishanths/predeclared/passes/predeclared/go18.go
@@ -0,0 +1,9 @@
+// +build go1.8
+
+package predeclared
+
+import "go/doc"
+
+func isPredeclaredIdent(name string) bool {
+ return doc.IsPredeclared(name)
+}
diff --git a/vendor/github.com/nishanths/predeclared/passes/predeclared/pre_go18.go b/vendor/github.com/nishanths/predeclared/passes/predeclared/pre_go18.go
new file mode 100644
index 000000000..5780e0b56
--- /dev/null
+++ b/vendor/github.com/nishanths/predeclared/passes/predeclared/pre_go18.go
@@ -0,0 +1,53 @@
+// +build !go1.8
+
+package predeclared
+
+func isPredeclaredIdent(name string) bool {
+ return predeclaredIdents[name]
+}
+
+// Keep in sync with https://golang.org/ref/spec#Predeclared_identifiers
+var predeclaredIdents = map[string]bool{
+ "bool": true,
+ "byte": true,
+ "complex64": true,
+ "complex128": true,
+ "error": true,
+ "float32": true,
+ "float64": true,
+ "int": true,
+ "int8": true,
+ "int16": true,
+ "int32": true,
+ "int64": true,
+ "rune": true,
+ "string": true,
+ "uint": true,
+ "uint8": true,
+ "uint16": true,
+ "uint32": true,
+ "uint64": true,
+ "uintptr": true,
+
+ "true": true,
+ "false": true,
+ "iota": true,
+
+ "nil": true,
+
+ "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,
+}
diff --git a/vendor/github.com/nishanths/predeclared/passes/predeclared/predeclared.go b/vendor/github.com/nishanths/predeclared/passes/predeclared/predeclared.go
new file mode 100644
index 000000000..67c0e0a00
--- /dev/null
+++ b/vendor/github.com/nishanths/predeclared/passes/predeclared/predeclared.go
@@ -0,0 +1,202 @@
+// Package predeclared provides a static analysis (used by the predeclared command)
+// that can detect declarations in Go code that shadow one of Go's predeclared identifiers.
+package predeclared
+
+import (
+ "fmt"
+ "go/ast"
+ "go/token"
+ "strings"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+// Flag names used by the analyzer. They are exported for use by analyzer
+// driver programs.
+const (
+ IgnoreFlag = "ignore"
+ QualifiedFlag = "q"
+)
+
+var (
+ fIgnore string
+ fQualified bool
+)
+
+func init() {
+ Analyzer.Flags.StringVar(&fIgnore, IgnoreFlag, "", "comma-separated list of predeclared identifiers to not report on")
+ Analyzer.Flags.BoolVar(&fQualified, QualifiedFlag, false, "include method names and field names (i.e., qualified names) in checks")
+}
+
+var Analyzer = &analysis.Analyzer{
+ Name: "predeclared",
+ Doc: "find code that shadows one of Go's predeclared identifiers",
+ Run: run,
+}
+
+func run(pass *analysis.Pass) (interface{}, error) {
+ cfg := newConfig(fIgnore, fQualified)
+ for _, file := range pass.Files {
+ processFile(pass.Report, cfg, pass.Fset, file)
+ }
+ return nil, nil
+}
+
+type config struct {
+ qualified bool
+ ignoredIdents map[string]struct{}
+}
+
+func newConfig(ignore string, qualified bool) *config {
+ cfg := &config{
+ qualified: qualified,
+ ignoredIdents: map[string]struct{}{},
+ }
+ for _, s := range strings.Split(ignore, ",") {
+ ident := strings.TrimSpace(s)
+ if ident == "" {
+ continue
+ }
+ cfg.ignoredIdents[ident] = struct{}{}
+ }
+ return cfg
+}
+
+type issue struct {
+ ident *ast.Ident
+ kind string
+ fset *token.FileSet
+}
+
+func (i issue) String() string {
+ pos := i.fset.Position(i.ident.Pos())
+ return fmt.Sprintf("%s: %s %s has same name as predeclared identifier", pos, i.kind, i.ident.Name)
+}
+
+func processFile(report func(analysis.Diagnostic), cfg *config, fset *token.FileSet, file *ast.File) []issue { // nolint: gocyclo
+ var issues []issue
+
+ maybeReport := func(x *ast.Ident, kind string) {
+ if _, isIgnored := cfg.ignoredIdents[x.Name]; !isIgnored && isPredeclaredIdent(x.Name) {
+ report(analysis.Diagnostic{
+ Pos: x.Pos(),
+ End: x.End(),
+ Message: fmt.Sprintf("%s %s has same name as predeclared identifier", kind, x.Name),
+ })
+ issues = append(issues, issue{x, kind, fset})
+ }
+ }
+
+ seenValueSpecs := make(map[*ast.ValueSpec]bool)
+
+ // TODO: consider deduping package name issues for files in the
+ // same directory.
+ maybeReport(file.Name, "package name")
+
+ for _, spec := range file.Imports {
+ if spec.Name == nil {
+ continue
+ }
+ maybeReport(spec.Name, "import name")
+ }
+
+ // Handle declarations and fields.
+ // https://golang.org/ref/spec#Declarations_and_scope
+ ast.Inspect(file, func(n ast.Node) bool {
+ switch x := n.(type) {
+ case *ast.GenDecl:
+ var kind string
+ switch x.Tok {
+ case token.CONST:
+ kind = "const"
+ case token.VAR:
+ kind = "variable"
+ default:
+ return true
+ }
+ for _, spec := range x.Specs {
+ if vspec, ok := spec.(*ast.ValueSpec); ok && !seenValueSpecs[vspec] {
+ seenValueSpecs[vspec] = true
+ for _, name := range vspec.Names {
+ maybeReport(name, kind)
+ }
+ }
+ }
+ return true
+ case *ast.TypeSpec:
+ maybeReport(x.Name, "type")
+ return true
+ case *ast.StructType:
+ if cfg.qualified && x.Fields != nil {
+ for _, field := range x.Fields.List {
+ for _, name := range field.Names {
+ maybeReport(name, "field")
+ }
+ }
+ }
+ return true
+ case *ast.InterfaceType:
+ if cfg.qualified && x.Methods != nil {
+ for _, meth := range x.Methods.List {
+ for _, name := range meth.Names {
+ maybeReport(name, "method")
+ }
+ }
+ }
+ return true
+ case *ast.FuncDecl:
+ if x.Recv == nil {
+ // it's a function
+ maybeReport(x.Name, "function")
+ } else {
+ // it's a method
+ if cfg.qualified {
+ maybeReport(x.Name, "method")
+ }
+ }
+ // add receivers idents
+ if x.Recv != nil {
+ for _, field := range x.Recv.List {
+ for _, name := range field.Names {
+ maybeReport(name, "receiver")
+ }
+ }
+ }
+ // Params and Results will be checked in the *ast.FuncType case.
+ return true
+ case *ast.FuncType:
+ // add params idents
+ for _, field := range x.Params.List {
+ for _, name := range field.Names {
+ maybeReport(name, "param")
+ }
+ }
+ // add returns idents
+ if x.Results != nil {
+ for _, field := range x.Results.List {
+ for _, name := range field.Names {
+ maybeReport(name, "named return")
+ }
+ }
+ }
+ return true
+ case *ast.LabeledStmt:
+ maybeReport(x.Label, "label")
+ return true
+ case *ast.AssignStmt:
+ // We only care about short variable declarations, which use token.DEFINE.
+ if x.Tok == token.DEFINE {
+ for _, expr := range x.Lhs {
+ if ident, ok := expr.(*ast.Ident); ok {
+ maybeReport(ident, "variable")
+ }
+ }
+ }
+ return true
+ default:
+ return true
+ }
+ })
+
+ return issues
+}