aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/sonatard/noctx/reqwithoutctx
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-09-15 18:05:35 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-09-15 19:34:30 +0200
commit712de1c63d9db97c81af68cd0dc4372c53d2e57a (patch)
treeae1761fec52c3ae4ddd003a4130ddbda8d0a2d69 /vendor/github.com/sonatard/noctx/reqwithoutctx
parent298a69c38dd5c8a9bbd7a022e88f4ddbcf885e16 (diff)
vendor/github.com/golangci/golangci-lint: update to v1.31
Diffstat (limited to 'vendor/github.com/sonatard/noctx/reqwithoutctx')
-rw-r--r--vendor/github.com/sonatard/noctx/reqwithoutctx/main.go14
-rw-r--r--vendor/github.com/sonatard/noctx/reqwithoutctx/report.go26
-rw-r--r--vendor/github.com/sonatard/noctx/reqwithoutctx/ssa.go180
3 files changed, 220 insertions, 0 deletions
diff --git a/vendor/github.com/sonatard/noctx/reqwithoutctx/main.go b/vendor/github.com/sonatard/noctx/reqwithoutctx/main.go
new file mode 100644
index 000000000..b09e1de1b
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/reqwithoutctx/main.go
@@ -0,0 +1,14 @@
+package reqwithoutctx
+
+import (
+ "golang.org/x/tools/go/analysis"
+)
+
+func Run(pass *analysis.Pass) (interface{}, error) {
+ analyzer := NewAnalyzer(pass)
+ reports := analyzer.Exec()
+
+ report(pass, reports)
+
+ return nil, nil
+}
diff --git a/vendor/github.com/sonatard/noctx/reqwithoutctx/report.go b/vendor/github.com/sonatard/noctx/reqwithoutctx/report.go
new file mode 100644
index 000000000..1c94e3148
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/reqwithoutctx/report.go
@@ -0,0 +1,26 @@
+package reqwithoutctx
+
+import (
+ "go/token"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/ssa"
+)
+
+type Report struct {
+ Instruction ssa.Instruction
+}
+
+func (n *Report) Pos() token.Pos {
+ return n.Instruction.Pos()
+}
+
+func (n *Report) Message() string {
+ return "should rewrite http.NewRequestWithContext or add (*Request).WithContext"
+}
+
+func report(pass *analysis.Pass, reports []*Report) {
+ for _, report := range reports {
+ pass.Reportf(report.Pos(), report.Message())
+ }
+}
diff --git a/vendor/github.com/sonatard/noctx/reqwithoutctx/ssa.go b/vendor/github.com/sonatard/noctx/reqwithoutctx/ssa.go
new file mode 100644
index 000000000..35751269e
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/reqwithoutctx/ssa.go
@@ -0,0 +1,180 @@
+package reqwithoutctx
+
+import (
+ "go/types"
+
+ "github.com/gostaticanalysis/analysisutil"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/buildssa"
+ "golang.org/x/tools/go/ssa"
+)
+
+type Analyzer struct {
+ Funcs []*ssa.Function
+ newRequestType types.Type
+ requestType types.Type
+}
+
+func NewAnalyzer(pass *analysis.Pass) *Analyzer {
+ newRequestType := analysisutil.TypeOf(pass, "net/http", "NewRequest")
+ requestType := analysisutil.TypeOf(pass, "net/http", "*Request")
+
+ srcFuncs := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA).SrcFuncs
+
+ return &Analyzer{
+ Funcs: srcFuncs,
+ newRequestType: newRequestType,
+ requestType: requestType,
+ }
+}
+
+func (a *Analyzer) Exec() []*Report {
+ if a.newRequestType == nil || a.requestType == nil {
+ return []*Report{}
+ }
+
+ usedReqs := a.usedReqs()
+ newReqs := a.requestsByNewRequest()
+
+ return a.report(usedReqs, newReqs)
+}
+
+func (a *Analyzer) report(usedReqs map[string]*ssa.Extract, newReqs map[*ssa.Call]*ssa.Extract) []*Report {
+ var reports []*Report
+
+ for _, fReq := range usedReqs {
+ for newRequest, req := range newReqs {
+ if fReq == req {
+ reports = append(reports, &Report{Instruction: newRequest})
+ }
+ }
+ }
+
+ return reports
+}
+
+func (a *Analyzer) usedReqs() map[string]*ssa.Extract {
+ reqExts := make(map[string]*ssa.Extract)
+
+ for _, f := range a.Funcs {
+ for _, b := range f.Blocks {
+ for _, instr := range b.Instrs {
+ switch i := instr.(type) {
+ case *ssa.Call:
+ exts := a.usedReqByCall(i)
+ for _, ext := range exts {
+ key := i.String() + ext.String()
+ reqExts[key] = ext
+ }
+ case *ssa.UnOp:
+ ext := a.usedReqByUnOp(i)
+ if ext != nil {
+ key := i.String() + ext.String()
+ reqExts[key] = ext
+ }
+ case *ssa.Return:
+ exts := a.usedReqByReturn(i)
+ for _, ext := range exts {
+ key := i.String() + ext.String()
+ reqExts[key] = ext
+ }
+ }
+ }
+ }
+ }
+
+ return reqExts
+}
+
+func (a *Analyzer) usedReqByCall(call *ssa.Call) []*ssa.Extract {
+ var exts []*ssa.Extract
+
+ // skip net/http.Request method call
+ if call.Common().Signature().Recv() != nil && types.Identical(call.Value().Type(), a.requestType) {
+ return exts
+ }
+
+ args := call.Common().Args
+ if len(args) == 0 {
+ return exts
+ }
+
+ for _, arg := range args {
+ ext, ok := arg.(*ssa.Extract)
+ if !ok {
+ continue
+ }
+
+ if !types.Identical(ext.Type(), a.requestType) {
+ continue
+ }
+
+ exts = append(exts, ext)
+ }
+
+ return exts
+}
+
+func (a *Analyzer) usedReqByUnOp(op *ssa.UnOp) *ssa.Extract {
+ if ext, ok := op.X.(*ssa.Extract); ok && types.Identical(ext.Type(), a.requestType) {
+ return ext
+ }
+
+ return nil
+}
+
+func (a *Analyzer) usedReqByReturn(ret *ssa.Return) []*ssa.Extract {
+ rets := ret.Results
+ exts := make([]*ssa.Extract, 0, len(rets))
+
+ for _, ret := range rets {
+ ext, ok := ret.(*ssa.Extract)
+ if !ok {
+ continue
+ }
+
+ if types.Identical(ext.Type(), a.requestType) {
+ exts = append(exts, ext)
+ }
+ }
+
+ return exts
+}
+
+func (a *Analyzer) requestsByNewRequest() map[*ssa.Call]*ssa.Extract {
+ reqs := make(map[*ssa.Call]*ssa.Extract)
+
+ for _, f := range a.Funcs {
+ for _, b := range f.Blocks {
+ for _, instr := range b.Instrs {
+ ext, ok := instr.(*ssa.Extract)
+ if !ok {
+ continue
+ }
+
+ if !types.Identical(ext.Type(), a.requestType) {
+ continue
+ }
+
+ operands := ext.Operands([]*ssa.Value{})
+ if len(operands) != 1 {
+ continue
+ }
+
+ operand := *operands[0]
+
+ f, ok := operand.(*ssa.Call)
+ if !ok {
+ continue
+ }
+
+ if types.Identical(f.Call.Value.Type(), a.newRequestType) {
+ reqs[f] = ext
+ }
+ }
+ }
+ }
+
+ return reqs
+}