diff options
| author | Taras Madan <tarasmadan@google.com> | 2024-09-10 12:16:33 +0200 |
|---|---|---|
| committer | Taras Madan <tarasmadan@google.com> | 2024-09-10 14:05:26 +0000 |
| commit | c97c816133b42257d0bcf1ee4bd178bb2a7a2b9e (patch) | |
| tree | 0bcbc2e540bbf8f62f6c17887cdd53b8c2cee637 /vendor/github.com/Antonboom/nilnil | |
| parent | 54e657429ab892ad06c90cd7c1a4eb33ba93a3dc (diff) | |
vendor: update
Diffstat (limited to 'vendor/github.com/Antonboom/nilnil')
| -rw-r--r-- | vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go | 136 | ||||
| -rw-r--r-- | vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go | 28 |
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) |
