55# Needs some introductory comments.
66
77from functools import reduce , partial
8- from itertools import ifilter , izip
8+ from itertools import ifilter , ifilterfalse , izip , tee
99from logging import debug
1010from re import compile as recompile , sub as resub
1111
@@ -72,6 +72,8 @@ def walk(self, tree, memo=None):
7272 comIns (self , tree , tree .tokenStopIndex , memo )
7373 if tree .isJavaSource :
7474 comIns (self , tree , len (tree .parser .input .tokens ), memo )
75+ # fixme: we're calling the mutators far too frequently instead
76+ # of only once per object after its walk is finished.
7577 for handler in self .configHandlers ('PostWalk' , suffix = 'Mutators' ):
7678 handler (self )
7779
@@ -80,6 +82,22 @@ def zipWalk(self, nodes, visitors, memo):
8082 for node , visitor in izip (nodes , visitors ):
8183 visitor .walk (node , memo )
8284
85+ def nodeTypeToString (self , node ):
86+ """ Returns the TYPE or QUALIFIED_TYPE_IDENT of the given node. """
87+ # (TYPE primitiveType
88+ # | TYPE qualifiedTypeIdent
89+ # | TYPE qualifiedTypeIdentSimplified
90+ # ) arrayDeclaratorList?
91+ alt = self .altIdent
92+ ntype = node .firstChildOfType (tokens .TYPE )
93+ nnext = ntype .children [0 ]
94+ if nnext .type == tokens .QUALIFIED_TYPE_IDENT :
95+ names = [alt (t .text ) for t in nnext .childrenOfType (tokens .IDENT )]
96+ stype = '.' .join (names )
97+ else :
98+ stype = nnext .text
99+ return alt (stype )
100+
83101
84102class TypeAcceptor (object ):
85103 """ TypeAcceptor -> shared visitor method(s) for type declarations.
@@ -125,26 +143,77 @@ class ModifiersAcceptor(object):
125143 """
126144 def acceptModifierList (self , node , memo ):
127145 """ Accept and process class and method modifiers. """
128- # modifier lists come with class, interface, enum and
129- # annotation declarations. they also come with method and var
130- # decls; see those methods in the Class definition.
146+ isAnno = lambda token :token .type == tokens .AT
147+ for ano in ifilter (isAnno , node .children ):
148+ self .nodesToAnnos (ano , memo )
149+ for mod in ifilterfalse (isAnno , node .children ):
150+ self .nodesToModifiers (mod , node )
151+ return self
131152
132- for branch in [c for c in node .children if c .type == tokens .AT ]:
133- # TODO: walk annotation correctly
134- name = branch .firstChildOfType (tokens .IDENT ).text
153+ def nodesToAnnos (self , branch , memo ):
154+ """ Convert the annotations in the given branch to a decorator. """
155+ name = branch .firstChildOfType (tokens .IDENT ).text
156+ init = branch .firstChildOfType (tokens .ANNOTATION_INIT_BLOCK )
157+ if not init :
135158 deco = self .factory .expr (left = name , fs = '@{left}()' )
159+ else :
160+ defKey = init .firstChildOfType (tokens .ANNOTATION_INIT_DEFAULT_KEY )
161+ if defKey :
162+ deco = self .factory .expr (left = name , fs = '@{left}({right})' )
163+ deco .right = right = self .factory .expr (parent = deco )
164+ right .walk (defKey .firstChild ())
165+ else :
166+ deco = self .factory .expr (left = name , fs = '@{left}({right})' )
167+ arg = deco .right = self .factory .expr (parent = deco )
168+ keys = init .firstChildOfType (tokens .ANNOTATION_INIT_KEY_LIST )
169+ for child in keys .children :
170+ fs , expr = child .text + '={right}' , child .firstChild ()
171+ fs += (', ' if child is not keys .children [- 1 ] else '' )
172+ arg .left = self .factory .expr (fs = fs , parent = arg )
173+ arg .left .walk (expr , memo )
174+ arg .right = arg = self .factory .expr (parent = arg )
136175 self .decorators .append (deco )
137176
138- for branch in [c for c in node .children if c .type != tokens .AT ]:
139- if node .parentType in tokens .methodTypes :
140- self .modifiers .extend (n .text for n in node .children ) # wrong
141- if self .isStatic :
142- self .parameters [0 ]['name' ] = 'cls'
143- self .modifiers .append (branch .text )
177+ def nodesToModifiers (self , branch , root ):
178+ """ Convert the modifiers in the given branch to template modifiers. """
179+ if root .parentType in tokens .methodTypes :
180+ self .modifiers .extend (n .text for n in root .children )
181+ if self .isStatic and self .parameters :
182+ self .parameters [0 ]['name' ] = 'cls'
183+ self .modifiers .append (branch .text )
184+
185+
186+ class VarAcceptor (object ):
187+ def acceptVarDeclaration (self , node , memo ):
188+ """ Creates a new expression for a variable declaration. """
189+ varDecls = node .firstChildOfType (tokens .VAR_DECLARATOR_LIST )
190+ for varDecl in varDecls .childrenOfType (tokens .VAR_DECLARATOR ):
191+ ident = varDecl .firstChildOfType (tokens .IDENT )
192+ self .variables .append (ident .text )
193+ identExp = self .factory .expr (left = ident .text , parent = self )
194+ declExp = varDecl .firstChildOfType (tokens .EXPR )
195+ assgnExp = identExp .pushRight (' = ' )
196+ declArr = varDecl .firstChildOfType (tokens .ARRAY_INITIALIZER )
197+ if declExp :
198+ assgnExp .walk (declExp , memo )
199+ elif declArr :
200+ assgnExp .right = exp = self .factory .expr (fs = '[' + FS .lr + ']' , parent = identExp )
201+ children = list (declArr .childrenOfType (tokens .EXPR ))
202+ for child in children :
203+ fs = FS .lr if child is children [- 1 ] else FS .lr + ', '
204+ exp .left = self .factory .expr (fs = fs , parent = identExp )
205+ exp .left .walk (child , memo )
206+ exp .right = exp = self .factory .expr (parent = identExp )
207+ else :
208+ if node .firstChildOfType (tokens .TYPE ).firstChildOfType (tokens .ARRAY_DECLARATOR_LIST ):
209+ val = assgnExp .pushRight ('[]' )
210+ else :
211+ typ = self .nodeTypeToString (node )
212+ val = assgnExp .pushRight ('{0}()' .format (typ ))
144213 return self
145214
146215
147- class Class (TypeAcceptor , ModifiersAcceptor , Base ):
216+ class Class (VarAcceptor , TypeAcceptor , ModifiersAcceptor , Base ):
148217 """ Class -> accepts AST branches for class-level objects.
149218
150219 """
@@ -183,36 +252,6 @@ def acceptFunctionMethodDecl(self, node, memo):
183252 mods = node .firstChildOfType (tokens .MODIFIER_LIST )
184253 return self .factory .method (name = ident .text , type = type , parent = self )
185254
186- def acceptVarDeclaration (self , node , memo ):
187- """ Creates a new expression for a variable declaration. """
188- # this is strikingly similar to
189- # MethodContent.acceptVarDeclaration; merge and fix.
190- mods = node .firstChildOfType (tokens .MODIFIER_LIST )
191- decl = node .firstChildOfType (tokens .VAR_DECLARATOR_LIST )
192- for vard in decl .childrenOfType (tokens .VAR_DECLARATOR ):
193- ident = vard .firstChildOfType (tokens .IDENT )
194- self .variables .append (ident .text )
195- expr = vard .firstChildOfType (tokens .EXPR )
196- child = self .factory .expr (left = ident .text , parent = self )
197- assgn = child .pushRight (' = ' )
198- arinit = vard .firstChildOfType (tokens .ARRAY_INITIALIZER )
199- if arinit :
200- assgn .right = exp = self .factory .expr (fs = '[' + FS .lr + ']' , parent = child )
201- children = list (arinit .childrenOfType (tokens .EXPR ))
202- for c in children :
203- fs = FS .lr if c is children [- 1 ] else FS .lr + ', '
204- exp .left = self .factory .expr (fs = fs , parent = child )
205- exp .left .walk (c , memo )
206- exp .right = exp = self .factory .expr (parent = child )
207- elif expr :
208- assgn .walk (expr , memo )
209- else :
210- typ = node .firstChildOfType (tokens .TYPE )
211- typ = typ .children [0 ].text
212- val = assgn .pushRight ()
213- val .left = '{0}()' .format (typ ) # wrong
214- return self
215-
216255 def acceptVoidMethodDecl (self , node , memo ):
217256 """ Accept and process a void method declaration. """
218257 ident = node .firstChildOfType (tokens .IDENT )
@@ -341,10 +380,17 @@ def acceptDo(self, node, memo):
341380 ifStat .expr .walk (parNode , memo )
342381 breakStat = self .factory .statement ('break' , parent = ifStat )
343382
383+ goodExprParents = (
384+ tokens .BLOCK_SCOPE ,
385+ tokens .CASE ,
386+ tokens .DEFAULT ,
387+ tokens .FOR_EACH
388+ )
389+
344390 def acceptExpr (self , node , memo ):
345391 """ Creates a new expression. """
346- goodParents = ( tokens . BLOCK_SCOPE , tokens . CASE , tokens . DEFAULT , tokens . FOR_EACH )
347- if node .parentType in goodParents : # wrong
392+ # this works but isn't precise
393+ if node .parentType in self . goodExprParents :
348394 return self .factory .expr (parent = self )
349395
350396 def acceptFor (self , node , memo ):
@@ -466,45 +512,19 @@ def acceptTry(self, node, memo):
466512 finStat = self .factory .statement ('finally' , fs = FS .lc , parent = self )
467513 finStat .walk (finNode , memo )
468514
515+ goodReturnParents = (
516+ tokens .BLOCK_SCOPE ,
517+ )
518+
469519 def acceptReturn (self , node , memo ):
470520 """ Creates a new return expression. """
471- if node .parentType == tokens .BLOCK_SCOPE : # wrong
521+ # again, this works but isn't as precise as it should be
522+ if node .parentType in self .goodReturnParents :
472523 expr = self .factory .expr (left = 'return' , parent = self )
473524 if node .children :
474525 expr .fs , expr .right = FS .lsr , self .factory .expr (parent = expr )
475526 expr .right .walk (node , memo )
476527
477- def acceptVarDeclaration (self , node , memo ):
478- """ Creates a new expression for a variable declaration. """
479- varDecls = node .firstChildOfType (tokens .VAR_DECLARATOR_LIST )
480- for varDecl in varDecls .childrenOfType (tokens .VAR_DECLARATOR ):
481- ident = varDecl .firstChildOfType (tokens .IDENT )
482- self .variables .append (ident .text )
483- identExp = self .factory .expr (left = ident .text , parent = self )
484- assgnExp = identExp .pushRight (' = ' )
485- declExp = varDecl .firstChildOfType (tokens .EXPR )
486- declArr = varDecl .firstChildOfType (tokens .ARRAY_INITIALIZER )
487- if declExp :
488- assgnExp .walk (declExp , memo )
489- elif declArr :
490- assgnExp .right = exp = self .factory .expr (fs = '[' + FS .lr + ']' )
491- children = list (declArr .childrenOfType (tokens .EXPR ))
492- for child in children :
493- fs = FS .lr if child is children [- 1 ] else FS .lr + ', '
494- exp .left = self .factory .expr (fs = fs )
495- exp .left .walk (child , memo )
496- exp .right = exp = self .factory .expr ()
497- else :
498- if node .firstChildOfType (tokens .TYPE ).firstChildOfType (tokens .ARRAY_DECLARATOR_LIST ):
499- val = assgnExp .pushRight ()
500- val .left = '[]'
501- else :
502- typ = node .firstChildOfType (tokens .TYPE )
503- typ = typ .children [0 ].text
504- val = assgnExp .pushRight ()
505- val .left = '{0}()' .format (typ ) # wrong
506- return self
507-
508528 def acceptWhile (self , node , memo ):
509529 """ Accept and process a while block. """
510530 # WHILE - PARENTESIZED_EXPR - BLOCK_SCOPE
@@ -514,18 +534,14 @@ def acceptWhile(self, node, memo):
514534 whileStat .walk (blkNode , memo )
515535
516536
517- class Method (ModifiersAcceptor , MethodContent ):
537+ class Method (VarAcceptor , ModifiersAcceptor , MethodContent ):
518538 """ Method -> accepts AST branches for method-level objects.
519539
520540 """
521541 def acceptFormalParamStdDecl (self , node , memo ):
522542 """ Accept and process a single parameter declaration. """
523543 ident = node .firstChildOfType (tokens .IDENT )
524- ptype = list (node .findChildrenOfType (tokens .TYPE ))[0 ] # wrong
525- try :
526- ptype = list (ptype .findChildrenOfType (tokens .IDENT ))[0 ].text
527- except (IndexError , ):
528- ptype = ptype .firstChild ().text
544+ ptype = self .nodeTypeToString (node )
529545 self .parameters .append (self .makeParam (ident .text , ptype ))
530546 return self
531547
@@ -596,7 +612,7 @@ def acceptPreformatted(self, node, memo):
596612 return acceptPreformatted
597613
598614 acceptArrayElementAccess = makeNodePreformattedExpr (FS .l + '[' + FS .r + ']' )
599- acceptCastExpr = makeNodePreformattedExpr (FS .l + '(' + FS .r + ')' ) # wrong.
615+ acceptCastExpr = makeNodePreformattedExpr (FS .l + '(' + FS .r + ')' ) # problem?
600616 acceptDiv = makeNodePreformattedExpr (FS .l + ' / ' + FS .r )
601617 acceptLogicalAnd = makeNodePreformattedExpr (FS .l + ' and ' + FS .r )
602618 acceptLogicalNot = makeNodePreformattedExpr ('not ' + FS .l )
@@ -655,11 +671,11 @@ def acceptBitShiftRightAssign(self, node, memo):
655671
656672 def acceptClassConstructorCall (self , node , memo ):
657673 """ Accept and process a class constructor call. """
658- self .acceptMethodCall (node , memo ) # probably wrong
674+ self .acceptMethodCall (node , memo )
659675 typeIdent = node .firstChildOfType (tokens .QUALIFIED_TYPE_IDENT )
660676 if typeIdent and typeIdent .children :
661- ids = [self .altIdent (child .text ) for child in typeIdent .children ]
662- self .left = '.' .join (ids ) # wrong
677+ names = [self .altIdent (child .text ) for child in typeIdent .children ]
678+ self .left = '.' .join (names )
663679
664680 def acceptDot (self , node , memo ):
665681 """ Accept and process a dotted expression. """
@@ -674,7 +690,7 @@ def acceptExpr(self, node, memo):
674690
675691 def acceptIdent (self , node , memo ):
676692 """ Accept and process an ident expression. """
677- self .left = name = self .altIdent (node .text )
693+ self .left = self .altIdent (node .text )
678694
679695 def acceptInstanceof (self , node , memo ):
680696 """ Accept and process an instanceof expression. """
0 commit comments