aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/sonatard
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
parent298a69c38dd5c8a9bbd7a022e88f4ddbcf885e16 (diff)
vendor/github.com/golangci/golangci-lint: update to v1.31
Diffstat (limited to 'vendor/github.com/sonatard')
-rw-r--r--vendor/github.com/sonatard/noctx/.gitignore1
-rw-r--r--vendor/github.com/sonatard/noctx/.golangci.yml20
-rw-r--r--vendor/github.com/sonatard/noctx/LICENSE21
-rw-r--r--vendor/github.com/sonatard/noctx/Makefile16
-rw-r--r--vendor/github.com/sonatard/noctx/README.md95
-rw-r--r--vendor/github.com/sonatard/noctx/go.mod8
-rw-r--r--vendor/github.com/sonatard/noctx/go.sum16
-rw-r--r--vendor/github.com/sonatard/noctx/ngfunc/main.go57
-rw-r--r--vendor/github.com/sonatard/noctx/ngfunc/report.go29
-rw-r--r--vendor/github.com/sonatard/noctx/ngfunc/types.go65
-rw-r--r--vendor/github.com/sonatard/noctx/noctx.go31
-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
14 files changed, 579 insertions, 0 deletions
diff --git a/vendor/github.com/sonatard/noctx/.gitignore b/vendor/github.com/sonatard/noctx/.gitignore
new file mode 100644
index 000000000..2d830686d
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/.gitignore
@@ -0,0 +1 @@
+coverage.out
diff --git a/vendor/github.com/sonatard/noctx/.golangci.yml b/vendor/github.com/sonatard/noctx/.golangci.yml
new file mode 100644
index 000000000..1580acde2
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/.golangci.yml
@@ -0,0 +1,20 @@
+run:
+
+linters-settings:
+ govet:
+ enable-all: true
+
+linters:
+ enable-all: true
+ disable:
+ - gochecknoglobals
+ - gomnd
+ - gocognit
+ - nestif
+
+issues:
+ exclude-rules:
+ - path: reqwithoutctx/ssa.go
+ text: "Consider preallocating `exts`"
+ linters:
+ - prealloc
diff --git a/vendor/github.com/sonatard/noctx/LICENSE b/vendor/github.com/sonatard/noctx/LICENSE
new file mode 100644
index 000000000..a00d5727f
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 sonatard
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/sonatard/noctx/Makefile b/vendor/github.com/sonatard/noctx/Makefile
new file mode 100644
index 000000000..1a27f6b59
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/Makefile
@@ -0,0 +1,16 @@
+.PHONY: all imports test lint
+
+all: imports test lint
+
+imports:
+ goimports -w ./
+
+test:
+ go test -race ./...
+
+test_coverage:
+ go test -race -coverprofile=coverage.out -covermode=atomic ./...
+
+lint:
+ golangci-lint run ./...
+
diff --git a/vendor/github.com/sonatard/noctx/README.md b/vendor/github.com/sonatard/noctx/README.md
new file mode 100644
index 000000000..bfe9782c6
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/README.md
@@ -0,0 +1,95 @@
+# noctx
+
+![](https://github.com/sonatard/noctx/workflows/.github/workflows/ci.yml/badge.svg)
+
+`noctx` finds sending http request without context.Context.
+
+You should use `noctx` if sending http request in your library.
+Passing `context.Context` enables library user to cancel http request, getting trace information and so on.
+
+## Install
+
+```sh
+$ go get -u github.com/sonatard/noctx/cmd/noctx
+```
+
+## Usage
+
+```sh
+$ go vet -vettool=`which noctx` main.go
+./main.go:6:11: net/http.Get must not be called
+```
+
+## Detection rules
+- Executing following functions
+ - `net/http.Get`
+ - `net/http.Head`
+ - `net/http.Post`
+ - `net/http.PostForm`
+ - `(*net/http.Client).Get`
+ - `(*net/http.Client).Head`
+ - `(*net/http.Client).Post`
+ - `(*net/http.Client).PostForm`
+- `http.Request` returned by `http.NewRequest` function and passes it to other function.
+
+## How to fix
+- Send http request using `(*http.Client).Do(*http.Request)` method.
+- In Go 1.13 and later, use `http.NewRequestWithContext` function instead of using `http.NewRequest` function.
+- In Go 1.12 and earlier, call `(http.Request).WithContext(ctx)` after `http.NewRequest`.
+
+`(http.Request).WithContext(ctx)` has a disadvantage of performance because it returns a copy of `http.Request`. Use `http.NewRequestWithContext` function if you only support Go1.13 or later.
+
+## Sample Code
+
+```go
+package main
+
+import (
+ "context"
+ "net/http"
+)
+
+func main() {
+ const url = "http://example.com"
+ http.Get(url) // want `net/http\.Get must not be called`
+ http.Head(url) // want `net/http\.Head must not be called`
+ http.Post(url, "", nil) // want `net/http\.Post must not be called`
+ http.PostForm(url, nil) // want `net/http\.PostForm must not be called`
+
+ cli := &http.Client{}
+ cli.Get(url) // want `\(\*net/http\.Client\)\.Get must not be called`
+ cli.Head(url) // want `\(\*net/http\.Client\)\.Head must not be called`
+ cli.Post(url, "", nil) // want `\(\*net/http\.Client\)\.Post must not be called`
+ cli.PostForm(url, nil) // want `\(\*net/http\.Client\)\.PostForm must not be called`
+
+ req, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext`
+ cli.Do(req)
+
+ ctx := context.Background()
+ req2, _ := http.NewRequestWithContext(ctx, http.MethodPost, url, nil) // OK
+ cli.Do(req2)
+
+ req3, _ := http.NewRequest(http.MethodPost, url, nil) // OK
+ req3 = req3.WithContext(ctx)
+ cli.Do(req3)
+
+ f2 := func(req *http.Request, ctx context.Context) *http.Request {
+ return req
+ }
+ req4, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext`
+ req4 = f2(req4, ctx)
+ cli.Do(req4)
+
+ req5, _ := func() (*http.Request, error) {
+ return http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext`
+ }()
+ cli.Do(req5)
+
+}
+```
+
+## Reference
+- [net/http - NewRequest](https://golang.org/pkg/net/http/#NewRequest)
+- [net/http - NewRequestWithContext](https://golang.org/pkg/net/http/#NewRequestWithContext)
+- [net/http - Request.WithContext](https://golang.org/pkg/net/http/#Request.WithContext)
+
diff --git a/vendor/github.com/sonatard/noctx/go.mod b/vendor/github.com/sonatard/noctx/go.mod
new file mode 100644
index 000000000..47b7901a0
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/go.mod
@@ -0,0 +1,8 @@
+module github.com/sonatard/noctx
+
+go 1.13
+
+require (
+ github.com/gostaticanalysis/analysisutil v0.0.3
+ golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9
+)
diff --git a/vendor/github.com/sonatard/noctx/go.sum b/vendor/github.com/sonatard/noctx/go.sum
new file mode 100644
index 000000000..f8e5b0759
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/go.sum
@@ -0,0 +1,16 @@
+github.com/gostaticanalysis/analysisutil v0.0.3 h1:iwp+5/UAyzQSFgQ4uR2sni99sJ8Eo9DEacKWM5pekIg=
+github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9 h1:KOkk4e2xd5OeCDJGwacvr75ICCbCsShrHiqPEdsA9hg=
+golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/vendor/github.com/sonatard/noctx/ngfunc/main.go b/vendor/github.com/sonatard/noctx/ngfunc/main.go
new file mode 100644
index 000000000..cfeb0f001
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/ngfunc/main.go
@@ -0,0 +1,57 @@
+package ngfunc
+
+import (
+ "go/types"
+
+ "github.com/gostaticanalysis/analysisutil"
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/buildssa"
+)
+
+func Run(pass *analysis.Pass) (interface{}, error) {
+ ngFuncNames := []string{
+ "net/http.Get",
+ "net/http.Head",
+ "net/http.Post",
+ "net/http.PostForm",
+ "(*net/http.Client).Get",
+ "(*net/http.Client).Head",
+ "(*net/http.Client).Post",
+ "(*net/http.Client).PostForm",
+ }
+
+ ngFuncs := typeFuncs(pass, ngFuncNames)
+ if len(ngFuncs) == 0 {
+ return nil, nil
+ }
+
+ reportFuncs := ngCalledFuncs(pass, ngFuncs)
+ report(pass, reportFuncs)
+
+ return nil, nil
+}
+
+func ngCalledFuncs(pass *analysis.Pass, ngFuncs []*types.Func) []*Report {
+ var reports []*Report
+
+ srcFuncs := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA).SrcFuncs
+ for _, sf := range srcFuncs {
+ for _, b := range sf.Blocks {
+ for _, instr := range b.Instrs {
+ for _, ngFunc := range ngFuncs {
+ if analysisutil.Called(instr, nil, ngFunc) {
+ ngCalledFunc := &Report{
+ Instruction: instr,
+ function: ngFunc,
+ }
+ reports = append(reports, ngCalledFunc)
+
+ break
+ }
+ }
+ }
+ }
+ }
+
+ return reports
+}
diff --git a/vendor/github.com/sonatard/noctx/ngfunc/report.go b/vendor/github.com/sonatard/noctx/ngfunc/report.go
new file mode 100644
index 000000000..e50051798
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/ngfunc/report.go
@@ -0,0 +1,29 @@
+package ngfunc
+
+import (
+ "fmt"
+ "go/token"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/ssa"
+)
+
+type Report struct {
+ Instruction ssa.Instruction
+ function *types.Func
+}
+
+func (n *Report) Pos() token.Pos {
+ return n.Instruction.Pos()
+}
+
+func (n *Report) Message() string {
+ return fmt.Sprintf("%s must not be called", n.function.FullName())
+}
+
+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/ngfunc/types.go b/vendor/github.com/sonatard/noctx/ngfunc/types.go
new file mode 100644
index 000000000..f1877386c
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/ngfunc/types.go
@@ -0,0 +1,65 @@
+package ngfunc
+
+import (
+ "fmt"
+ "go/types"
+ "strings"
+
+ "github.com/gostaticanalysis/analysisutil"
+ "golang.org/x/tools/go/analysis"
+)
+
+var errNotFound = fmt.Errorf("function not found")
+
+func typeFuncs(pass *analysis.Pass, funcs []string) []*types.Func {
+ fs := make([]*types.Func, 0, len(funcs))
+
+ for _, fn := range funcs {
+ f, err := typeFunc(pass, fn)
+ if err != nil {
+ continue
+ }
+
+ fs = append(fs, f)
+ }
+
+ return fs
+}
+
+func typeFunc(pass *analysis.Pass, funcName string) (*types.Func, error) {
+ ss := strings.Split(strings.TrimSpace(funcName), ".")
+
+ switch len(ss) {
+ case 2:
+ // package function: pkgname.Func
+ f, ok := analysisutil.ObjectOf(pass, ss[0], ss[1]).(*types.Func)
+ if !ok || f == nil {
+ return nil, errNotFound
+ }
+
+ return f, nil
+ case 3:
+ // method: (*pkgname.Type).Method
+ pkgname := strings.TrimLeft(ss[0], "(")
+ typename := strings.TrimRight(ss[1], ")")
+
+ if pkgname != "" && pkgname[0] == '*' {
+ pkgname = pkgname[1:]
+ typename = "*" + typename
+ }
+
+ typ := analysisutil.TypeOf(pass, pkgname, typename)
+ if typ == nil {
+ return nil, errNotFound
+ }
+
+ m := analysisutil.MethodOf(typ, ss[2])
+ if m == nil {
+ return nil, errNotFound
+ }
+
+ return m, nil
+ }
+
+ return nil, errNotFound
+}
diff --git a/vendor/github.com/sonatard/noctx/noctx.go b/vendor/github.com/sonatard/noctx/noctx.go
new file mode 100644
index 000000000..478ad8855
--- /dev/null
+++ b/vendor/github.com/sonatard/noctx/noctx.go
@@ -0,0 +1,31 @@
+package noctx
+
+import (
+ "github.com/sonatard/noctx/ngfunc"
+ "github.com/sonatard/noctx/reqwithoutctx"
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/buildssa"
+)
+
+var Analyzer = &analysis.Analyzer{
+ Name: "noctx",
+ Doc: Doc,
+ Run: run,
+ Requires: []*analysis.Analyzer{
+ buildssa.Analyzer,
+ },
+}
+
+const Doc = "noctx finds sending http request without context.Context"
+
+func run(pass *analysis.Pass) (interface{}, error) {
+ if _, err := ngfunc.Run(pass); err != nil {
+ return nil, err
+ }
+
+ if _, err := reqwithoutctx.Run(pass); err != nil {
+ return nil, err
+ }
+
+ return nil, nil
+}
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
+}