diff options
author | Teddy Wing | 2023-05-18 02:02:25 +0200 |
---|---|---|
committer | Teddy Wing | 2023-05-18 02:02:50 +0200 |
commit | 9c66c7865010cec45e7d49019aa344d0774ec7e8 (patch) | |
tree | 99474d0bceb2e2eabd1a1aa1a36599e75ef62e88 | |
parent | d75790724acc77890acdbe4e1894e287e4db9b46 (diff) | |
download | gocapturedrefrace-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.go | 89 |
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 } |