aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeddy Wing2023-05-18 03:35:49 +0200
committerTeddy Wing2023-05-18 03:35:49 +0200
commitf0aece52e7d41c404f5a3dbcbe174b43351cb25f (patch)
tree0f7a4bfba203a3a2170b814ec79512af707f9287
parenta54ba9c28ebbde6419e53d265aed2102e46bac9b (diff)
downloadgocapturedrefrace-f0aece52e7d41c404f5a3dbcbe174b43351cb25f.tar.bz2
Find variable declarations in function closure
Treat these as shadowed variables and ignore them.
-rw-r--r--gocapturedrefrace.go74
1 files changed, 53 insertions, 21 deletions
diff --git a/gocapturedrefrace.go b/gocapturedrefrace.go
index fd2cc94..cab0b4f 100644
--- a/gocapturedrefrace.go
+++ b/gocapturedrefrace.go
@@ -86,7 +86,7 @@ func checkClosure(pass *analysis.Pass, funcLit *ast.FuncLit) {
// Build a list of assignments local to funcLit. These will be ignored as
// shadowed variables.
- localAssignments := findLocalAssignments(pass, funcLit)
+ localAssignments := findLocalVarDeclarations(pass, funcLit)
ast.Inspect(
funcLit,
@@ -143,41 +143,73 @@ func checkClosure(pass *analysis.Pass, funcLit *ast.FuncLit) {
)
}
-// findLocalAssignments returns a list of all variable definitions in funcLit.
-func findLocalAssignments(
+// findLocalVarDeclarations returns a list of all variable declarations in
+// funcLit.
+func findLocalVarDeclarations(
pass *analysis.Pass,
funcLit *ast.FuncLit,
-) (localAssignments []*ast.Ident) {
- localAssignments = []*ast.Ident{}
+) (declarations []*ast.Ident) {
+ declarations = []*ast.Ident{}
ast.Inspect(
funcLit,
func(node ast.Node) bool {
- assignStmt, ok := node.(*ast.AssignStmt)
- if !ok {
- return true
- }
-
- if assignStmt.Tok != token.DEFINE {
- return true
- }
-
- for _, lhs := range assignStmt.Lhs {
- ident, ok := lhs.(*ast.Ident)
- if !ok {
+ switch node := node.(type) {
+ case *ast.AssignStmt:
+ // assignStmt, ok := node.(*ast.AssignStmt)
+ // if !ok {
+ // return true
+ // }
+ assignStmt := node
+
+ if assignStmt.Tok != token.DEFINE {
return true
}
- if ident == nil {
- return true
+ for _, lhs := range assignStmt.Lhs {
+ ident, ok := lhs.(*ast.Ident)
+ if !ok {
+ return true
+ }
+
+ if ident == nil {
+ return true
+ }
+
+ declarations = append(declarations, ident)
}
- localAssignments = append(localAssignments, ident)
+ case *ast.GenDecl:
+ decl := varDeclaration(node)
+ if decl != nil {
+ declarations = append(declarations, decl)
+ }
}
return true
},
)
- return localAssignments
+ return declarations
+}
+
+// varDeclaration returns the identifier corresponding to variable declarations
+// in decl, or nil if decl is not a variable declaration.
+func varDeclaration(decl *ast.GenDecl) *ast.Ident {
+ if decl.Tok != token.VAR {
+ return nil
+ }
+
+ for _, spec := range decl.Specs {
+ valueSpec, ok := spec.(*ast.ValueSpec)
+ if !ok {
+ return nil
+ }
+
+ for _, ident := range valueSpec.Names {
+ return ident
+ }
+ }
+
+ return nil
}