aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/Antonboom/nilnil
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2024-09-10 12:16:33 +0200
committerTaras Madan <tarasmadan@google.com>2024-09-10 14:05:26 +0000
commitc97c816133b42257d0bcf1ee4bd178bb2a7a2b9e (patch)
tree0bcbc2e540bbf8f62f6c17887cdd53b8c2cee637 /vendor/github.com/Antonboom/nilnil
parent54e657429ab892ad06c90cd7c1a4eb33ba93a3dc (diff)
vendor: update
Diffstat (limited to 'vendor/github.com/Antonboom/nilnil')
-rw-r--r--vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go136
-rw-r--r--vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go28
2 files changed, 96 insertions, 68 deletions
diff --git a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go
index e980db546..5646ee909 100644
--- a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go
+++ b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go
@@ -2,6 +2,9 @@ package analyzer
import (
"go/ast"
+ "go/token"
+ "go/types"
+ "strconv"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
@@ -40,29 +43,15 @@ func newNilNil() *nilNil {
}
}
-var (
- types = []ast.Node{(*ast.TypeSpec)(nil)}
-
- funcAndReturns = []ast.Node{
- (*ast.FuncDecl)(nil),
- (*ast.FuncLit)(nil),
- (*ast.ReturnStmt)(nil),
- }
-)
-
-type typeSpecByName map[string]typer
+var funcAndReturns = []ast.Node{
+ (*ast.FuncDecl)(nil),
+ (*ast.FuncLit)(nil),
+ (*ast.ReturnStmt)(nil),
+}
func (n *nilNil) run(pass *analysis.Pass) (interface{}, error) {
insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
- typeSpecs := typeSpecByName{
- "any": newTyper(new(ast.InterfaceType)),
- }
- insp.Preorder(types, func(node ast.Node) {
- t := node.(*ast.TypeSpec)
- typeSpecs[t.Name.Name] = newTyper(t.Type)
- })
-
var fs funcTypeStack
insp.Nodes(funcAndReturns, func(node ast.Node, push bool) (proceed bool) {
switch v := node.(type) {
@@ -87,13 +76,32 @@ func (n *nilNil) run(pass *analysis.Pass) (interface{}, error) {
return false
}
- fRes1, fRes2 := ft.Results.List[0], ft.Results.List[1]
- if !(n.isDangerNilField(fRes1, typeSpecs) && n.isErrorField(fRes2)) {
+ fRes1Type := pass.TypesInfo.TypeOf(ft.Results.List[0].Type)
+ if fRes1Type == nil {
return false
}
- rRes1, rRes2 := v.Results[0], v.Results[1]
- if isNil(rRes1) && isNil(rRes2) {
+ fRes2Type := pass.TypesInfo.TypeOf(ft.Results.List[1].Type)
+ if fRes2Type == nil {
+ return false
+ }
+
+ ok, zv := n.isDangerNilType(fRes1Type)
+ if !(ok && isErrorType(fRes2Type)) {
+ return false
+ }
+
+ retVal, retErr := v.Results[0], v.Results[1]
+
+ var needWarn bool
+ switch zv {
+ case zeroValueNil:
+ needWarn = isNil(pass, retVal) && isNil(pass, retErr)
+ case zeroValueZero:
+ needWarn = isZero(retVal) && isNil(pass, retErr)
+ }
+
+ if needWarn {
pass.Reportf(v.Pos(), reportMsg)
}
}
@@ -104,55 +112,73 @@ func (n *nilNil) run(pass *analysis.Pass) (interface{}, error) {
return nil, nil //nolint:nilnil
}
-func (n *nilNil) isDangerNilField(f *ast.Field, typeSpecs typeSpecByName) bool {
- return n.isDangerNilType(f.Type, typeSpecs)
-}
+type zeroValue int
-func (n *nilNil) isDangerNilType(t ast.Expr, typeSpecs typeSpecByName) bool {
+const (
+ zeroValueNil = iota + 1
+ zeroValueZero
+)
+
+func (n *nilNil) isDangerNilType(t types.Type) (bool, zeroValue) {
switch v := t.(type) {
- case *ast.StarExpr:
- return n.checkedTypes.Contains(ptrType)
+ case *types.Pointer:
+ return n.checkedTypes.Contains(ptrType), zeroValueNil
- case *ast.FuncType:
- return n.checkedTypes.Contains(funcType)
+ case *types.Signature:
+ return n.checkedTypes.Contains(funcType), zeroValueNil
- case *ast.InterfaceType:
- return n.checkedTypes.Contains(ifaceType)
+ case *types.Interface:
+ return n.checkedTypes.Contains(ifaceType), zeroValueNil
- case *ast.MapType:
- return n.checkedTypes.Contains(mapType)
+ case *types.Map:
+ return n.checkedTypes.Contains(mapType), zeroValueNil
- case *ast.ChanType:
- return n.checkedTypes.Contains(chanType)
+ case *types.Chan:
+ return n.checkedTypes.Contains(chanType), zeroValueNil
- case *ast.Ident:
- if t, ok := typeSpecs[v.Name]; ok {
- return n.isDangerNilType(t.Type(), typeSpecs)
+ case *types.Basic:
+ if v.Kind() == types.Uintptr {
+ return n.checkedTypes.Contains(uintptrType), zeroValueZero
+ }
+ if v.Kind() == types.UnsafePointer {
+ return n.checkedTypes.Contains(unsafeptrType), zeroValueNil
}
+
+ case *types.Named:
+ return n.isDangerNilType(v.Underlying())
}
- return false
+ return false, 0
}
-func (n *nilNil) isErrorField(f *ast.Field) bool {
- return isIdent(f.Type, "error")
-}
+var errorIface = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
-func isNil(e ast.Expr) bool {
- return isIdent(e, "nil")
+func isErrorType(t types.Type) bool {
+ _, ok := t.Underlying().(*types.Interface)
+ return ok && types.Implements(t, errorIface)
}
-func isIdent(n ast.Node, name string) bool {
- i, ok := n.(*ast.Ident)
+func isNil(pass *analysis.Pass, e ast.Expr) bool {
+ i, ok := e.(*ast.Ident)
if !ok {
return false
}
- return i.Name == name
-}
-type typer interface {
- Type() ast.Expr
+ _, ok = pass.TypesInfo.ObjectOf(i).(*types.Nil)
+ return ok
}
-func newTyper(t ast.Expr) typer { return typerImpl{t: t} } //
-type typerImpl struct{ t ast.Expr } //
-func (ti typerImpl) Type() ast.Expr { return ti.t }
+func isZero(e ast.Expr) bool {
+ bl, ok := e.(*ast.BasicLit)
+ if !ok {
+ return false
+ }
+ if bl.Kind != token.INT {
+ return false
+ }
+
+ v, err := strconv.ParseInt(bl.Value, 0, 64)
+ if err != nil {
+ return false
+ }
+ return v == 0
+}
diff --git a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go
index 520b813a5..c9b8e3eed 100644
--- a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go
+++ b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go
@@ -8,11 +8,13 @@ import (
func newDefaultCheckedTypes() checkedTypes {
return checkedTypes{
- ptrType: struct{}{},
- funcType: struct{}{},
- ifaceType: struct{}{},
- mapType: struct{}{},
- chanType: struct{}{},
+ ptrType: {},
+ funcType: {},
+ ifaceType: {},
+ mapType: {},
+ chanType: {},
+ uintptrType: {},
+ unsafeptrType: {},
}
}
@@ -25,15 +27,15 @@ func (t typeName) S() string {
}
const (
- ptrType typeName = "ptr"
- funcType typeName = "func"
- ifaceType typeName = "iface"
- mapType typeName = "map"
- chanType typeName = "chan"
+ ptrType typeName = "ptr"
+ funcType typeName = "func"
+ ifaceType typeName = "iface"
+ mapType typeName = "map"
+ chanType typeName = "chan"
+ uintptrType typeName = "uintptr"
+ unsafeptrType typeName = "unsafeptr"
)
-var knownTypes = []typeName{ptrType, funcType, ifaceType, mapType, chanType}
-
type checkedTypes map[typeName]struct{}
func (c checkedTypes) Contains(t typeName) bool {
@@ -60,7 +62,7 @@ func (c checkedTypes) Set(s string) error {
c.disableAll()
for _, t := range types {
switch tt := typeName(t); tt {
- case ptrType, funcType, ifaceType, mapType, chanType:
+ case ptrType, funcType, ifaceType, mapType, chanType, uintptrType, unsafeptrType:
c[tt] = struct{}{}
default:
return fmt.Errorf("unknown checked type name %q (see help)", t)