diff options
author | Teddy Wing | 2023-05-18 03:35:49 +0200 |
---|---|---|
committer | Teddy Wing | 2023-05-18 03:35:49 +0200 |
commit | f0aece52e7d41c404f5a3dbcbe174b43351cb25f (patch) | |
tree | 0f7a4bfba203a3a2170b814ec79512af707f9287 | |
parent | a54ba9c28ebbde6419e53d265aed2102e46bac9b (diff) | |
download | gocapturedrefrace-f0aece52e7d41c404f5a3dbcbe174b43351cb25f.tar.bz2 |
Find variable declarations in function closure
Treat these as shadowed variables and ignore them.
-rw-r--r-- | gocapturedrefrace.go | 74 |
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 } |