From d2f3ef9714f4db2d0ec56cb7e4066cc369aa6332 Mon Sep 17 00:00:00 2001
From: david-sarah <david-sarah@jacaranda.org>
Date: Sun, 9 Oct 2011 04:40:22 +0000
Subject: [PATCH] check-miscaptures.py: check while loops and list
 comprehensions as well as for loops. Also fix a pyflakes warning. refs #1555

---
 misc/coding_tools/check-miscaptures.py | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/misc/coding_tools/check-miscaptures.py b/misc/coding_tools/check-miscaptures.py
index f7950a92..2e827fb9 100644
--- a/misc/coding_tools/check-miscaptures.py
+++ b/misc/coding_tools/check-miscaptures.py
@@ -1,7 +1,7 @@
 #! /usr/bin/python
 
-import os, sys, compiler, traceback
-from compiler.ast import Node, For, AssName, Name, Lambda, Function
+import os, sys, compiler
+from compiler.ast import Node, For, While, ListComp, AssName, Name, Lambda, Function
 
 
 def check_source(source):
@@ -21,16 +21,25 @@ def check_thing(parser, thing):
         return results
 
 def check_ast(ast, results):
-    """Check a node outside a 'for' loop."""
-    if isinstance(ast, For):
-        check_for(ast, results)
+    """Check a node outside a loop."""
+    if isinstance(ast, (For, While, ListComp)):
+        check_loop(ast, results)
     else:
         for child in ast.getChildNodes():
             if isinstance(ast, Node):
                 check_ast(child, results)
 
-def check_for(ast, results):
-    """Check a particular outer 'for' loop."""
+def check_loop(ast, results):
+    """Check a particular outer loop."""
+
+    # List comprehensions have a poorly designed AST of the form
+    # ListComp(exprNode, [ListCompFor(...), ...]), in which the
+    # result expression is outside the ListCompFor node even though
+    # it is logically inside the loop(s).
+    # There may be multiple ListCompFor nodes (in cases such as
+    #   [lambda: (a,b) for a in ... for b in ...]
+    # ), 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
     nested = set()
-- 
2.45.2