aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeddy Wing2023-05-18 02:02:25 +0200
committerTeddy Wing2023-05-18 02:02:50 +0200
commit9c66c7865010cec45e7d49019aa344d0774ec7e8 (patch)
tree99474d0bceb2e2eabd1a1aa1a36599e75ef62e88
parentd75790724acc77890acdbe4e1894e287e4db9b46 (diff)
downloadgocapturedrefrace-9c66c7865010cec45e7d49019aa344d0774ec7e8.tar.bz2
Ignore shadowed variables
In order to ignore shadowed variables, we first build a list of all local assignments in the closure, and ignore any ident in that list.
-rw-r--r--gocapturedrefrace.go89
1 files changed, 52 insertions, 37 deletions
diff --git a/gocapturedrefrace.go b/gocapturedrefrace.go
index cdc6486..3f776e0 100644
--- a/gocapturedrefrace.go
+++ b/gocapturedrefrace.go
@@ -85,13 +85,12 @@ func checkClosure(pass *analysis.Pass, funcLit *ast.FuncLit) {
// Get the closure's scope.
funcScope := pass.TypesInfo.Scopes[funcLit.Type]
+ localAssignments := checkShadowing(pass, funcLit)
+ fmt.Printf("localAssignments: %#v\n", localAssignments)
+
ast.Inspect(
funcLit,
func(node ast.Node) bool {
- if isShadowingDeclaration(pass, node, funcScope) {
- return true
- }
-
ident, ok := node.(*ast.Ident)
if !ok {
return true
@@ -101,6 +100,13 @@ func checkClosure(pass *analysis.Pass, funcLit *ast.FuncLit) {
return true
}
+ // Ignore shadowed variables.
+ for _, localAssignmentIdent := range localAssignments {
+ if ident == localAssignmentIdent {
+ return true
+ }
+ }
+
// Find out whether `ident` was defined in an outer scope.
scope, scopeObj := funcScope.LookupParent(ident.Name, ident.NamePos)
@@ -140,43 +146,52 @@ func checkClosure(pass *analysis.Pass, funcLit *ast.FuncLit) {
}
// TODO: doc
-func isShadowingDeclaration(
+func checkShadowing(
pass *analysis.Pass,
- node ast.Node,
- funcScope *types.Scope,
-) bool {
+ funcLit *ast.FuncLit,
+ // funcScope *types.Scope,
+) (localAssignments []*ast.Ident) {
// TODO: Plan: Change this function to checkShadowing. Call ast.Inspect and build a list of local assignments in the closure. Then in checkClosure, ignore objects in the local assignments list.
- assignStmt, ok := node.(*ast.AssignStmt)
- if !ok {
- return false
- }
+ localAssignments = []*ast.Ident{}
- if assignStmt.Tok != token.DEFINE {
- return false
- }
+ ast.Inspect(
+ funcLit,
+ func(node ast.Node) bool {
+ assignStmt, ok := node.(*ast.AssignStmt)
+ if !ok {
+ return true
+ }
- for _, lhs := range assignStmt.Lhs {
- ident, ok := lhs.(*ast.Ident)
- if !ok {
- return false
- }
- fmt.Printf("assignStmt: %#v\n", ident)
-
- if ident == nil {
- return false
- }
-
- return true
-
- // TODO: If ident is in parent, ignore it an move on.
- // scope, scopeObj := funcScope.LookupParent(ident.Name, ident.NamePos)
- //
- // // Identifier is local to the closure.
- // if scope == nil && scopeObj == nil {
- // return
- // }
- }
+ if assignStmt.Tok != token.DEFINE {
+ return true
+ }
+
+ for _, lhs := range assignStmt.Lhs {
+ ident, ok := lhs.(*ast.Ident)
+ if !ok {
+ return true
+ }
+ fmt.Printf("assignStmt: %#v\n", ident)
+
+ if ident == nil {
+ return true
+ }
+
+ localAssignments = append(localAssignments, ident)
+
+ // TODO: If ident is in parent, ignore it an move on.
+ // scope, scopeObj := funcScope.LookupParent(ident.Name, ident.NamePos)
+ //
+ // // Identifier is local to the closure.
+ // if scope == nil && scopeObj == nil {
+ // return
+ // }
+ }
+
+ return true
+ },
+ )
- return false
+ return localAssignments
}