diff options
| author | Taras Madan <tarasmadan@google.com> | 2022-09-05 14:27:54 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-09-05 12:27:54 +0000 |
| commit | b2f2446b46bf02821d90ebedadae2bf7ae0e880e (patch) | |
| tree | 923cf42842918d6bebca1d6bbdc08abed54d274d /vendor/github.com/jingyugao | |
| parent | e6654faff4bcca4be92e9a8596fd4b77f747c39e (diff) | |
go.mod, vendor: update (#3358)
* go.mod, vendor: remove unnecessary dependencies
Commands:
1. go mod tidy
2. go mod vendor
* go.mod, vendor: update cloud.google.com/go
Commands:
1. go get -u cloud.google.com/go
2. go mod tidy
3. go mod vendor
* go.mod, vendor: update cloud.google.com/*
Commands:
1. go get -u cloud.google.com/storage cloud.google.com/logging
2. go mod tidy
3. go mod vendor
* go.mod, .golangci.yml, vendor: update *lint*
Commands:
1. go get -u golang.org/x/tools github.com/golangci/golangci-lint@v1.47.0
2. go mod tidy
3. go mod vendor
4. edit .golangci.yml to suppress new errors (resolved in the same PR later)
* all: fix lint errors
hash.go: copy() recommended by gosimple
parse.go: ent is never nil
verifier.go: signal.Notify() with unbuffered channel is bad. Have no idea why.
* .golangci.yml: adjust godot rules
check-all is deprecated, but still work
if you're hesitating too - I'll remove this commit
Diffstat (limited to 'vendor/github.com/jingyugao')
| -rw-r--r-- | vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go | 197 |
1 files changed, 83 insertions, 114 deletions
diff --git a/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go b/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go index 1a3e96dec..a142a6744 100644 --- a/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go +++ b/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go @@ -1,12 +1,9 @@ package rowserr import ( - "fmt" "go/ast" "go/types" - "strconv" - "github.com/gostaticanalysis/analysisutil" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/buildssa" "golang.org/x/tools/go/ssa" @@ -30,11 +27,12 @@ const ( ) type runner struct { - pass *analysis.Pass - rowsTyp *types.Pointer - rowsObj types.Object - skipFile map[*ast.File]bool - sqlPkgs []string + pass *analysis.Pass + rowsTyp *types.Pointer + rowsInterface *types.Interface + rowsObj types.Object + skipFile map[*ast.File]bool + sqlPkgs []string } func NewRun(pkgs ...string) func(pass *analysis.Pass) (interface{}, error) { @@ -51,7 +49,7 @@ func NewRun(pkgs ...string) func(pass *analysis.Pass) (interface{}, error) { // run executes an analysis for the pass. The receiver is passed // by value because this func is called in parallel for different passes. -func (r runner) run(pass *analysis.Pass, pkgPath string) (interface{}, error) { +func (r runner) run(pass *analysis.Pass, pkgPath string) { r.pass = pass pssa := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA) funcs := pssa.SrcFuncs @@ -59,107 +57,108 @@ func (r runner) run(pass *analysis.Pass, pkgPath string) (interface{}, error) { pkg := pssa.Pkg.Prog.ImportedPackage(pkgPath) if pkg == nil { // skip - return nil, nil + return } - r.rowsObj = pkg.Type(rowsName).Object() + rowsType := pkg.Type(rowsName) + if rowsType == nil { + // skip checking + return + } + r.rowsObj = rowsType.Object() if r.rowsObj == nil { // skip checking - return nil, nil + return } resNamed, ok := r.rowsObj.Type().(*types.Named) if !ok { - return nil, nil + return + } + + rowsInterface, ok := r.rowsObj.Type().Underlying().(*types.Interface) + if ok { + r.rowsInterface = rowsInterface } r.rowsTyp = types.NewPointer(resNamed) r.skipFile = map[*ast.File]bool{} for _, f := range funcs { - if r.noImportedDBSQL(f) { - // skip this - continue - } - // skip if the function is just referenced - var isreffunc bool + var isRefFunc bool for i := 0; i < f.Signature.Results().Len(); i++ { if types.Identical(f.Signature.Results().At(i).Type(), r.rowsTyp) { - isreffunc = true + isRefFunc = true } } - if isreffunc { + if isRefFunc { continue } for _, b := range f.Blocks { for i := range b.Instrs { - if r.notCheck(b, i) { - pass.Reportf(b.Instrs[i].Pos(), fmt.Sprintf("rows.Err must be checked")) + if r.errCallMissing(b, i) { + pass.Reportf(b.Instrs[i].Pos(), "rows.Err must be checked") } } } } - - return nil, nil } -func (r *runner) notCheck(b *ssa.BasicBlock, i int) (ret bool) { - call, ok := r.getReqCall(b.Instrs[i]) +func (r *runner) errCallMissing(b *ssa.BasicBlock, i int) (ret bool) { + call, ok := r.getCallReturnsRow(b.Instrs[i]) if !ok { return false } for _, cRef := range *call.Referrers() { - val, ok := r.getResVal(cRef) + val, ok := r.getRowsVal(cRef) if !ok { continue } if len(*val.Referrers()) == 0 { - return true + continue } - resRefs := *val.Referrers() - var notCallClose func(resRef ssa.Instruction) bool - notCallClose = func(resRef ssa.Instruction) bool { + var errCalled func(resRef ssa.Instruction) bool + errCalled = func(resRef ssa.Instruction) bool { switch resRef := resRef.(type) { case *ssa.Phi: - resRefs = append(resRefs, (*resRef.Referrers())...) for _, rf := range *resRef.Referrers() { - if !notCallClose(rf) { - return false + if errCalled(rf) { + return true } } - case *ssa.Store: // Call in Closure function - if len(*resRef.Addr.Referrers()) == 0 { - return true - } - for _, aref := range *resRef.Addr.Referrers() { - if c, ok := aref.(*ssa.MakeClosure); ok { + switch c := aref.(type) { + case *ssa.MakeClosure: f := c.Fn.(*ssa.Function) - if r.noImportedDBSQL(f) { - // skip this - return false - } called := r.isClosureCalled(c) - - return r.calledInFunc(f, called) + if r.calledInFunc(f, called) { + return true + } + case *ssa.UnOp: + for _, rf := range *c.Referrers() { + if errCalled(rf) { + return true + } + } } - } case *ssa.Call: // Indirect function call - if r.isCloseCall(resRef) { - return false + if r.isErrCall(resRef) { + return true } if f, ok := resRef.Call.Value.(*ssa.Function); ok { for _, b := range f.Blocks { for i := range b.Instrs { - return r.notCheck(b, i) + if !r.errCallMissing(b, i) { + return true + } } } } @@ -171,55 +170,63 @@ func (r *runner) notCheck(b *ssa.BasicBlock, i int) (ret bool) { } for _, ccall := range *bOp.Referrers() { - if r.isCloseCall(ccall) { - return false + if r.isErrCall(ccall) { + return true } } } - } - return true + + return false } for _, resRef := range resRefs { - if !notCallClose(resRef) { + if errCalled(resRef) { return false } } } + return true } -func (r *runner) getReqCall(instr ssa.Instruction) (*ssa.Call, bool) { +func (r *runner) getCallReturnsRow(instr ssa.Instruction) (*ssa.Call, bool) { call, ok := instr.(*ssa.Call) if !ok { return nil, false } res := call.Call.Signature().Results() - flag := false for i := 0; i < res.Len(); i++ { - flag = flag || types.Identical(res.At(i).Type(), r.rowsTyp) - } - - if !flag { - return nil, false + typeToCheck := res.At(i).Type() + if types.Identical(typeToCheck, r.rowsTyp) { + return call, true + } + if r.rowsInterface != nil && types.Implements(typeToCheck, r.rowsInterface) { + return call, true + } } - return call, true + return nil, false } -func (r *runner) getResVal(instr ssa.Instruction) (ssa.Value, bool) { +func (r *runner) getRowsVal(instr ssa.Instruction) (ssa.Value, bool) { switch instr := instr.(type) { case *ssa.Call: if len(instr.Call.Args) == 1 && types.Identical(instr.Call.Args[0].Type(), r.rowsTyp) { return instr.Call.Args[0], true } + if len(instr.Call.Args) == 1 && r.rowsInterface != nil && types.Implements(instr.Call.Args[0].Type(), r.rowsInterface) { + return instr.Call.Args[0], true + } case ssa.Value: if types.Identical(instr.Type(), r.rowsTyp) { return instr, true } + if r.rowsInterface != nil && types.Implements(instr.Type(), r.rowsInterface) { + return instr, true + } default: } @@ -238,16 +245,22 @@ func (r *runner) getBodyOp(instr ssa.Instruction) (*ssa.UnOp, bool) { return op, true } -func (r *runner) isCloseCall(ccall ssa.Instruction) bool { +func (r *runner) isErrCall(ccall ssa.Instruction) bool { switch ccall := ccall.(type) { case *ssa.Defer: if ccall.Call.Value != nil && ccall.Call.Value.Name() == errMethod { return true } + if ccall.Call.Method != nil && ccall.Call.Method.Name() == errMethod { + return true + } case *ssa.Call: if ccall.Call.Value != nil && ccall.Call.Value.Name() == errMethod { return true } + if ccall.Call.Method != nil && ccall.Call.Method.Name() == errMethod { + return true + } } return false @@ -264,40 +277,6 @@ func (r *runner) isClosureCalled(c *ssa.MakeClosure) bool { return false } -func (r *runner) noImportedDBSQL(f *ssa.Function) (ret bool) { - obj := f.Object() - if obj == nil { - return false - } - - file := analysisutil.File(r.pass, obj.Pos()) - if file == nil { - return false - } - - if skip, has := r.skipFile[file]; has { - return skip - } - defer func() { - r.skipFile[file] = ret - }() - - for _, impt := range file.Imports { - path, err := strconv.Unquote(impt.Path.Value) - if err != nil { - continue - } - path = analysisutil.RemoveVendor(path) - for _, pkg := range r.sqlPkgs { - if pkg == path { - return false - } - } - } - - return true -} - func (r *runner) calledInFunc(f *ssa.Function, called bool) bool { for _, b := range f.Blocks { for i, instr := range b.Instrs { @@ -308,28 +287,18 @@ func (r *runner) calledInFunc(f *ssa.Function, called bool) bool { if vCall, ok := v.(*ssa.Call); ok { if vCall.Call.Value != nil && vCall.Call.Value.Name() == errMethod { if called { - return false + return true } } } } } default: - if r.notCheck(b, i) || !called { - return true + if r.errCallMissing(b, i) || !called { + return false } } } } - return true -} - -// isNamedType reports whether t is the named type path.name. -func isNamedType(t types.Type, path, name string) bool { - n, ok := t.(*types.Named) - if !ok { - return false - } - obj := n.Obj() - return obj.Name() == name && obj.Pkg() != nil && obj.Pkg().Path() == path + return false } |
