From 9c66c7865010cec45e7d49019aa344d0774ec7e8 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Thu, 18 May 2023 02:02:25 +0200 Subject: 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. --- gocapturedrefrace.go | 89 ++++++++++++++++++++++++++++++---------------------- 1 file 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 } -- cgit v1.2.3