aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/jingyugao
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2022-09-05 14:27:54 +0200
committerGitHub <noreply@github.com>2022-09-05 12:27:54 +0000
commitb2f2446b46bf02821d90ebedadae2bf7ae0e880e (patch)
tree923cf42842918d6bebca1d6bbdc08abed54d274d /vendor/github.com/jingyugao
parente6654faff4bcca4be92e9a8596fd4b77f747c39e (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.go197
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
}