From: david-sarah Date: Sun, 9 Oct 2011 04:48:00 +0000 (+0000) Subject: check-miscaptures.py: Python doesn't really have declarations; report the topmost... X-Git-Url: https://git.rkrishnan.org/components/%22news.html/module-simplejson.scanner.html?a=commitdiff_plain;h=5359c24e9901c588770d05227c4c563ed5cbc29a;p=tahoe-lafs%2Ftahoe-lafs.git check-miscaptures.py: Python doesn't really have declarations; report the topmost assignment. refs #1555 --- diff --git a/misc/coding_tools/check-miscaptures.py b/misc/coding_tools/check-miscaptures.py index c1ced6c3..b6c9f71e 100644 --- a/misc/coding_tools/check-miscaptures.py +++ b/misc/coding_tools/check-miscaptures.py @@ -41,21 +41,22 @@ def check_loop(ast, results): # ), and that case they are not nested in the AST. But these # warts (nonobviously) happen not to matter for our analysis. - declared = {} # maps name to lineno of declaration + assigned = {} # maps name to lineno of topmost assignment nested = set() - collect_declared_and_nested(ast, declared, nested) + collect_assigned_and_nested(ast, assigned, nested) # For each nested function... for funcnode in nested: # Check for captured variables in this function. captured = set() - collect_captured(funcnode, declared, captured) + collect_captured(funcnode, assigned, captured) for name in captured: # We want to report the outermost capturing function # (since that is where the workaround will need to be - # added), and the variable declaration. Just one report - # per capturing function per variable will do. - results.append(make_result(funcnode, name, declared[name])) + # added), and the topmost assignment to the variable. + # Just one report per capturing function per variable + # will do. + results.append(make_result(funcnode, name, assigned[name])) # Check each node in the function body in case it # contains another 'for' loop. @@ -63,14 +64,15 @@ def check_loop(ast, results): for child in childnodes: check_ast(funcnode, results) -def collect_declared_and_nested(ast, declared, nested): +def collect_assigned_and_nested(ast, assigned, nested): """ - Collect the names declared in this 'for' loop, not including - names declared in nested functions. Also collect the nodes of - functions that are nested one level deep. + Collect the names assigned in this loop, not including names + assigned in nested functions. Also collect the nodes of functions + that are nested one level deep. """ if isinstance(ast, AssName): - declared[ast.name] = ast.lineno + if ast.name not in assigned or assigned[ast.name] > ast.lineno: + assigned[ast.name] = ast.lineno else: childnodes = ast.getChildNodes() if isinstance(ast, (Lambda, Function)): @@ -83,24 +85,23 @@ def collect_declared_and_nested(ast, declared, nested): for child in childnodes: if isinstance(ast, Node): - collect_declared_and_nested(child, declared, nested) + collect_assigned_and_nested(child, assigned, nested) -def collect_captured(ast, declared, captured): - """Collect any captured variables that are also in declared.""" +def collect_captured(ast, assigned, captured): + """Collect any captured variables that are also in assigned.""" if isinstance(ast, Name): - if ast.name in declared: + if ast.name in assigned: captured.add(ast.name) else: childnodes = ast.getChildNodes() - if isinstance(ast, (Lambda, Function)): # Formal parameters of the function are excluded from # captures we care about in subnodes of the function body. - new_declared = declared.copy() - remove_argnames(ast.argnames, new_declared) + new_assigned = assigned.copy() + remove_argnames(ast.argnames, new_assigned) for child in childnodes[len(ast.defaults):]: - collect_captured(child, declared, captured) + collect_captured(child, assigned, captured) # The default argument expressions are "outside" the # function, even though they are children of the @@ -109,7 +110,7 @@ def collect_captured(ast, declared, captured): for child in childnodes: if isinstance(ast, Node): - collect_captured(child, declared, captured) + collect_captured(child, assigned, captured) def remove_argnames(names, fromset): @@ -132,7 +133,7 @@ def report(out, path, results): if isinstance(r, SyntaxError): print >>out, path + (" NOT ANALYSED due to syntax error: %s" % r) else: - print >>out, path + (":%r %s captures %r declared at line %d" % r) + print >>out, path + (":%r %s captures %r assigned at line %d" % r) def check(sources, out): class Counts: