aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/kyoh86/exportloopref
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2023-02-22 22:16:50 +0100
committerTaras Madan <tarasmadan@google.com>2023-02-24 12:47:23 +0100
commit4165372ec8fd142475a4e35fd0cf4f8042132208 (patch)
tree21cd62211b4dd80bee469054c5b65db77342333c /vendor/github.com/kyoh86/exportloopref
parent2b3ed821a493b8936c8bacfa6f8b4f1c90a00855 (diff)
dependencies: update
set go min requirements to 1.19 update dependencies update vendor
Diffstat (limited to 'vendor/github.com/kyoh86/exportloopref')
-rw-r--r--vendor/github.com/kyoh86/exportloopref/.goreleaser.yml88
-rw-r--r--vendor/github.com/kyoh86/exportloopref/README.md8
-rw-r--r--vendor/github.com/kyoh86/exportloopref/exportloopref.go169
-rw-r--r--vendor/github.com/kyoh86/exportloopref/go.mod5
-rw-r--r--vendor/github.com/kyoh86/exportloopref/go.sum20
5 files changed, 152 insertions, 138 deletions
diff --git a/vendor/github.com/kyoh86/exportloopref/.goreleaser.yml b/vendor/github.com/kyoh86/exportloopref/.goreleaser.yml
index 22ff44040..95d44aaac 100644
--- a/vendor/github.com/kyoh86/exportloopref/.goreleaser.yml
+++ b/vendor/github.com/kyoh86/exportloopref/.goreleaser.yml
@@ -1,43 +1,51 @@
+# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
+
project_name: exportloopref
-release:
- github:
- owner: kyoh86
- name: exportloopref
-brews:
-- install: |
- bin.install "exportloopref"
- github:
- owner: kyoh86
- name: homebrew-tap
- folder: Formula
- homepage: https://github.com/kyoh86/exportloopref
- description: An analyzer that finds exporting pointers for loop variables.
builds:
-- goos:
- - linux
- - darwin
- - windows
- goarch:
- - amd64
- - "386"
- main: ./cmd/exportloopref
- ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
- binary: exportloopref
+ - id: default
+ goos:
+ - linux
+ - darwin
+ - windows
+ goarch:
+ - amd64
+ - arm64
+ - "386"
+ main: ./cmd/exportloopref
+ binary: exportloopref
+brews:
+ - install: |
+ bin.install "exportloopref"
+ tap:
+ owner: kyoh86
+ name: homebrew-tap
+ folder: Formula
+ homepage: https://github.com/kyoh86/exportloopref
+ description: An analyzer that finds exporting pointers for loop variables.
+ license: MIT
+nfpms:
+ - builds:
+ - default
+ maintainer: kyoh86 <me@kyoh86.dev>
+ homepage: https://github.com/kyoh86/exportloopref
+ description: An analyzer that finds exporting pointers for loop variables.
+ license: MIT
+ formats:
+ - apk
+ - deb
+ - rpm
archives:
-- id: gzip
- format: tar.gz
- format_overrides:
- - goos: windows
- format: zip
- name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
- files:
- - licence*
- - LICENCE*
- - license*
- - LICENSE*
- - readme*
- - README*
- - changelog*
- - CHANGELOG*
-snapshot:
- name_template: SNAPSHOT-{{ .Commit }}
+ - id: gzip
+ format: tar.gz
+ format_overrides:
+ - goos: windows
+ format: zip
+ files:
+ - licence*
+ - LICENCE*
+ - license*
+ - LICENSE*
+ - readme*
+ - README*
+ - changelog*
+ - CHANGELOG*
diff --git a/vendor/github.com/kyoh86/exportloopref/README.md b/vendor/github.com/kyoh86/exportloopref/README.md
index 5c019c738..0f581ffce 100644
--- a/vendor/github.com/kyoh86/exportloopref/README.md
+++ b/vendor/github.com/kyoh86/exportloopref/README.md
@@ -1,6 +1,8 @@
# exportloopref
An analyzer that finds exporting pointers for loop variables.
+![](https://repository-images.githubusercontent.com/256768552/a1c5bb80-dd73-11eb-9453-e520f517e730)
+Pin them all!
[![PkgGoDev](https://pkg.go.dev/badge/kyoh86/exportloopref)](https://pkg.go.dev/kyoh86/exportloopref)
[![Go Report Card](https://goreportcard.com/badge/github.com/kyoh86/exportloopref)](https://goreportcard.com/report/github.com/kyoh86/exportloopref)
@@ -9,7 +11,7 @@ An analyzer that finds exporting pointers for loop variables.
## What's this?
-Sample problem code from: https://github.com/kyoh86/exportloopref/blob/master/testdata/src/simple/simple.go
+Sample problem code from: https://github.com/kyoh86/exportloopref/blob/main/testdata/src/simple/simple.go
```go
package main
@@ -109,7 +111,7 @@ func printp(p *int) {
}
```
-ref: https://github.com/kyoh86/exportloopref/blob/master/testdata/src/fixed/fixed.go
+ref: https://github.com/kyoh86/exportloopref/blob/main/testdata/src/fixed/fixed.go
## Sensing policy
@@ -120,7 +122,7 @@ e.g.
```go
var s Foo
-for _, p := []int{10, 11, 12, 13} {
+for _, p := range []int{10, 11, 12, 13} {
s.Bar(&p) // If s stores the pointer, it will be bug.
}
```
diff --git a/vendor/github.com/kyoh86/exportloopref/exportloopref.go b/vendor/github.com/kyoh86/exportloopref/exportloopref.go
index 4d1671a06..d071d5c35 100644
--- a/vendor/github.com/kyoh86/exportloopref/exportloopref.go
+++ b/vendor/github.com/kyoh86/exportloopref/exportloopref.go
@@ -17,21 +17,15 @@ var Analyzer = &analysis.Analyzer{
Run: run,
RunDespiteErrors: true,
Requires: []*analysis.Analyzer{inspect.Analyzer},
- // ResultType reflect.Type
- // FactTypes []Fact
-}
-
-func init() {
- // Analyzer.Flags.StringVar(&v, "name", "default", "description")
}
func run(pass *analysis.Pass) (interface{}, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
search := &Searcher{
- Stats: map[token.Pos]struct{}{},
- Vars: map[token.Pos]map[token.Pos]struct{}{},
- Types: pass.TypesInfo.Types,
+ LoopVars: map[token.Pos]struct{}{},
+ LocalVars: map[token.Pos]map[token.Pos]struct{}{},
+ Pass: pass,
}
nodeFilter := []ast.Node{
@@ -42,50 +36,60 @@ func run(pass *analysis.Pass) (interface{}, error) {
(*ast.UnaryExpr)(nil),
}
- inspect.WithStack(nodeFilter, func(n ast.Node, push bool, stack []ast.Node) bool {
- id, insert, digg := search.Check(n, stack)
- if id != nil {
- dMsg := fmt.Sprintf("exporting a pointer for the loop variable %s", id.Name)
- fMsg := fmt.Sprintf("loop variable %s should be pinned", id.Name)
- var suggest []analysis.SuggestedFix
- if insert != token.NoPos {
- suggest = []analysis.SuggestedFix{{
- Message: fMsg,
- TextEdits: []analysis.TextEdit{{
- Pos: insert,
- End: insert,
- NewText: []byte(fmt.Sprintf("%[1]s := %[1]s\n", id.Name)),
- }},
- }}
- }
- d := analysis.Diagnostic{Pos: id.Pos(),
- End: id.End(),
- Message: dMsg,
- Category: "exportloopref",
- SuggestedFixes: suggest,
- }
- pass.Report(d)
- }
- return digg
- })
+ inspect.WithStack(nodeFilter, search.CheckAndReport)
return nil, nil
}
type Searcher struct {
- // Statement variables : map to collect positions that
- // variables are declared like below.
+ // LoopVars is positions that loop-variables are declared like below.
// - for <KEY>, <VALUE> := range ...
- // - var <X> int
- // - D := ...
- Stats map[token.Pos]struct{}
- // Local variables maps loop-position, decl-location to ignore
- // safe pointers for variable which declared in the loop.
- Vars map[token.Pos]map[token.Pos]struct{}
- Types map[ast.Expr]types.TypeAndValue
+ // - for <VALUE> := <INIT>; <CONDITION>; <INCREMENT>
+ LoopVars map[token.Pos]struct{}
+ // LocalVars is positions of loops and the variables declared in them.
+ // Use this to determine if a point assignment is an export outside the loop.
+ LocalVars map[token.Pos]map[token.Pos]struct{}
+
+ Pass *analysis.Pass
+}
+
+// CheckAndReport inspects each node with stack.
+// It is implemented as the I/F of the "golang.org/x/tools/go/analysis/passes/inspect".Analysis.WithStack.
+func (s *Searcher) CheckAndReport(n ast.Node, push bool, stack []ast.Node) bool {
+ id, insert, digg := s.Check(n, stack)
+ if id == nil {
+ // no prob.
+ return digg
+ }
+
+ // suggests fix
+ var suggest []analysis.SuggestedFix
+ if insert != token.NoPos {
+ suggest = []analysis.SuggestedFix{{
+ Message: fmt.Sprintf("loop variable %s should be pinned", id.Name),
+ TextEdits: []analysis.TextEdit{{
+ Pos: insert,
+ End: insert,
+ NewText: []byte(fmt.Sprintf("%[1]s := %[1]s\n", id.Name)),
+ }},
+ }}
+ }
+
+ // report a diagnostic
+ d := analysis.Diagnostic{Pos: id.Pos(),
+ End: id.End(),
+ Message: fmt.Sprintf("exporting a pointer for the loop variable %s", id.Name),
+ Category: "exportloopref",
+ SuggestedFixes: suggest,
+ }
+ s.Pass.Report(d)
+ return digg
}
-func (s *Searcher) Check(n ast.Node, stack []ast.Node) (*ast.Ident, token.Pos, bool) {
+// Check each node and stack, whether it exports loop variables or not.
+// Finding export, report the *ast.Ident of exported loop variable,
+// and token.Pos to insert assignment to fix the diagnostic.
+func (s *Searcher) Check(n ast.Node, stack []ast.Node) (loopVar *ast.Ident, insertPos token.Pos, digg bool) {
switch typed := n.(type) {
case *ast.RangeStmt:
s.parseRangeStmt(typed)
@@ -102,72 +106,92 @@ func (s *Searcher) Check(n ast.Node, stack []ast.Node) (*ast.Ident, token.Pos, b
return nil, token.NoPos, true
}
+// parseRangeStmt will check range statement (i.e. `for <KEY>, <VALUE> := range ...`),
+// and collect positions of <KEY> and <VALUE>.
func (s *Searcher) parseRangeStmt(n *ast.RangeStmt) {
- s.addStat(n.Key)
- s.addStat(n.Value)
+ s.storeLoopVars(n.Key)
+ s.storeLoopVars(n.Value)
}
+// parseForStmt will check for statement (i.e. `for <VALUE> := <INIT>; <CONDITION>; <INCREMENT>`),
+// and collect positions of <VALUE>.
func (s *Searcher) parseForStmt(n *ast.ForStmt) {
switch post := n.Post.(type) {
case *ast.AssignStmt:
// e.g. for p = head; p != nil; p = p.next
for _, lhs := range post.Lhs {
- s.addStat(lhs)
+ s.storeLoopVars(lhs)
}
case *ast.IncDecStmt:
// e.g. for i := 0; i < n; i++
- s.addStat(post.X)
+ s.storeLoopVars(post.X)
}
}
-func (s *Searcher) addStat(expr ast.Expr) {
+func (s *Searcher) storeLoopVars(expr ast.Expr) {
if id, ok := expr.(*ast.Ident); ok {
- s.Stats[id.Pos()] = struct{}{}
+ s.LoopVars[id.Pos()] = struct{}{}
}
}
+// parseDeclStmt will parse declaring statement (i.e. `var`, `type`, `const`),
+// and store the position if it is "var" declaration and is in any loop.
func (s *Searcher) parseDeclStmt(n *ast.DeclStmt, stack []ast.Node) {
+ genDecl, ok := n.Decl.(*ast.GenDecl)
+ if !ok {
+ // (dead branch)
+ // if the Decl is not GenDecl (i.e. `var`, `type` or `const` statement), it is ignored
+ return
+ }
+ if genDecl.Tok != token.VAR {
+ // if the Decl is not `var` (may be `type` or `const`), it is ignored
+ return
+ }
+
loop, _ := s.innermostLoop(stack)
if loop == nil {
return
}
- // Register declaring variables
- if genDecl, ok := n.Decl.(*ast.GenDecl); ok && genDecl.Tok == token.VAR {
- for _, spec := range genDecl.Specs {
- for _, name := range spec.(*ast.ValueSpec).Names {
- s.addVar(loop, name)
- }
+ // Register declared variables
+ for _, spec := range genDecl.Specs {
+ for _, name := range spec.(*ast.ValueSpec).Names {
+ s.storeLocalVar(loop, name)
}
}
}
+// parseDeclStmt will parse assignment statement (i.e. `<VAR> = <VALUE>`),
+// and store the position if it is .
func (s *Searcher) parseAssignStmt(n *ast.AssignStmt, stack []ast.Node) {
+ if n.Tok != token.DEFINE {
+ // if the statement is simple assignment (without definement), it is ignored
+ return
+ }
+
loop, _ := s.innermostLoop(stack)
if loop == nil {
return
}
// Find statements declaring local variable
- if n.Tok == token.DEFINE {
- for _, h := range n.Lhs {
- s.addVar(loop, h)
- }
+ for _, h := range n.Lhs {
+ s.storeLocalVar(loop, h)
}
}
-func (s *Searcher) addVar(loop ast.Node, expr ast.Expr) {
+func (s *Searcher) storeLocalVar(loop ast.Node, expr ast.Expr) {
loopPos := loop.Pos()
id, ok := expr.(*ast.Ident)
if !ok {
return
}
- vars, ok := s.Vars[loopPos]
+ vars, ok := s.LocalVars[loopPos]
if !ok {
vars = map[token.Pos]struct{}{}
}
vars[id.Obj.Pos()] = struct{}{}
- s.Vars[loopPos] = vars
+ s.LocalVars[loopPos] = vars
}
func insertionPosition(block *ast.BlockStmt) token.Pos {
@@ -189,13 +213,15 @@ func (s *Searcher) innermostLoop(stack []ast.Node) (ast.Node, token.Pos) {
return nil, token.NoPos
}
+// checkUnaryExpr check unary expression (i.e. <OPERATOR><VAR> like `-x`, `*p` or `&v`) and stack.
+// THIS IS THE ESSENTIAL PART OF THIS PARSER.
func (s *Searcher) checkUnaryExpr(n *ast.UnaryExpr, stack []ast.Node) (*ast.Ident, token.Pos, bool) {
- loop, insert := s.innermostLoop(stack)
- if loop == nil {
+ if n.Op != token.AND {
return nil, token.NoPos, true
}
- if n.Op != token.AND {
+ loop, insert := s.innermostLoop(stack)
+ if loop == nil {
return nil, token.NoPos, true
}
@@ -207,7 +233,7 @@ func (s *Searcher) checkUnaryExpr(n *ast.UnaryExpr, stack []ast.Node) (*ast.Iden
// If the identity is not the loop statement variable,
// it will not be reported.
- if _, isStat := s.Stats[id.Obj.Pos()]; !isStat {
+ if _, isDecl := s.LoopVars[id.Obj.Pos()]; !isDecl {
return nil, token.NoPos, true
}
@@ -266,12 +292,15 @@ func (s *Searcher) checkUnaryExpr(n *ast.UnaryExpr, stack []ast.Node) (*ast.Iden
}
func (s *Searcher) isVar(loop ast.Node, expr ast.Expr) bool {
- vars := s.Vars[loop.Pos()] // map[token.Pos]struct{}
+ vars := s.LocalVars[loop.Pos()] // map[token.Pos]struct{}
if vars == nil {
return false
}
switch typed := expr.(type) {
case (*ast.Ident):
+ if typed.Obj == nil {
+ return false // global var in another file (ref: #13)
+ }
_, isVar := vars[typed.Obj.Pos()]
return isVar
case (*ast.IndexExpr): // like X[Y], check X
@@ -287,7 +316,7 @@ func (s *Searcher) getIdentity(expr ast.Expr) *ast.Ident {
switch typed := expr.(type) {
case *ast.SelectorExpr:
// Ignore if the parent is pointer ref (fix for #2)
- if _, ok := s.Types[typed.X].Type.(*types.Pointer); ok {
+ if _, ok := s.Pass.TypesInfo.Types[typed.X].Type.(*types.Pointer); ok {
return nil
}
diff --git a/vendor/github.com/kyoh86/exportloopref/go.mod b/vendor/github.com/kyoh86/exportloopref/go.mod
deleted file mode 100644
index 34a53987a..000000000
--- a/vendor/github.com/kyoh86/exportloopref/go.mod
+++ /dev/null
@@ -1,5 +0,0 @@
-module github.com/kyoh86/exportloopref
-
-go 1.14
-
-require golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa
diff --git a/vendor/github.com/kyoh86/exportloopref/go.sum b/vendor/github.com/kyoh86/exportloopref/go.sum
deleted file mode 100644
index 3b199f006..000000000
--- a/vendor/github.com/kyoh86/exportloopref/go.sum
+++ /dev/null
@@ -1,20 +0,0 @@
-github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-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.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
-golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-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/net v0.0.0-20200226121028-0de0cce0169b/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/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa h1:mMXQKlWCw9mIWgVLLfiycDZjMHMMYqiuakI4E/l2xcA=
-golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=