Minimize
Table
Bug Overview
line | bug priority | bug | bug description | existing since | author |
---|
1420 | medium | IL_INFINITE_LOOP | Diese Schleife terminiert nicht. Bitte Code überprüfen! Falls dies beabsichtigt ist und der Fehler soll ignoriert werden, dann //NOBUG verwenden. | 18.06.2012-10:31 | Unbekannt |
2541 | medium | IL_INFINITE_LOOP | Diese Schleife terminiert nicht. Bitte Code überprüfen! Falls dies beabsichtigt ist und der Fehler soll ignoriert werden, dann //NOBUG verwenden. | 18.06.2012-10:31 | Unbekannt |
117 | medium | TODO | Der Code ist an dieser Stelle eventuell unfertig oder fehlerhaft. Bitte überprüfen! | 18.06.2012-10:31 | Unbekannt |
180 | medium | SystemPrintln | Bitte keine System.(out|err).print-Ausgaben verwenden, stattdessen Logger-Klassen nutzen. Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
193 | medium | SystemPrintln | Bitte keine System.(out|err).print-Ausgaben verwenden, stattdessen Logger-Klassen nutzen. Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
205 | medium | SystemPrintln | Bitte keine System.(out|err).print-Ausgaben verwenden, stattdessen Logger-Klassen nutzen. Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
220 | medium | SystemPrintln | Bitte keine System.(out|err).print-Ausgaben verwenden, stattdessen Logger-Klassen nutzen. Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
228 | high | OBL_UNSATISFIED_OBLIGATION | Öffnet eine Methode einen Stream oder eine andere Ressource muss diese mit einem try/finally-Block geschlossen werden. Bitte Code auf eine entsprechende cleanup-Operation hin überprüfen! Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
229 | medium | SystemPrintln | Bitte keine System.(out|err).print-Ausgaben verwenden, stattdessen Logger-Klassen nutzen. Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
232 | medium | SystemPrintln | Bitte keine System.(out|err).print-Ausgaben verwenden, stattdessen Logger-Klassen nutzen. Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
323 | medium | TODO | Der Code ist an dieser Stelle eventuell unfertig oder fehlerhaft. Bitte überprüfen! | 18.06.2012-10:31 | Unbekannt |
565 | medium | TODO | Der Code ist an dieser Stelle eventuell unfertig oder fehlerhaft. Bitte überprüfen! | 18.06.2012-10:31 | Unbekannt |
1626 | medium | TODO | Der Code ist an dieser Stelle eventuell unfertig oder fehlerhaft. Bitte überprüfen! | 18.06.2012-10:31 | Unbekannt |
1669 | medium | ExcessiveMethodLength | Diese Methode ist sehr lang, ein Indiz dafür das diese Methode zu viel tut, es sollten Hilfsmethoden genutzt und Copy/Paste-Code entfernt werden. Falls dies beabsichtigt ist und der Fehler soll ignoriert werden, dann //NOBUG verwenden. Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
2050 | medium | TODO | Der Code ist an dieser Stelle eventuell unfertig oder fehlerhaft. Bitte überprüfen! | 18.06.2012-10:31 | Unbekannt |
2260 | medium | EmptyIfStmt | Leeres if-Statement, bei Erfüllung der Bedingung wird keine Anweisung ausgeführt, dieser Code kann entfernt werden. Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
2441 | medium | FIXME | Der Code ist an dieser Stelle eventuell unfertig oder fehlerhaft. Bitte überprüfen! | 18.06.2012-10:31 | Unbekannt |
2539 | medium | FIXME | Der Code ist an dieser Stelle eventuell unfertig oder fehlerhaft. Bitte überprüfen! | 18.06.2012-10:31 | Unbekannt |
2766 | medium | TODO | Der Code ist an dieser Stelle eventuell unfertig oder fehlerhaft. Bitte überprüfen! | 18.06.2012-10:31 | Unbekannt |
2767 | medium | TODO | Der Code ist an dieser Stelle eventuell unfertig oder fehlerhaft. Bitte überprüfen! | 18.06.2012-10:31 | Unbekannt |
2848 | medium | WhileLoopsMustUseBraces | Es wird ein while-Statement ohne geschweifte Klammern verwendet, dies führt bei Erweiterungen oft zu Fehlern. Bitte Klammern setzen! Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
3031 | medium | TODO | Der Code ist an dieser Stelle eventuell unfertig oder fehlerhaft. Bitte überprüfen! | 18.06.2012-10:31 | Unbekannt |
3091 | medium | SystemPrintln | Bitte keine System.(out|err).print-Ausgaben verwenden, stattdessen Logger-Klassen nutzen. Details zum Fehler... | 18.06.2012-10:31 | Unbekannt |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codehaus.groovy.antlr;
17
18 import antlr.RecognitionException;
19 import antlr.TokenStreamException;
20 import antlr.TokenStreamRecognitionException;
21 import antlr.collections.AST;
22 import com.thoughtworks.xstream.XStream;
23 import org.codehaus.groovy.GroovyBugError;
24 import org.codehaus.groovy.antlr.parser.GroovyLexer;
25 import org.codehaus.groovy.antlr.parser.GroovyRecognizer;
26 import org.codehaus.groovy.antlr.parser.GroovyTokenTypes;
27 import org.codehaus.groovy.antlr.treewalker.*;
28 import org.codehaus.groovy.ast.*;
29 import org.codehaus.groovy.ast.expr.*;
30 import org.codehaus.groovy.ast.stmt.*;
31 import org.codehaus.groovy.control.CompilationFailedException;
32 import org.codehaus.groovy.control.ParserPlugin;
33 import org.codehaus.groovy.control.SourceUnit;
34 import org.codehaus.groovy.syntax.*;
35 import org.objectweb.asm.Opcodes;
36
37 import java.io.FileNotFoundException;
38 import java.io.FileOutputStream;
39 import java.io.FileWriter;
40 import java.io.PrintStream;
41 import java.io.Reader;
42 import java.security.AccessController;
43 import java.security.PrivilegedAction;
44 import java.util.ArrayList;
45 import java.util.HashSet;
46 import java.util.Iterator;
47 import java.util.LinkedList;
48 import java.util.List;
49 import java.util.Set;
50
51
52
53
54
55
56 public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, GroovyTokenTypes {
57
58 private static class AnonymousInnerClassCarrier extends Expression {
59 ClassNode innerClass;
60
61 public Expression transformExpression(ExpressionTransformer transformer) {
62 return null;
63 }
64
65 @Override
66 public void setSourcePosition(final ASTNode node) {
67 super.setSourcePosition(node);
68 innerClass.setSourcePosition(node);
69 }
70
71 @Override
72 public void setColumnNumber(final int columnNumber) {
73 super.setColumnNumber(columnNumber);
74 innerClass.setColumnNumber(columnNumber);
75 }
76
77 @Override
78 public void setLineNumber(final int lineNumber) {
79 super.setLineNumber(lineNumber);
80 innerClass.setLineNumber(lineNumber);
81 }
82
83 @Override
84 public void setLastColumnNumber(final int columnNumber) {
85 super.setLastColumnNumber(columnNumber);
86 innerClass.setLastColumnNumber(columnNumber);
87 }
88
89 @Override
90 public void setLastLineNumber(final int lineNumber) {
91 super.setLastLineNumber(lineNumber);
92 innerClass.setLastLineNumber(lineNumber);
93 }
94 }
95
96 protected AST ast;
97 private ClassNode classNode;
98 private String[] tokenNames;
99 private int innerClassCounter = 1;
100 private boolean enumConstantBeingDef = false;
101 private boolean forStatementBeingDef = false;
102 private boolean firstParamIsVarArg = false;
103 private boolean firstParam = false;
104
105 public
106 final SourceBuffer sourceBuffer = new SourceBuffer();
107 transformCSTIntoAST(sourceUnit, reader, sourceBuffer);
108 processAST();
109 return outputAST(sourceUnit, sourceBuffer);
110 }
111
112 protected void transformCSTIntoAST(SourceUnit sourceUnit, Reader reader, SourceBuffer sourceBuffer) throws CompilationFailedException {
113 ast = null;
114
115 setController(sourceUnit);
116
117
118
119 UnicodeEscapingReader unicodeReader = new UnicodeEscapingReader(reader, sourceBuffer);
120 UnicodeLexerSharedInputState inputState = new UnicodeLexerSharedInputState(unicodeReader);
121 GroovyLexer lexer = new GroovyLexer(inputState);
122 unicodeReader.setLexer(lexer);
123 GroovyRecognizer parser = GroovyRecognizer.make(lexer);
124 parser.setSourceBuffer(sourceBuffer);
125 tokenNames = parser.getTokenNames();
126 parser.setFilename(sourceUnit.getName());
127
128
129 try {
130 parser.compilationUnit();
131 }
132 catch (TokenStreamRecognitionException tsre) {
133 RecognitionException e = tsre.recog;
134 SyntaxException se = new SyntaxException(e.getMessage(), e, e.getLine(), e.getColumn());
135 se.setFatal(true);
136 sourceUnit.addError(se);
137 }
138 catch (RecognitionException e) {
139 SyntaxException se = new SyntaxException(e.getMessage(), e, e.getLine(), e.getColumn());
140 se.setFatal(true);
141 sourceUnit.addError(se);
142 }
143 catch (TokenStreamException e) {
144 sourceUnit.addException(e);
145 }
146
147 ast = parser.getAST();
148 }
149
150 protected void processAST() {
151 AntlrASTProcessor snippets = new AntlrASTProcessSnippets();
152 ast = snippets.process(ast);
153 }
154
155 public Reduction outputAST(final SourceUnit sourceUnit, final SourceBuffer sourceBuffer) {
156 AccessController.doPrivileged(new PrivilegedAction() {
157 public Object run() {
158 outputASTInVariousFormsIfNeeded(sourceUnit, sourceBuffer);
159 return null;
160 }
161 });
162
163 return null;
164 }
165
166 private void outputASTInVariousFormsIfNeeded(SourceUnit sourceUnit, SourceBuffer sourceBuffer) {
167
168 if ("xml".equals(System.getProperty("antlr.ast"))) {
169 saveAsXML(sourceUnit.getName(), ast);
170 }
171
172
173 if ("groovy".equals(System.getProperty("antlr.ast"))) {
174 try {
175 PrintStream out = new PrintStream(new FileOutputStream(sourceUnit.getName() + ".pretty.groovy"));
176 Visitor visitor = new SourcePrinter(out, tokenNames);
177 AntlrASTProcessor treewalker = new SourceCodeTraversal(visitor);
178 treewalker.process(ast);
179 } catch (FileNotFoundException e) {
SystemPrintln
181 }
182 }
183
184
185
186 if ("mindmap".equals(System.getProperty("antlr.ast"))) {
187 try {
188 PrintStream out = new PrintStream(new FileOutputStream(sourceUnit.getName() + ".mm"));
189 Visitor visitor = new MindMapPrinter(out, tokenNames);
190 AntlrASTProcessor treewalker = new PreOrderTraversal(visitor);
191 treewalker.process(ast);
192 } catch (FileNotFoundException e) {
SystemPrintln
194 }
195 }
196
197
198 if ("extendedMindmap".equals(System.getProperty("antlr.ast"))) {
199 try {
200 PrintStream out = new PrintStream(new FileOutputStream(sourceUnit.getName() + ".mm"));
201 Visitor visitor = new MindMapPrinter(out, tokenNames, sourceBuffer);
202 AntlrASTProcessor treewalker = new PreOrderTraversal(visitor);
203 treewalker.process(ast);
204 } catch (FileNotFoundException e) {
SystemPrintln
206 }
207 }
208
209
210 if ("html".equals(System.getProperty("antlr.ast"))) {
211 try {
212 PrintStream out = new PrintStream(new FileOutputStream(sourceUnit.getName() + ".html"));
213 List<VisitorAdapter> v = new ArrayList<VisitorAdapter>();
214 v.add(new NodeAsHTMLPrinter(out, tokenNames));
215 v.add(new SourcePrinter(out, tokenNames));
216 Visitor visitors = new CompositeVisitor(v);
217 AntlrASTProcessor treewalker = new SourceCodeTraversal(visitors);
218 treewalker.process(ast);
219 } catch (FileNotFoundException e) {
SystemPrintln
221 }
222 }
223 }
224
225 private void saveAsXML(String name, AST ast) {
226 XStream xstream = new XStream();
227 try {
OBL_UNSATISFIED_OBLIGATION
SystemPrintln
230 }
231 catch (Exception e) {
SystemPrintln
233 e.printStackTrace();
234 }
235 }
236
237 public ModuleNode buildAST(SourceUnit sourceUnit, ClassLoader classLoader, Reduction cst) throws ParserException {
238 setClassLoader(classLoader);
239 makeModule();
240 try {
241 convertGroovy(ast);
242 if (output.getStatementBlock().isEmpty() && output.getMethods().isEmpty() && output.getClasses().isEmpty()) {
243 output.addStatement(ReturnStatement.RETURN_NULL_OR_VOID);
244 }
245
246
247
248 ClassNode scriptClassNode = output.getScriptClassDummy();
249 if (scriptClassNode != null) {
250 List<Statement> statements = output.getStatementBlock().getStatements();
251 if (statements.size() > 0) {
252 Statement firstStatement = statements.get(0);
253 Statement lastStatement = statements.get(statements.size() - 1);
254
255 scriptClassNode.setSourcePosition(firstStatement);
256 scriptClassNode.setLastColumnNumber(lastStatement.getLastColumnNumber());
257 scriptClassNode.setLastLineNumber(lastStatement.getLastLineNumber());
258 }
259 }
260 }
261 catch (ASTRuntimeException e) {
262 throw new ASTParserException(e.getMessage() + ". File: " + sourceUnit.getName(), e);
263 }
264 return output;
265 }
266
267
268
269
270 protected void convertGroovy(AST node) {
271 while (node != null) {
272 int type = node.getType();
273 switch (type) {
274 case PACKAGE_DEF:
275 packageDef(node);
276 break;
277
278 case STATIC_IMPORT:
279 case IMPORT:
280 importDef(node);
281 break;
282
283 case CLASS_DEF:
284 classDef(node);
285 break;
286
287 case INTERFACE_DEF:
288 interfaceDef(node);
289 break;
290
291 case METHOD_DEF:
292 methodDef(node);
293 break;
294
295 case ENUM_DEF:
296 enumDef(node);
297 break;
298
299 case ANNOTATION_DEF:
300 annotationDef(node);
301 break;
302
303 default: {
304 Statement statement = statement(node);
305 output.addStatement(statement);
306 }
307 }
308 node = node.getNextSibling();
309 }
310 }
311
312
313
314
315 protected void packageDef(AST packageDef) {
316 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
317 AST node = packageDef.getFirstChild();
318 if (isType(ANNOTATIONS, node)) {
319 processAnnotations(annotations, node);
320 node = node.getNextSibling();
321 }
322 String name = qualifiedName(node);
323
324 PackageNode packageNode = setPackage(name, annotations);
325 configureAST(packageNode, packageDef);
326 }
327
328 protected void importDef(AST importNode) {
329 boolean isStatic = importNode.getType() == STATIC_IMPORT;
330 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
331
332 AST node = importNode.getFirstChild();
333 if (isType(ANNOTATIONS, node)) {
334 processAnnotations(annotations, node);
335 node = node.getNextSibling();
336 }
337
338 String alias = null;
339 if (isType(LITERAL_as, node)) {
340
341 node = node.getFirstChild();
342 AST aliasNode = node.getNextSibling();
343 alias = identifier(aliasNode);
344 }
345
346 if (node.getNumberOfChildren() == 0) {
347 String name = identifier(node);
348
349 ClassNode type = ClassHelper.make(name);
350 configureAST(type, importNode);
351 addImport(type, name, alias, annotations);
352 return;
353 }
354
355 AST packageNode = node.getFirstChild();
356 String packageName = qualifiedName(packageNode);
357 AST nameNode = packageNode.getNextSibling();
358 if (isType(STAR, nameNode)) {
359 if (isStatic) {
360
361
362 ClassNode type = ClassHelper.make(packageName);
363 configureAST(type, importNode);
364 addStaticStarImport(type, packageName, annotations);
365 } else {
366
367 addStarImport(packageName, annotations);
368 }
369
370 if (alias != null) throw new GroovyBugError(
371 "imports like 'import foo.* as Bar' are not " +
372 "supported and should be caught by the grammar");
373 } else {
374 String name = identifier(nameNode);
375 if (isStatic) {
376
377
378 ClassNode type = ClassHelper.make(packageName);
379 configureAST(type, importNode);
380 addStaticImport(type, name, alias, annotations);
381 } else {
382
383 ClassNode type = ClassHelper.make(packageName + "." + name);
384 configureAST(type, importNode);
385 addImport(type, name, alias, annotations);
386 }
387 }
388 }
389
390 private void processAnnotations(List<AnnotationNode> annotations, AST node) {
391 AST child = node.getFirstChild();
392 while (child != null) {
393 if (isType(ANNOTATION, child))
394 annotations.add(annotation(child));
395 child = child.getNextSibling();
396 }
397 }
398
399 protected void annotationDef(AST classDef) {
400 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
401 AST node = classDef.getFirstChild();
402 int modifiers = Opcodes.ACC_PUBLIC;
403 if (isType(MODIFIERS, node)) {
404 modifiers = modifiers(node, annotations, modifiers);
405 checkNoInvalidModifier(classDef, "Annotation Definition", modifiers, Opcodes.ACC_SYNCHRONIZED, "synchronized");
406 node = node.getNextSibling();
407 }
408 modifiers |= Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION;
409
410 String name = identifier(node);
411 node = node.getNextSibling();
412 ClassNode superClass = ClassHelper.OBJECT_TYPE;
413
414 GenericsType[] genericsType = null;
415 if (isType(TYPE_PARAMETERS, node)) {
416 genericsType = makeGenericsType(node);
417 node = node.getNextSibling();
418 }
419
420 ClassNode[] interfaces = ClassNode.EMPTY_ARRAY;
421 if (isType(EXTENDS_CLAUSE, node)) {
422 interfaces = interfaces(node);
423 node = node.getNextSibling();
424 }
425
426 boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0);
427 modifiers &= ~Opcodes.ACC_SYNTHETIC;
428 classNode = new ClassNode(dot(getPackageName(), name), modifiers, superClass, interfaces, null);
429 classNode.setSyntheticPublic(syntheticPublic);
430 classNode.addAnnotations(annotations);
431 classNode.setGenericsTypes(genericsType);
432 classNode.addInterface(ClassHelper.Annotation_TYPE);
433 configureAST(classNode, classDef);
434
435 assertNodeType(OBJBLOCK, node);
436 objectBlock(node);
437 output.addClass(classNode);
438 classNode = null;
439 }
440
441 protected void interfaceDef(AST classDef) {
442 int oldInnerClassCounter = innerClassCounter;
443 innerInterfaceDef(classDef);
444 classNode = null;
445 innerClassCounter = oldInnerClassCounter;
446 }
447
448 protected void innerInterfaceDef(AST classDef) {
449 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
450 AST node = classDef.getFirstChild();
451 int modifiers = Opcodes.ACC_PUBLIC;
452 if (isType(MODIFIERS, node)) {
453 modifiers = modifiers(node, annotations, modifiers);
454 checkNoInvalidModifier(classDef, "Interface", modifiers, Opcodes.ACC_SYNCHRONIZED, "synchronized");
455 node = node.getNextSibling();
456 }
457 modifiers |= Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE;
458
459 String name = identifier(node);
460 node = node.getNextSibling();
461 ClassNode superClass = ClassHelper.OBJECT_TYPE;
462
463 GenericsType[] genericsType = null;
464 if (isType(TYPE_PARAMETERS, node)) {
465 genericsType = makeGenericsType(node);
466 node = node.getNextSibling();
467 }
468
469 ClassNode[] interfaces = ClassNode.EMPTY_ARRAY;
470 if (isType(EXTENDS_CLAUSE, node)) {
471 interfaces = interfaces(node);
472 node = node.getNextSibling();
473 }
474
475 ClassNode outerClass = classNode;
476 boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0);
477 modifiers &= ~Opcodes.ACC_SYNTHETIC;
478 if (classNode != null) {
479 name = classNode.getNameWithoutPackage() + "$" + name;
480 String fullName = dot(classNode.getPackageName(), name);
481 classNode = new InnerClassNode(classNode, fullName, modifiers, superClass, interfaces, null);
482 } else {
483 classNode = new ClassNode(dot(getPackageName(), name), modifiers, superClass, interfaces, null);
484 }
485 classNode.setSyntheticPublic(syntheticPublic);
486 classNode.addAnnotations(annotations);
487 classNode.setGenericsTypes(genericsType);
488 configureAST(classNode, classDef);
489
490 int oldClassCount = innerClassCounter;
491
492 assertNodeType(OBJBLOCK, node);
493 objectBlock(node);
494 output.addClass(classNode);
495
496 classNode = outerClass;
497 innerClassCounter = oldClassCount;
498 }
499
500 protected void classDef(AST classDef) {
501 int oldInnerClassCounter = innerClassCounter;
502 innerClassDef(classDef);
503 classNode = null;
504 innerClassCounter = oldInnerClassCounter;
505 }
506
507 private ClassNode getClassOrScript(ClassNode node) {
508 if (node != null) return node;
509 return output.getScriptClassDummy();
510 }
511
512 protected Expression anonymousInnerClassDef(AST node) {
513 ClassNode oldNode = classNode;
514 ClassNode outerClass = getClassOrScript(oldNode);
515 String fullName = outerClass.getName() + '$' + innerClassCounter;
516 innerClassCounter++;
517 if (enumConstantBeingDef) {
518 classNode = new EnumConstantClassNode(outerClass, fullName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
519 } else {
520 classNode = new InnerClassNode(outerClass, fullName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
521 }
522 ((InnerClassNode) classNode).setAnonymous(true);
523
524 assertNodeType(OBJBLOCK, node);
525 objectBlock(node);
526 output.addClass(classNode);
527 AnonymousInnerClassCarrier ret = new AnonymousInnerClassCarrier();
528 ret.innerClass = classNode;
529 classNode = oldNode;
530
531 return ret;
532 }
533
534 protected void innerClassDef(AST classDef) {
535 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
536 AST node = classDef.getFirstChild();
537 int modifiers = Opcodes.ACC_PUBLIC;
538 if (isType(MODIFIERS, node)) {
539 modifiers = modifiers(node, annotations, modifiers);
540 checkNoInvalidModifier(classDef, "Class", modifiers, Opcodes.ACC_SYNCHRONIZED, "synchronized");
541 node = node.getNextSibling();
542 }
543
544 String name = identifier(node);
545 node = node.getNextSibling();
546
547 GenericsType[] genericsType = null;
548 if (isType(TYPE_PARAMETERS, node)) {
549 genericsType = makeGenericsType(node);
550 node = node.getNextSibling();
551 }
552
553 ClassNode superClass = null;
554 if (isType(EXTENDS_CLAUSE, node)) {
555 superClass = makeTypeWithArguments(node);
556 node = node.getNextSibling();
557 }
558
559 ClassNode[] interfaces = ClassNode.EMPTY_ARRAY;
560 if (isType(IMPLEMENTS_CLAUSE, node)) {
561 interfaces = interfaces(node);
562 node = node.getNextSibling();
563 }
564
565
566 MixinNode[] mixins = {};
567 ClassNode outerClass = classNode;
568 boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0);
569 modifiers &= ~Opcodes.ACC_SYNTHETIC;
570 if (classNode != null) {
571 name = classNode.getNameWithoutPackage() + "$" + name;
572 String fullName = dot(classNode.getPackageName(), name);
573 classNode = new InnerClassNode(classNode, fullName, modifiers, superClass, interfaces, mixins);
574 } else {
575 classNode = new ClassNode(dot(getPackageName(), name), modifiers, superClass, interfaces, mixins);
576 }
577 classNode.addAnnotations(annotations);
578 classNode.setGenericsTypes(genericsType);
579 classNode.setSyntheticPublic(syntheticPublic);
580 configureAST(classNode, classDef);
581
582
583
584
585
586 output.addClass(classNode);
587
588 int oldClassCount = innerClassCounter;
589
590 assertNodeType(OBJBLOCK, node);
591 objectBlock(node);
592
593 classNode = outerClass;
594 innerClassCounter = oldClassCount;
595 }
596
597 protected void objectBlock(AST objectBlock) {
598 for (AST node = objectBlock.getFirstChild(); node != null; node = node.getNextSibling()) {
599 int type = node.getType();
600 switch (type) {
601 case OBJBLOCK:
602 objectBlock(node);
603 break;
604
605 case ANNOTATION_FIELD_DEF:
606 case METHOD_DEF:
607 methodDef(node);
608 break;
609
610 case CTOR_IDENT:
611 constructorDef(node);
612 break;
613
614 case VARIABLE_DEF:
615 fieldDef(node);
616 break;
617
618 case STATIC_INIT:
619 staticInit(node);
620 break;
621
622 case INSTANCE_INIT:
623 objectInit(node);
624 break;
625
626 case ENUM_DEF:
627 enumDef(node);
628 break;
629
630 case ENUM_CONSTANT_DEF:
631 enumConstantDef(node);
632 break;
633
634 case CLASS_DEF:
635 innerClassDef(node);
636 break;
637
638 case INTERFACE_DEF:
639 innerInterfaceDef(node);
640 break;
641
642 default:
643 unknownAST(node);
644 }
645 }
646 }
647
648 protected void enumDef(AST enumNode) {
649 assertNodeType(ENUM_DEF, enumNode);
650 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
651
652 AST node = enumNode.getFirstChild();
653 int modifiers = Opcodes.ACC_PUBLIC;
654 if (isType(MODIFIERS, node)) {
655 modifiers = modifiers(node, annotations, modifiers);
656 node = node.getNextSibling();
657 }
658
659 String name = identifier(node);
660 node = node.getNextSibling();
661
662 ClassNode[] interfaces = interfaces(node);
663 node = node.getNextSibling();
664
665 boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0);
666 modifiers &= ~Opcodes.ACC_SYNTHETIC;
667 String enumName = (classNode != null ? name : dot(getPackageName(), name));
668 ClassNode enumClass = EnumHelper.makeEnumNode(enumName, modifiers, interfaces, classNode);
669 enumClass.setSyntheticPublic(syntheticPublic);
670 ClassNode oldNode = classNode;
671 enumClass.addAnnotations(annotations);
672 classNode = enumClass;
673 assertNodeType(OBJBLOCK, node);
674 objectBlock(node);
675 classNode = oldNode;
676
677 output.addClass(enumClass);
678 }
679
680 protected void enumConstantDef(AST node) {
681 enumConstantBeingDef = true;
682 assertNodeType(ENUM_CONSTANT_DEF, node);
683 AST element = node.getFirstChild();
684 if (isType(ANNOTATIONS, element)) {
685 element = element.getNextSibling();
686 }
687 String identifier = identifier(element);
688 Expression init = null;
689 element = element.getNextSibling();
690
691 if (element != null) {
692 init = expression(element);
693 ClassNode innerClass = getAnonymousInnerClassNode(init);
694
695 if (innerClass != null) {
696
697
698
699 innerClass.setSuperClass(classNode);
700 innerClass.setModifiers(classNode.getModifiers() | Opcodes.ACC_FINAL);
701
702 init = new ClassExpression(innerClass);
703
704 classNode.setModifiers(classNode.getModifiers() & ~Opcodes.ACC_FINAL);
705 } else if (isType(ELIST, element)) {
706 if (init instanceof ListExpression && !((ListExpression) init).isWrapped()) {
707 ListExpression le = new ListExpression();
708 le.addExpression(init);
709 init = le;
710 }
711 }
712 }
713 EnumHelper.addEnumConstant(classNode, identifier, init);
714 enumConstantBeingDef = false;
715 }
716
717 protected void throwsList(AST node, List<ClassNode> list) {
718 String name;
719 if (isType(DOT, node)) {
720 name = qualifiedName(node);
721 } else {
722 name = identifier(node);
723 }
724 ClassNode exception = ClassHelper.make(name);
725 configureAST(exception, node);
726 list.add(exception);
727 AST next = node.getNextSibling();
728 if (next != null) throwsList(next, list);
729 }
730
731 protected void methodDef(AST methodDef) {
732 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
733 AST node = methodDef.getFirstChild();
734
735 GenericsType[] generics = null;
736 if (isType(TYPE_PARAMETERS, node)) {
737 generics = makeGenericsType(node);
738 node = node.getNextSibling();
739 }
740
741 int modifiers = Opcodes.ACC_PUBLIC;
742 if (isType(MODIFIERS, node)) {
743 modifiers = modifiers(node, annotations, modifiers);
744 checkNoInvalidModifier(methodDef, "Method", modifiers, Opcodes.ACC_VOLATILE, "volatile");
745 node = node.getNextSibling();
746 }
747
748 if (isAnInterface()) {
749 modifiers |= Opcodes.ACC_ABSTRACT;
750 }
751
752 ClassNode returnType = null;
753 if (isType(TYPE, node)) {
754 returnType = makeTypeWithArguments(node);
755 node = node.getNextSibling();
756 }
757
758 String name = identifier(node);
759 if (classNode != null && !classNode.isAnnotationDefinition()) {
760 if (classNode.getNameWithoutPackage().equals(name)) {
761 if (isAnInterface()) {
762 throw new ASTRuntimeException(methodDef, "Constructor not permitted within an interface.");
763 }
764 throw new ASTRuntimeException(methodDef, "Invalid constructor format. Remove '" + returnType.getName() +
765 "' as the return type if you want a constructor, or use a different name if you want a method.");
766 }
767 }
768 node = node.getNextSibling();
769
770 Parameter[] parameters = Parameter.EMPTY_ARRAY;
771 ClassNode[] exceptions = ClassNode.EMPTY_ARRAY;
772
773 if (classNode == null || !classNode.isAnnotationDefinition()) {
774
775 assertNodeType(PARAMETERS, node);
776 parameters = parameters(node);
777 if (parameters == null) parameters = Parameter.EMPTY_ARRAY;
778 node = node.getNextSibling();
779
780 if (isType(LITERAL_throws, node)) {
781 AST throwsNode = node.getFirstChild();
782 List<ClassNode> exceptionList = new ArrayList<ClassNode>();
783 throwsList(throwsNode, exceptionList);
784 exceptions = exceptionList.toArray(exceptions);
785 node = node.getNextSibling();
786 }
787 }
788
789 boolean hasAnnotationDefault = false;
790 Statement code = null;
791 if ((modifiers & Opcodes.ACC_ABSTRACT) == 0) {
792 if (node == null) {
793 throw new ASTRuntimeException(methodDef, "You defined a method without body. Try adding a body, or declare it abstract.");
794 }
795 assertNodeType(SLIST, node);
796 code = statementList(node);
797 } else if (node != null && classNode.isAnnotationDefinition()) {
798 code = statement(node);
799 hasAnnotationDefault = true;
800 } else if ((modifiers & Opcodes.ACC_ABSTRACT) > 0) {
801 if (node != null) {
802 throw new ASTRuntimeException(methodDef, "Abstract methods do not define a body.");
803 }
804 }
805
806 boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0);
807 modifiers &= ~Opcodes.ACC_SYNTHETIC;
808 MethodNode methodNode = new MethodNode(name, modifiers, returnType, parameters, exceptions, code);
809 methodNode.addAnnotations(annotations);
810 methodNode.setGenericsTypes(generics);
811 methodNode.setAnnotationDefault(hasAnnotationDefault);
812 methodNode.setSyntheticPublic(syntheticPublic);
813 configureAST(methodNode, methodDef);
814
815 if (classNode != null) {
816 classNode.addMethod(methodNode);
817 } else {
818 output.addMethod(methodNode);
819 }
820 }
821
822 private void checkNoInvalidModifier(AST node, String nodeType, int modifiers, int modifier, String modifierText) {
823 if ((modifiers & modifier) != 0) {
824 throw new ASTRuntimeException(node, nodeType + " has an incorrect modifier '" + modifierText + "'.");
825 }
826 }
827
828 private boolean isAnInterface() {
829 return classNode != null && (classNode.getModifiers() & Opcodes.ACC_INTERFACE) > 0;
830 }
831
832 protected void staticInit(AST staticInit) {
833 BlockStatement code = (BlockStatement) statementList(staticInit);
834 classNode.addStaticInitializerStatements(code.getStatements(), false);
835 }
836
837 protected void objectInit(AST init) {
838 BlockStatement code = (BlockStatement) statementList(init);
839 classNode.addObjectInitializerStatements(code);
840 }
841
842 protected void constructorDef(AST constructorDef) {
843 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
844 AST node = constructorDef.getFirstChild();
845 int modifiers = Opcodes.ACC_PUBLIC;
846 if (isType(MODIFIERS, node)) {
847 modifiers = modifiers(node, annotations, modifiers);
848 node = node.getNextSibling();
849 }
850
851 assertNodeType(PARAMETERS, node);
852 Parameter[] parameters = parameters(node);
853 if (parameters == null) parameters = Parameter.EMPTY_ARRAY;
854 node = node.getNextSibling();
855
856 ClassNode[] exceptions = ClassNode.EMPTY_ARRAY;
857 if (isType(LITERAL_throws, node)) {
858 AST throwsNode = node.getFirstChild();
859 List<ClassNode> exceptionList = new ArrayList<ClassNode>();
860 throwsList(throwsNode, exceptionList);
861 exceptions = exceptionList.toArray(exceptions);
862 node = node.getNextSibling();
863 }
864
865 assertNodeType(SLIST, node);
866 Statement code = statementList(node);
867
868 boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0);
869 modifiers &= ~Opcodes.ACC_SYNTHETIC;
870 ConstructorNode constructorNode = classNode.addConstructor(modifiers, parameters, exceptions, code);
871 constructorNode.setSyntheticPublic(syntheticPublic);
872 constructorNode.addAnnotations(annotations);
873 configureAST(constructorNode, constructorDef);
874 }
875
876 protected void fieldDef(AST fieldDef) {
877 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
878 AST node = fieldDef.getFirstChild();
879
880 int modifiers = 0;
881 if (isType(MODIFIERS, node)) {
882 modifiers = modifiers(node, annotations, modifiers);
883 node = node.getNextSibling();
884 }
885
886 if (classNode.isInterface()) {
887 modifiers |= Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
888 if ((modifiers & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) == 0) {
889 modifiers |= Opcodes.ACC_PUBLIC;
890 }
891 }
892
893 ClassNode type = null;
894 if (isType(TYPE, node)) {
895 type = makeTypeWithArguments(node);
896 node = node.getNextSibling();
897 }
898
899 String name = identifier(node);
900 node = node.getNextSibling();
901
902 Expression initialValue = null;
903 if (node != null) {
904 assertNodeType(ASSIGN, node);
905 initialValue = expression(node.getFirstChild());
906 }
907
908 if (classNode.isInterface() && initialValue == null && type != null) {
909 if (type == ClassHelper.int_TYPE) {
910 initialValue = new ConstantExpression(0);
911 } else if (type == ClassHelper.long_TYPE) {
912 initialValue = new ConstantExpression(0L);
913 } else if (type == ClassHelper.double_TYPE) {
914 initialValue = new ConstantExpression(0.0);
915 } else if (type == ClassHelper.float_TYPE) {
916 initialValue = new ConstantExpression(0.0F);
917 } else if (type == ClassHelper.boolean_TYPE) {
918 initialValue = ConstantExpression.FALSE;
919 } else if (type == ClassHelper.short_TYPE) {
920 initialValue = new ConstantExpression((short) 0);
921 } else if (type == ClassHelper.byte_TYPE) {
922 initialValue = new ConstantExpression((byte) 0);
923 } else if (type == ClassHelper.char_TYPE) {
924 initialValue = new ConstantExpression((char) 0);
925 }
926 }
927
928
929 FieldNode fieldNode = new FieldNode(name, modifiers, type, classNode, initialValue);
930 fieldNode.addAnnotations(annotations);
931 configureAST(fieldNode, fieldDef);
932
933 if (!hasVisibility(modifiers)) {
934
935 int fieldModifiers = 0;
936 int flags = Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT | Opcodes.ACC_VOLATILE | Opcodes.ACC_FINAL;
937
938 if (!hasVisibility(modifiers)) {
939 modifiers |= Opcodes.ACC_PUBLIC;
940 fieldModifiers |= Opcodes.ACC_PRIVATE;
941 }
942
943
944 fieldModifiers |= (modifiers & flags);
945 fieldNode.setModifiers(fieldModifiers);
946 fieldNode.setSynthetic(true);
947
948
949
950
951 FieldNode storedNode = classNode.getDeclaredField(fieldNode.getName());
952 if (storedNode != null && !classNode.hasProperty(name)) {
953 fieldNode = storedNode;
954
955
956
957 classNode.getFields().remove(storedNode);
958 }
959
960 PropertyNode propertyNode = new PropertyNode(fieldNode, modifiers, null, null);
961 configureAST(propertyNode, fieldDef);
962 classNode.addProperty(propertyNode);
963 } else {
964 fieldNode.setModifiers(modifiers);
965
966
967
968 PropertyNode pn = classNode.getProperty(name);
969 if (pn != null && pn.getField().isSynthetic()) {
970 classNode.getFields().remove(pn.getField());
971 pn.setField(fieldNode);
972 }
973 classNode.addField(fieldNode);
974 }
975 }
976
977 protected ClassNode[] interfaces(AST node) {
978 List<ClassNode> interfaceList = new ArrayList<ClassNode>();
979 for (AST implementNode = node.getFirstChild(); implementNode != null; implementNode = implementNode.getNextSibling()) {
980 interfaceList.add(makeTypeWithArguments(implementNode));
981 }
982 ClassNode[] interfaces = ClassNode.EMPTY_ARRAY;
983 if (!interfaceList.isEmpty()) {
984 interfaces = new ClassNode[interfaceList.size()];
985 interfaceList.toArray(interfaces);
986 }
987 return interfaces;
988 }
989
990 protected Parameter[] parameters(AST parametersNode) {
991 AST node = parametersNode.getFirstChild();
992 firstParam = false;
993 firstParamIsVarArg = false;
994 if (node == null) {
995 if (isType(IMPLICIT_PARAMETERS, parametersNode)) return Parameter.EMPTY_ARRAY;
996 return null;
997 } else {
998 List<Parameter> parameters = new ArrayList<Parameter>();
999 AST firstParameterNode = null;
1000 do {
1001 firstParam = (firstParameterNode == null);
1002 if (firstParameterNode == null) firstParameterNode = node;
1003 parameters.add(parameter(node));
1004 node = node.getNextSibling();
1005 }
1006 while (node != null);
1007
1008 verifyParameters(parameters, firstParameterNode);
1009
1010 Parameter[] answer = new Parameter[parameters.size()];
1011 parameters.toArray(answer);
1012 return answer;
1013 }
1014 }
1015
1016 private void verifyParameters(List<Parameter> parameters, AST firstParameterNode) {
1017 if (parameters.size() <= 1) return;
1018
1019 Parameter first = parameters.get(0);
1020 if (firstParamIsVarArg) {
1021 throw new ASTRuntimeException(firstParameterNode, "The var-arg parameter " + first.getName() + " must be the last parameter.");
1022 }
1023 }
1024
1025 protected Parameter parameter(AST paramNode) {
1026 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
1027 boolean variableParameterDef = isType(VARIABLE_PARAMETER_DEF, paramNode);
1028 AST node = paramNode.getFirstChild();
1029
1030 int modifiers = 0;
1031 if (isType(MODIFIERS, node)) {
1032 modifiers = modifiers(node, annotations, modifiers);
1033 node = node.getNextSibling();
1034 }
1035
1036 ClassNode type = ClassHelper.DYNAMIC_TYPE;
1037 if (isType(TYPE, node)) {
1038 type = makeTypeWithArguments(node);
1039 if (variableParameterDef) type = type.makeArray();
1040 node = node.getNextSibling();
1041 }
1042
1043 String name = identifier(node);
1044 node = node.getNextSibling();
1045
1046 VariableExpression leftExpression = new VariableExpression(name, type);
1047 leftExpression.setModifiers(modifiers);
1048 configureAST(leftExpression, paramNode);
1049
1050 Parameter parameter = null;
1051 if (node != null) {
1052 assertNodeType(ASSIGN, node);
1053 Expression rightExpression = expression(node.getFirstChild());
1054 if (isAnInterface()) {
1055 throw new ASTRuntimeException(node, "Cannot specify default value for method parameter '" + name + " = " + rightExpression.getText() + "' inside an interface");
1056 }
1057 parameter = new Parameter(type, name, rightExpression);
1058 } else
1059 parameter = new Parameter(type, name);
1060
1061 if (firstParam) firstParamIsVarArg = variableParameterDef;
1062
1063 configureAST(parameter, paramNode);
1064 parameter.addAnnotations(annotations);
1065 parameter.setModifiers(modifiers);
1066 return parameter;
1067 }
1068
1069 protected int modifiers(AST modifierNode, List<AnnotationNode> annotations, int defaultModifiers) {
1070 assertNodeType(MODIFIERS, modifierNode);
1071
1072 boolean access = false;
1073 int answer = 0;
1074
1075 for (AST node = modifierNode.getFirstChild(); node != null; node = node.getNextSibling()) {
1076 int type = node.getType();
1077 switch (type) {
1078 case STATIC_IMPORT:
1079
1080 break;
1081
1082
1083 case ANNOTATION:
1084 annotations.add(annotation(node));
1085 break;
1086
1087
1088 case LITERAL_private:
1089 answer = setModifierBit(node, answer, Opcodes.ACC_PRIVATE);
1090 access = setAccessTrue(node, access);
1091 break;
1092
1093 case LITERAL_protected:
1094 answer = setModifierBit(node, answer, Opcodes.ACC_PROTECTED);
1095 access = setAccessTrue(node, access);
1096 break;
1097
1098 case LITERAL_public:
1099 answer = setModifierBit(node, answer, Opcodes.ACC_PUBLIC);
1100 access = setAccessTrue(node, access);
1101 break;
1102
1103
1104 case ABSTRACT:
1105 answer = setModifierBit(node, answer, Opcodes.ACC_ABSTRACT);
1106 break;
1107
1108 case FINAL:
1109 answer = setModifierBit(node, answer, Opcodes.ACC_FINAL);
1110 break;
1111
1112 case LITERAL_native:
1113 answer = setModifierBit(node, answer, Opcodes.ACC_NATIVE);
1114 break;
1115
1116 case LITERAL_static:
1117 answer = setModifierBit(node, answer, Opcodes.ACC_STATIC);
1118 break;
1119
1120 case STRICTFP:
1121 answer = setModifierBit(node, answer, Opcodes.ACC_STRICT);
1122 break;
1123
1124 case LITERAL_synchronized:
1125 answer = setModifierBit(node, answer, Opcodes.ACC_SYNCHRONIZED);
1126 break;
1127
1128 case LITERAL_transient:
1129 answer = setModifierBit(node, answer, Opcodes.ACC_TRANSIENT);
1130 break;
1131
1132 case LITERAL_volatile:
1133 answer = setModifierBit(node, answer, Opcodes.ACC_VOLATILE);
1134 break;
1135
1136 default:
1137 unknownAST(node);
1138 }
1139 }
1140 if (!access) {
1141 answer |= defaultModifiers;
1142
1143 if (defaultModifiers == Opcodes.ACC_PUBLIC) answer |= Opcodes.ACC_SYNTHETIC;
1144 }
1145 return answer;
1146 }
1147
1148 protected boolean setAccessTrue(AST node, boolean access) {
1149 if (!access) {
1150 return true;
1151 } else {
1152 throw new ASTRuntimeException(node, "Cannot specify modifier: " + node.getText() + " when access scope has already been defined");
1153 }
1154 }
1155
1156 protected int setModifierBit(AST node, int answer, int bit) {
1157 if ((answer & bit) != 0) {
1158 throw new ASTRuntimeException(node, "Cannot repeat modifier: " + node.getText());
1159 }
1160 return answer | bit;
1161 }
1162
1163 protected AnnotationNode annotation(AST annotationNode) {
1164 AST node = annotationNode.getFirstChild();
1165 String name = qualifiedName(node);
1166 AnnotationNode annotatedNode = new AnnotationNode(ClassHelper.make(name));
1167 configureAST(annotatedNode, annotationNode);
1168 while (true) {
1169 node = node.getNextSibling();
1170 if (isType(ANNOTATION_MEMBER_VALUE_PAIR, node)) {
1171 AST memberNode = node.getFirstChild();
1172 String param = identifier(memberNode);
1173 Expression expression = expression(memberNode.getNextSibling());
1174 if (annotatedNode.getMember(param) != null) {
1175 throw new ASTRuntimeException(memberNode, "Annotation member '" + param + "' has already been associated with a value");
1176 }
1177 annotatedNode.setMember(param, expression);
1178 } else {
1179 break;
1180 }
1181 }
1182 return annotatedNode;
1183 }
1184
1185
1186
1187
1188
1189 protected Statement statement(AST node) {
1190 Statement statement = null;
1191 int type = node.getType();
1192 switch (type) {
1193 case SLIST:
1194 case LITERAL_finally:
1195 statement = statementList(node);
1196 break;
1197
1198 case METHOD_CALL:
1199 statement = methodCall(node);
1200 break;
1201
1202 case VARIABLE_DEF:
1203 statement = variableDef(node);
1204 break;
1205
1206
1207 case LABELED_STAT:
1208 statement = labelledStatement(node);
1209 break;
1210
1211 case LITERAL_assert:
1212 statement = assertStatement(node);
1213 break;
1214
1215 case LITERAL_break:
1216 statement = breakStatement(node);
1217 break;
1218
1219 case LITERAL_continue:
1220 statement = continueStatement(node);
1221 break;
1222
1223 case LITERAL_if:
1224 statement = ifStatement(node);
1225 break;
1226
1227 case LITERAL_for:
1228 statement = forStatement(node);
1229 break;
1230
1231 case LITERAL_return:
1232 statement = returnStatement(node);
1233 break;
1234
1235 case LITERAL_synchronized:
1236 statement = synchronizedStatement(node);
1237 break;
1238
1239 case LITERAL_switch:
1240 statement = switchStatement(node);
1241 break;
1242
1243 case LITERAL_try:
1244 statement = tryStatement(node);
1245 break;
1246
1247 case LITERAL_throw:
1248 statement = throwStatement(node);
1249 break;
1250
1251 case LITERAL_while:
1252 statement = whileStatement(node);
1253 break;
1254
1255 default:
1256 statement = new ExpressionStatement(expression(node));
1257 }
1258 if (statement != null) {
1259 configureAST(statement, node);
1260 }
1261 return statement;
1262 }
1263
1264 protected Statement statementList(AST code) {
1265 return statementListNoChild(code.getFirstChild(), code);
1266 }
1267
1268 protected Statement statementListNoChild(AST node, AST alternativeConfigureNode) {
1269 BlockStatement block = new BlockStatement();
1270
1271 if (node != null) {
1272 configureAST(block, node);
1273 } else {
1274 configureAST(block, alternativeConfigureNode);
1275 }
1276 for (; node != null; node = node.getNextSibling()) {
1277 block.addStatement(statement(node));
1278 }
1279 return block;
1280 }
1281
1282 protected Statement assertStatement(AST assertNode) {
1283 AST node = assertNode.getFirstChild();
1284 BooleanExpression booleanExpression = booleanExpression(node);
1285 Expression messageExpression = null;
1286
1287 node = node.getNextSibling();
1288 if (node != null) {
1289 messageExpression = expression(node);
1290 } else {
1291 messageExpression = ConstantExpression.NULL;
1292 }
1293 AssertStatement assertStatement = new AssertStatement(booleanExpression, messageExpression);
1294 configureAST(assertStatement, assertNode);
1295 return assertStatement;
1296 }
1297
1298 protected Statement breakStatement(AST node) {
1299 BreakStatement breakStatement = new BreakStatement(label(node));
1300 configureAST(breakStatement, node);
1301 return breakStatement;
1302 }
1303
1304 protected Statement continueStatement(AST node) {
1305 ContinueStatement continueStatement = new ContinueStatement(label(node));
1306 configureAST(continueStatement, node);
1307 return continueStatement;
1308 }
1309
1310 protected Statement forStatement(AST forNode) {
1311 AST inNode = forNode.getFirstChild();
1312 Expression collectionExpression;
1313 Parameter forParameter;
1314 if (isType(CLOSURE_LIST, inNode)) {
1315 forStatementBeingDef = true;
1316 ClosureListExpression clist = closureListExpression(inNode);
1317 forStatementBeingDef = false;
1318 int size = clist.getExpressions().size();
1319 if (size != 3) {
1320 throw new ASTRuntimeException(inNode, "3 expressions are required for the classic for loop, you gave " + size);
1321 }
1322 collectionExpression = clist;
1323 forParameter = ForStatement.FOR_LOOP_DUMMY;
1324 } else {
1325 AST variableNode = inNode.getFirstChild();
1326 AST collectionNode = variableNode.getNextSibling();
1327
1328 ClassNode type = ClassHelper.OBJECT_TYPE;
1329 if (isType(VARIABLE_DEF, variableNode)) {
1330 AST node = variableNode.getFirstChild();
1331
1332 if (isType(MODIFIERS, node)) {
1333 int modifiersMask = modifiers(node, new ArrayList<AnnotationNode>(), 0);
1334
1335 if ((modifiersMask & ~Opcodes.ACC_FINAL) != 0) {
1336 throw new ASTRuntimeException(node, "Only the 'final' modifier is allowed in front of the for loop variable.");
1337 }
1338 node = node.getNextSibling();
1339 }
1340 type = makeTypeWithArguments(node);
1341
1342 variableNode = node.getNextSibling();
1343 }
1344 String variable = identifier(variableNode);
1345
1346 collectionExpression = expression(collectionNode);
1347 forParameter = new Parameter(type, variable);
1348 configureAST(forParameter, variableNode);
1349 }
1350
1351 final AST node = inNode.getNextSibling();
1352 Statement block;
1353 if (isType(SEMI, node)) {
1354 block = EmptyStatement.INSTANCE;
1355 } else {
1356 block = statement(node);
1357 }
1358 ForStatement forStatement = new ForStatement(forParameter, collectionExpression, block);
1359 configureAST(forStatement, forNode);
1360 return forStatement;
1361 }
1362
1363 protected Statement ifStatement(AST ifNode) {
1364 AST node = ifNode.getFirstChild();
1365 assertNodeType(EXPR, node);
1366 BooleanExpression booleanExpression = booleanExpression(node);
1367
1368 node = node.getNextSibling();
1369 Statement ifBlock = statement(node);
1370
1371 Statement elseBlock = EmptyStatement.INSTANCE;
1372 node = node.getNextSibling();
1373 if (node != null) {
1374 elseBlock = statement(node);
1375 }
1376 IfStatement ifStatement = new IfStatement(booleanExpression, ifBlock, elseBlock);
1377 configureAST(ifStatement, ifNode);
1378 return ifStatement;
1379 }
1380
1381 protected Statement labelledStatement(AST labelNode) {
1382 AST node = labelNode.getFirstChild();
1383 String label = identifier(node);
1384 Statement statement = statement(node.getNextSibling());
1385 if (statement.getStatementLabel() == null)
1386 statement.setStatementLabel(label);
1387 return statement;
1388 }
1389
1390 protected Statement methodCall(AST code) {
1391 Expression expression = methodCallExpression(code);
1392 ExpressionStatement expressionStatement = new ExpressionStatement(expression);
1393 configureAST(expressionStatement, code);
1394 return expressionStatement;
1395 }
1396
1397 protected Expression declarationExpression(AST variableDef) {
1398 AST node = variableDef.getFirstChild();
1399 ClassNode type = null;
1400 List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
1401 int modifiers = 0;
1402 if (isType(MODIFIERS, node)) {
1403
1404 modifiers = modifiers(node, annotations, 0);
1405 node = node.getNextSibling();
1406 }
1407 if (isType(TYPE, node)) {
1408 type = makeTypeWithArguments(node);
1409 node = node.getNextSibling();
1410 }
1411
1412 Expression leftExpression;
1413 Expression rightExpression = EmptyExpression.INSTANCE;
1414 AST right;
1415
1416 if (isType(ASSIGN, node)) {
1417 node = node.getFirstChild();
1418 AST left = node.getFirstChild();
1419 ArgumentListExpression alist = new ArgumentListExpression();
IL_INFINITE_LOOP
1421 assertNodeType(VARIABLE_DEF, varDef);
1422 DeclarationExpression de = (DeclarationExpression) declarationExpression(varDef);
1423 alist.addExpression(de.getVariableExpression());
1424 }
1425 leftExpression = alist;
1426 right = node.getNextSibling();
1427 if (right != null) rightExpression = expression(right);
1428 } else {
1429 String name = identifier(node);
1430 VariableExpression ve = new VariableExpression(name, type);
1431 ve.setModifiers(modifiers);
1432 leftExpression = ve;
1433
1434 right = node.getNextSibling();
1435 if (right != null) {
1436 assertNodeType(ASSIGN, right);
1437 rightExpression = expression(right.getFirstChild());
1438 }
1439 }
1440
1441 configureAST(leftExpression, node);
1442
1443 Token token = makeToken(Types.ASSIGN, variableDef);
1444 DeclarationExpression expression = new DeclarationExpression(leftExpression, token, rightExpression);
1445 expression.addAnnotations(annotations);
1446 configureAST(expression, variableDef);
1447 ExpressionStatement expressionStatement = new ExpressionStatement(expression);
1448 configureAST(expressionStatement, variableDef);
1449 return expression;
1450 }
1451
1452 protected Statement variableDef(AST variableDef) {
1453 ExpressionStatement expressionStatement = new ExpressionStatement(declarationExpression(variableDef));
1454 configureAST(expressionStatement, variableDef);
1455 return expressionStatement;
1456 }
1457
1458 protected Statement returnStatement(AST node) {
1459 AST exprNode = node.getFirstChild();
1460
1461
1462
1463
1464
1465
1466 Expression expression = exprNode == null ? ConstantExpression.NULL : expression(exprNode);
1467 ReturnStatement returnStatement = new ReturnStatement(expression);
1468 configureAST(returnStatement, node);
1469 return returnStatement;
1470 }
1471
1472 protected Statement switchStatement(AST switchNode) {
1473 AST node = switchNode.getFirstChild();
1474 Expression expression = expression(node);
1475 Statement defaultStatement = EmptyStatement.INSTANCE;
1476
1477 List list = new ArrayList();
1478 for (node = node.getNextSibling(); isType(CASE_GROUP, node); node = node.getNextSibling()) {
1479 Statement tmpDefaultStatement;
1480 AST child = node.getFirstChild();
1481 if (isType(LITERAL_case, child)) {
1482 List cases = new LinkedList();
1483
1484 tmpDefaultStatement = caseStatements(child, cases);
1485 list.addAll(cases);
1486 } else {
1487 tmpDefaultStatement = statement(child.getNextSibling());
1488 }
1489 if (tmpDefaultStatement != EmptyStatement.INSTANCE) {
1490 if (defaultStatement == EmptyStatement.INSTANCE) {
1491 defaultStatement = tmpDefaultStatement;
1492 } else {
1493 throw new ASTRuntimeException(switchNode, "The default case is already defined.");
1494 }
1495 }
1496 }
1497 if (node != null) {
1498 unknownAST(node);
1499 }
1500 SwitchStatement switchStatement = new SwitchStatement(expression, list, defaultStatement);
1501 configureAST(switchStatement, switchNode);
1502 return switchStatement;
1503 }
1504
1505 protected Statement caseStatements(AST node, List cases) {
1506 List<Expression> expressions = new LinkedList<Expression>();
1507 Statement statement = EmptyStatement.INSTANCE;
1508 Statement defaultStatement = EmptyStatement.INSTANCE;
1509 AST nextSibling = node;
1510 do {
1511 Expression expression = expression(nextSibling.getFirstChild());
1512 expressions.add(expression);
1513 nextSibling = nextSibling.getNextSibling();
1514 } while (isType(LITERAL_case, nextSibling));
1515 if (nextSibling != null) {
1516 if (isType(LITERAL_default, nextSibling)) {
1517 defaultStatement = statement(nextSibling.getNextSibling());
1518 statement = EmptyStatement.INSTANCE;
1519 } else {
1520 statement = statement(nextSibling);
1521 }
1522 }
1523 Iterator iterator = expressions.iterator();
1524 while (iterator.hasNext()) {
1525 Expression expr = (Expression) iterator.next();
1526 Statement stmt;
1527 if (iterator.hasNext()) {
1528 stmt = new CaseStatement(expr, EmptyStatement.INSTANCE);
1529 } else {
1530 stmt = new CaseStatement(expr, statement);
1531 }
1532 configureAST(stmt, node);
1533 cases.add(stmt);
1534 }
1535 return defaultStatement;
1536 }
1537
1538 protected Statement synchronizedStatement(AST syncNode) {
1539 AST node = syncNode.getFirstChild();
1540 Expression expression = expression(node);
1541 Statement code = statement(node.getNextSibling());
1542 SynchronizedStatement synchronizedStatement = new SynchronizedStatement(expression, code);
1543 configureAST(synchronizedStatement, syncNode);
1544 return synchronizedStatement;
1545 }
1546
1547 protected Statement throwStatement(AST node) {
1548 AST expressionNode = node.getFirstChild();
1549 if (expressionNode == null) {
1550 expressionNode = node.getNextSibling();
1551 }
1552 if (expressionNode == null) {
1553 throw new ASTRuntimeException(node, "No expression available");
1554 }
1555 ThrowStatement throwStatement = new ThrowStatement(expression(expressionNode));
1556 configureAST(throwStatement, node);
1557 return throwStatement;
1558 }
1559
1560 protected Statement tryStatement(AST tryStatementNode) {
1561 AST tryNode = tryStatementNode.getFirstChild();
1562 Statement tryStatement = statement(tryNode);
1563 Statement finallyStatement = EmptyStatement.INSTANCE;
1564 AST node = tryNode.getNextSibling();
1565
1566
1567 List<CatchStatement> catches = new ArrayList<CatchStatement>();
1568 for (; node != null && isType(LITERAL_catch, node); node = node.getNextSibling()) {
1569 final List<CatchStatement> catchStatements = catchStatement(node);
1570 catches.addAll(catchStatements);
1571 }
1572
1573 if (isType(LITERAL_finally, node)) {
1574 finallyStatement = statement(node);
1575 node = node.getNextSibling();
1576 }
1577
1578 if (finallyStatement instanceof EmptyStatement && catches.size() == 0) {
1579 throw new ASTRuntimeException(tryStatementNode, "A try statement must have at least one catch or finally block.");
1580 }
1581
1582 TryCatchStatement tryCatchStatement = new TryCatchStatement(tryStatement, finallyStatement);
1583 configureAST(tryCatchStatement, tryStatementNode);
1584 for (CatchStatement statement : catches) {
1585 tryCatchStatement.addCatch(statement);
1586 }
1587 return tryCatchStatement;
1588 }
1589
1590 protected List<CatchStatement> catchStatement(AST catchNode) {
1591 AST node = catchNode.getFirstChild();
1592 List<CatchStatement> catches = new LinkedList<CatchStatement>();
1593 Statement code = statement(node.getNextSibling());
1594 if (MULTICATCH == node.getType()) {
1595 AST variableNode = node.getNextSibling();
1596 final AST multicatches = node.getFirstChild();
1597 if (multicatches.getType() != MULTICATCH_TYPES) {
1598
1599
1600 String variable = identifier(multicatches);
1601 Parameter catchParameter = new Parameter(ClassHelper.DYNAMIC_TYPE, variable);
1602 CatchStatement answer = new CatchStatement(catchParameter, code);
1603 configureAST(answer, catchNode);
1604 catches.add(answer);
1605 } else {
1606
1607
1608 AST exceptionNodes = multicatches.getFirstChild();
1609 String variable = identifier(multicatches.getNextSibling());
1610 while (exceptionNodes != null) {
1611 ClassNode exceptionType = buildName(exceptionNodes);
1612 Parameter catchParameter = new Parameter(exceptionType, variable);
1613 CatchStatement answer = new CatchStatement(catchParameter, code);
1614 configureAST(answer, catchNode);
1615 catches.add(answer);
1616 exceptionNodes = exceptionNodes.getNextSibling();
1617 }
1618 }
1619 }
1620 return catches;
1621 }
1622
1623 protected Statement whileStatement(AST whileNode) {
1624 AST node = whileNode.getFirstChild();
1625 assertNodeType(EXPR, node);
1626
1627 if (isType(VARIABLE_DEF, node.getFirstChild())) {
1628 throw new ASTRuntimeException(whileNode,
1629 "While loop condition contains a declaration; this is currently unsupported.");
1630 }
1631 BooleanExpression booleanExpression = booleanExpression(node);
1632
1633 node = node.getNextSibling();
1634 Statement block;
1635 if (isType(SEMI, node)) {
1636 block = EmptyStatement.INSTANCE;
1637 } else {
1638 block = statement(node);
1639 }
1640 WhileStatement whileStatement = new WhileStatement(booleanExpression, block);
1641 configureAST(whileStatement, whileNode);
1642 return whileStatement;
1643 }
1644
1645
1646
1647
1648
1649 protected Expression expression(AST node) {
1650 return expression(node, false);
1651 }
1652
1653 protected Expression expression(AST node, boolean convertToConstant) {
1654 Expression expression = expressionSwitch(node);
1655 if (convertToConstant && expression instanceof VariableExpression) {
1656
1657
1658
1659
1660 VariableExpression ve = (VariableExpression) expression;
1661 if (!ve.isThisExpression() && !ve.isSuperExpression()) {
1662 expression = new ConstantExpression(ve.getName());
1663 }
1664 }
1665 configureAST(expression, node);
1666 return expression;
1667 }
1668
ExcessiveMethodLength
1670 int type = node.getType();
1671 switch (type) {
1672 case EXPR:
1673 return expression(node.getFirstChild());
1674
1675 case ELIST:
1676 return expressionList(node);
1677
1678 case SLIST:
1679 return blockExpression(node);
1680
1681 case CLOSABLE_BLOCK:
1682 return closureExpression(node);
1683
1684 case SUPER_CTOR_CALL:
1685 return specialConstructorCallExpression(node, ClassNode.SUPER);
1686
1687 case METHOD_CALL:
1688 return methodCallExpression(node);
1689
1690 case LITERAL_new:
1691 return constructorCallExpression(node);
1692
1693 case CTOR_CALL:
1694 return specialConstructorCallExpression(node, ClassNode.THIS);
1695
1696 case QUESTION:
1697 case ELVIS_OPERATOR:
1698 return ternaryExpression(node);
1699
1700 case OPTIONAL_DOT:
1701 case SPREAD_DOT:
1702 case DOT:
1703 return dotExpression(node);
1704
1705 case IDENT:
1706 case LITERAL_boolean:
1707 case LITERAL_byte:
1708 case LITERAL_char:
1709 case LITERAL_double:
1710 case LITERAL_float:
1711 case LITERAL_int:
1712 case LITERAL_long:
1713 case LITERAL_short:
1714 case LITERAL_void:
1715 case LITERAL_this:
1716 case LITERAL_super:
1717 return variableExpression(node);
1718
1719 case LIST_CONSTRUCTOR:
1720 return listExpression(node);
1721
1722 case MAP_CONSTRUCTOR:
1723 return mapExpression(node);
1724
1725 case LABELED_ARG:
1726 return mapEntryExpression(node);
1727
1728 case SPREAD_ARG:
1729 return spreadExpression(node);
1730
1731 case SPREAD_MAP_ARG:
1732 return spreadMapExpression(node);
1733
1734
1735
1736
1737
1738 case MEMBER_POINTER:
1739 return methodPointerExpression(node);
1740
1741 case INDEX_OP:
1742 return indexExpression(node);
1743
1744 case LITERAL_instanceof:
1745 return instanceofExpression(node);
1746
1747 case LITERAL_as:
1748 return asExpression(node);
1749
1750 case TYPECAST:
1751 return castExpression(node);
1752
1753
1754
1755 case LITERAL_true:
1756 return literalExpression(node, Boolean.TRUE);
1757 case LITERAL_false:
1758 return literalExpression(node, Boolean.FALSE);
1759 case LITERAL_null:
1760 return literalExpression(node, null);
1761 case STRING_LITERAL:
1762 return literalExpression(node, node.getText());
1763
1764 case STRING_CONSTRUCTOR:
1765 return gstring(node);
1766
1767 case NUM_DOUBLE:
1768 case NUM_FLOAT:
1769 case NUM_BIG_DECIMAL:
1770 return decimalExpression(node);
1771
1772 case NUM_BIG_INT:
1773 case NUM_INT:
1774 case NUM_LONG:
1775 return integerExpression(node);
1776
1777
1778 case LNOT:
1779 NotExpression notExpression = new NotExpression(expression(node.getFirstChild()));
1780 configureAST(notExpression, node);
1781 return notExpression;
1782
1783 case UNARY_MINUS:
1784 return unaryMinusExpression(node);
1785
1786 case BNOT:
1787 BitwiseNegationExpression bitwiseNegationExpression = new BitwiseNegationExpression(expression(node.getFirstChild()));
1788 configureAST(bitwiseNegationExpression, node);
1789 return bitwiseNegationExpression;
1790
1791 case UNARY_PLUS:
1792 return unaryPlusExpression(node);
1793
1794
1795 case INC:
1796 return prefixExpression(node, Types.PLUS_PLUS);
1797
1798 case DEC:
1799 return prefixExpression(node, Types.MINUS_MINUS);
1800
1801
1802 case POST_INC:
1803 return postfixExpression(node, Types.PLUS_PLUS);
1804
1805 case POST_DEC:
1806 return postfixExpression(node, Types.MINUS_MINUS);
1807
1808
1809
1810
1811 case ASSIGN:
1812 return binaryExpression(Types.ASSIGN, node);
1813
1814 case EQUAL:
1815 return binaryExpression(Types.COMPARE_EQUAL, node);
1816
1817 case IDENTICAL:
1818 return binaryExpression(Types.COMPARE_IDENTICAL, node);
1819
1820 case NOT_EQUAL:
1821 return binaryExpression(Types.COMPARE_NOT_EQUAL, node);
1822
1823 case NOT_IDENTICAL:
1824 return binaryExpression(Types.COMPARE_NOT_IDENTICAL, node);
1825
1826 case COMPARE_TO:
1827 return binaryExpression(Types.COMPARE_TO, node);
1828
1829 case LE:
1830 return binaryExpression(Types.COMPARE_LESS_THAN_EQUAL, node);
1831
1832 case LT:
1833 return binaryExpression(Types.COMPARE_LESS_THAN, node);
1834
1835 case GT:
1836 return binaryExpression(Types.COMPARE_GREATER_THAN, node);
1837
1838 case GE:
1839 return binaryExpression(Types.COMPARE_GREATER_THAN_EQUAL, node);
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853 case LAND:
1854 return binaryExpression(Types.LOGICAL_AND, node);
1855
1856 case LOR:
1857 return binaryExpression(Types.LOGICAL_OR, node);
1858
1859 case BAND:
1860 return binaryExpression(Types.BITWISE_AND, node);
1861
1862 case BAND_ASSIGN:
1863 return binaryExpression(Types.BITWISE_AND_EQUAL, node);
1864
1865 case BOR:
1866 return binaryExpression(Types.BITWISE_OR, node);
1867
1868 case BOR_ASSIGN:
1869 return binaryExpression(Types.BITWISE_OR_EQUAL, node);
1870
1871 case BXOR:
1872 return binaryExpression(Types.BITWISE_XOR, node);
1873
1874 case BXOR_ASSIGN:
1875 return binaryExpression(Types.BITWISE_XOR_EQUAL, node);
1876
1877
1878 case PLUS:
1879 return binaryExpression(Types.PLUS, node);
1880
1881 case PLUS_ASSIGN:
1882 return binaryExpression(Types.PLUS_EQUAL, node);
1883
1884
1885 case MINUS:
1886 return binaryExpression(Types.MINUS, node);
1887
1888 case MINUS_ASSIGN:
1889 return binaryExpression(Types.MINUS_EQUAL, node);
1890
1891
1892 case STAR:
1893 return binaryExpression(Types.MULTIPLY, node);
1894
1895 case STAR_ASSIGN:
1896 return binaryExpression(Types.MULTIPLY_EQUAL, node);
1897
1898
1899 case STAR_STAR:
1900 return binaryExpression(Types.POWER, node);
1901
1902 case STAR_STAR_ASSIGN:
1903 return binaryExpression(Types.POWER_EQUAL, node);
1904
1905
1906 case DIV:
1907 return binaryExpression(Types.DIVIDE, node);
1908
1909 case DIV_ASSIGN:
1910 return binaryExpression(Types.DIVIDE_EQUAL, node);
1911
1912
1913 case MOD:
1914 return binaryExpression(Types.MOD, node);
1915
1916 case MOD_ASSIGN:
1917 return binaryExpression(Types.MOD_EQUAL, node);
1918
1919 case SL:
1920 return binaryExpression(Types.LEFT_SHIFT, node);
1921
1922 case SL_ASSIGN:
1923 return binaryExpression(Types.LEFT_SHIFT_EQUAL, node);
1924
1925 case SR:
1926 return binaryExpression(Types.RIGHT_SHIFT, node);
1927
1928 case SR_ASSIGN:
1929 return binaryExpression(Types.RIGHT_SHIFT_EQUAL, node);
1930
1931 case BSR:
1932 return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED, node);
1933
1934 case BSR_ASSIGN:
1935 return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED_EQUAL, node);
1936
1937 case VARIABLE_DEF:
1938 return declarationExpression(node);
1939
1940
1941 case REGEX_FIND:
1942 return binaryExpression(Types.FIND_REGEX, node);
1943
1944 case REGEX_MATCH:
1945 return binaryExpression(Types.MATCH_REGEX, node);
1946
1947
1948
1949 case RANGE_INCLUSIVE:
1950 return rangeExpression(node, true);
1951
1952 case RANGE_EXCLUSIVE:
1953 return rangeExpression(node, false);
1954
1955 case DYNAMIC_MEMBER:
1956 return dynamicMemberExpression(node);
1957
1958 case LITERAL_in:
1959 return binaryExpression(Types.KEYWORD_IN, node);
1960
1961 case ANNOTATION:
1962 return new AnnotationConstantExpression(annotation(node));
1963
1964 case CLOSURE_LIST:
1965 return closureListExpression(node);
1966
1967 case LBRACK:
1968 case LPAREN:
1969 return tupleExpression(node);
1970
1971 case OBJBLOCK:
1972 return anonymousInnerClassDef(node);
1973
1974 default:
1975 unknownAST(node);
1976 }
1977 return null;
1978 }
1979
1980 private TupleExpression tupleExpression(AST node) {
1981 TupleExpression exp = new TupleExpression();
1982 configureAST(exp, node);
1983 node = node.getFirstChild();
1984 while (node != null) {
1985 assertNodeType(VARIABLE_DEF, node);
1986 AST nameNode = node.getFirstChild().getNextSibling();
1987 VariableExpression varExp = new VariableExpression(nameNode.getText());
1988 configureAST(varExp, nameNode);
1989 exp.addExpression(varExp);
1990 node = node.getNextSibling();
1991 }
1992 return exp;
1993 }
1994
1995 private ClosureListExpression closureListExpression(AST node) {
1996 isClosureListExpressionAllowedHere(node);
1997 AST exprNode = node.getFirstChild();
1998 List<Expression> list = new LinkedList<Expression>();
1999 while (exprNode != null) {
2000 if (isType(EXPR, exprNode)) {
2001 Expression expr = expression(exprNode);
2002 configureAST(expr, exprNode);
2003 list.add(expr);
2004 } else {
2005 assertNodeType(EMPTY_STAT, exprNode);
2006 list.add(EmptyExpression.INSTANCE);
2007 }
2008
2009 exprNode = exprNode.getNextSibling();
2010 }
2011 ClosureListExpression cle = new ClosureListExpression(list);
2012 configureAST(cle, node);
2013 return cle;
2014 }
2015
2016 private void isClosureListExpressionAllowedHere(AST node) {
2017 if (!forStatementBeingDef) {
2018 throw new ASTRuntimeException(node,
2019 "Expression list of the form (a; b; c) is not supported in this context.");
2020 }
2021 }
2022
2023 protected Expression dynamicMemberExpression(AST dynamicMemberNode) {
2024 AST node = dynamicMemberNode.getFirstChild();
2025 return expression(node);
2026 }
2027
2028 protected Expression ternaryExpression(AST ternaryNode) {
2029 AST node = ternaryNode.getFirstChild();
2030 Expression base = expression(node);
2031 node = node.getNextSibling();
2032 Expression left = expression(node);
2033 node = node.getNextSibling();
2034 Expression ret;
2035 if (node == null) {
2036 ret = new ElvisOperatorExpression(base, left);
2037 } else {
2038 Expression right = expression(node);
2039 BooleanExpression booleanExpression = new BooleanExpression(base);
2040 booleanExpression.setSourcePosition(base);
2041 ret = new TernaryExpression(booleanExpression, left, right);
2042 }
2043 configureAST(ret, ternaryNode);
2044 return ret;
2045 }
2046
2047 protected Expression variableExpression(AST node) {
2048 String text = node.getText();
2049
2050
2051
2052 VariableExpression variableExpression = new VariableExpression(text);
2053 configureAST(variableExpression, node);
2054 return variableExpression;
2055 }
2056
2057 protected Expression literalExpression(AST node, Object value) {
2058 ConstantExpression constantExpression = new ConstantExpression(value);
2059 configureAST(constantExpression, node);
2060 return constantExpression;
2061 }
2062
2063 protected Expression rangeExpression(AST rangeNode, boolean inclusive) {
2064 AST node = rangeNode.getFirstChild();
2065 Expression left = expression(node);
2066 Expression right = expression(node.getNextSibling());
2067 RangeExpression rangeExpression = new RangeExpression(left, right, inclusive);
2068 configureAST(rangeExpression, rangeNode);
2069 return rangeExpression;
2070 }
2071
2072 protected Expression spreadExpression(AST node) {
2073 AST exprNode = node.getFirstChild();
2074 AST listNode = exprNode.getFirstChild();
2075 Expression right = expression(listNode);
2076 SpreadExpression spreadExpression = new SpreadExpression(right);
2077 configureAST(spreadExpression, node);
2078 return spreadExpression;
2079 }
2080
2081 protected Expression spreadMapExpression(AST node) {
2082 AST exprNode = node.getFirstChild();
2083 Expression expr = expression(exprNode);
2084 SpreadMapExpression spreadMapExpression = new SpreadMapExpression(expr);
2085 configureAST(spreadMapExpression, node);
2086 return spreadMapExpression;
2087 }
2088
2089 protected Expression methodPointerExpression(AST node) {
2090 AST exprNode = node.getFirstChild();
2091 Expression objectExpression = expression(exprNode);
2092 AST mNode = exprNode.getNextSibling();
2093 Expression methodName;
2094 if (isType(DYNAMIC_MEMBER, mNode)) {
2095 methodName = expression(mNode);
2096 } else {
2097 methodName = new ConstantExpression(identifier(mNode));
2098 }
2099 configureAST(methodName, mNode);
2100 MethodPointerExpression methodPointerExpression = new MethodPointerExpression(objectExpression, methodName);
2101 configureAST(methodPointerExpression, node);
2102 return methodPointerExpression;
2103 }
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115 protected Expression listExpression(AST listNode) {
2116 List<Expression> expressions = new ArrayList<Expression>();
2117 AST elist = listNode.getFirstChild();
2118 assertNodeType(ELIST, elist);
2119
2120 for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
2121
2122 switch (node.getType()) {
2123 case LABELED_ARG:
2124 assertNodeType(COMMA, node);
2125 break;
2126 case SPREAD_MAP_ARG:
2127 assertNodeType(SPREAD_ARG, node);
2128 break;
2129 }
2130 expressions.add(expression(node));
2131 }
2132 ListExpression listExpression = new ListExpression(expressions);
2133 configureAST(listExpression, listNode);
2134 return listExpression;
2135 }
2136
2137
2138
2139
2140 protected Expression mapExpression(AST mapNode) {
2141 List expressions = new ArrayList();
2142 AST elist = mapNode.getFirstChild();
2143 if (elist != null) {
2144 assertNodeType(ELIST, elist);
2145 for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
2146 switch (node.getType()) {
2147 case LABELED_ARG:
2148 case SPREAD_MAP_ARG:
2149 break;
2150 case SPREAD_ARG:
2151 assertNodeType(SPREAD_MAP_ARG, node);
2152 break;
2153 default:
2154 assertNodeType(LABELED_ARG, node);
2155 break;
2156 }
2157 expressions.add(mapEntryExpression(node));
2158 }
2159 }
2160 MapExpression mapExpression = new MapExpression(expressions);
2161 configureAST(mapExpression, mapNode);
2162 return mapExpression;
2163 }
2164
2165 protected MapEntryExpression mapEntryExpression(AST node) {
2166 if (node.getType() == SPREAD_MAP_ARG) {
2167 AST rightNode = node.getFirstChild();
2168 Expression keyExpression = spreadMapExpression(node);
2169 Expression rightExpression = expression(rightNode);
2170 MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, rightExpression);
2171 configureAST(mapEntryExpression, node);
2172 return mapEntryExpression;
2173 } else {
2174 AST keyNode = node.getFirstChild();
2175 Expression keyExpression = expression(keyNode);
2176 AST valueNode = keyNode.getNextSibling();
2177 Expression valueExpression = expression(valueNode);
2178 MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, valueExpression);
2179 configureAST(mapEntryExpression, node);
2180 return mapEntryExpression;
2181 }
2182 }
2183
2184
2185 protected Expression instanceofExpression(AST node) {
2186 AST leftNode = node.getFirstChild();
2187 Expression leftExpression = expression(leftNode);
2188
2189 AST rightNode = leftNode.getNextSibling();
2190 ClassNode type = buildName(rightNode);
2191 assertTypeNotNull(type, rightNode);
2192
2193 Expression rightExpression = new ClassExpression(type);
2194 configureAST(rightExpression, rightNode);
2195 BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.KEYWORD_INSTANCEOF, node), rightExpression);
2196 configureAST(binaryExpression, node);
2197 return binaryExpression;
2198 }
2199
2200 protected void assertTypeNotNull(ClassNode type, AST rightNode) {
2201 if (type == null) {
2202 throw new ASTRuntimeException(rightNode, "No type available for: " + qualifiedName(rightNode));
2203 }
2204 }
2205
2206 protected Expression asExpression(AST node) {
2207 AST leftNode = node.getFirstChild();
2208 Expression leftExpression = expression(leftNode);
2209
2210 AST rightNode = leftNode.getNextSibling();
2211 ClassNode type = makeTypeWithArguments(rightNode);
2212
2213 return CastExpression.asExpression(type, leftExpression);
2214 }
2215
2216 protected Expression castExpression(AST castNode) {
2217 AST node = castNode.getFirstChild();
2218 ClassNode type = makeTypeWithArguments(node);
2219 assertTypeNotNull(type, node);
2220
2221 AST expressionNode = node.getNextSibling();
2222 Expression expression = expression(expressionNode);
2223
2224 CastExpression castExpression = new CastExpression(type, expression);
2225 configureAST(castExpression, castNode);
2226 return castExpression;
2227 }
2228
2229
2230 protected Expression indexExpression(AST indexNode) {
2231 AST bracket = indexNode.getFirstChild();
2232 AST leftNode = bracket.getNextSibling();
2233 Expression leftExpression = expression(leftNode);
2234
2235 AST rightNode = leftNode.getNextSibling();
2236 Expression rightExpression = expression(rightNode);
2237
2238 BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.LEFT_SQUARE_BRACKET, bracket), rightExpression);
2239 configureAST(binaryExpression, indexNode);
2240 return binaryExpression;
2241 }
2242
2243 protected Expression binaryExpression(int type, AST node) {
2244 Token token = makeToken(type, node);
2245
2246 AST leftNode = node.getFirstChild();
2247 Expression leftExpression = expression(leftNode);
2248
2249 AST rightNode = leftNode.getNextSibling();
2250 if (rightNode == null) {
2251 return leftExpression;
2252 }
2253
2254 if (Types.ofType(type, Types.ASSIGNMENT_OPERATOR)) {
2255 if (leftExpression instanceof VariableExpression ||
2256 leftExpression.getClass() == PropertyExpression.class ||
2257 leftExpression instanceof FieldExpression ||
2258 leftExpression instanceof AttributeExpression ||
2259 leftExpression instanceof DeclarationExpression ||
EmptyIfStmt
2261
2262 } else if (leftExpression instanceof ConstantExpression) {
2263 throw new ASTRuntimeException(node, "\n[" + ((ConstantExpression) leftExpression).getValue() + "] is a constant expression, but it should be a variable expression");
2264 } else if (leftExpression instanceof BinaryExpression) {
2265 Expression leftexp = ((BinaryExpression) leftExpression).getLeftExpression();
2266 int lefttype = ((BinaryExpression) leftExpression).getOperation().getType();
2267 if (!Types.ofType(lefttype, Types.ASSIGNMENT_OPERATOR) && lefttype != Types.LEFT_SQUARE_BRACKET) {
2268 throw new ASTRuntimeException(node, "\n" + ((BinaryExpression) leftExpression).getText() + " is a binary expression, but it should be a variable expression");
2269 }
2270 } else if (leftExpression instanceof GStringExpression) {
2271 throw new ASTRuntimeException(node, "\n\"" + ((GStringExpression) leftExpression).getText() + "\" is a GString expression, but it should be a variable expression");
2272 } else if (leftExpression instanceof MethodCallExpression) {
2273 throw new ASTRuntimeException(node, "\n\"" + ((MethodCallExpression) leftExpression).getText() + "\" is a method call expression, but it should be a variable expression");
2274 } else if (leftExpression instanceof MapExpression) {
2275 throw new ASTRuntimeException(node, "\n'" + ((MapExpression) leftExpression).getText() + "' is a map expression, but it should be a variable expression");
2276 } else {
2277 throw new ASTRuntimeException(node, "\n" + leftExpression.getClass() + ", with its value '" + leftExpression.getText() + "', is a bad expression as the left hand side of an assignment operator");
2278 }
2279 }
2280
2281
2282
2283 Expression rightExpression = expression(rightNode);
2284 BinaryExpression binaryExpression = new BinaryExpression(leftExpression, token, rightExpression);
2285 configureAST(binaryExpression, node);
2286 return binaryExpression;
2287 }
2288
2289 protected Expression prefixExpression(AST node, int token) {
2290 Expression expression = expression(node.getFirstChild());
2291 PrefixExpression prefixExpression = new PrefixExpression(makeToken(token, node), expression);
2292 configureAST(prefixExpression, node);
2293 return prefixExpression;
2294 }
2295
2296 protected Expression postfixExpression(AST node, int token) {
2297 Expression expression = expression(node.getFirstChild());
2298 PostfixExpression postfixExpression = new PostfixExpression(expression, makeToken(token, node));
2299 configureAST(postfixExpression, node);
2300 return postfixExpression;
2301 }
2302
2303 protected BooleanExpression booleanExpression(AST node) {
2304 BooleanExpression booleanExpression = new BooleanExpression(expression(node));
2305 configureAST(booleanExpression, node);
2306 return booleanExpression;
2307 }
2308
2309 protected Expression dotExpression(AST node) {
2310
2311 AST leftNode = node.getFirstChild();
2312 if (leftNode != null) {
2313 AST identifierNode = leftNode.getNextSibling();
2314 if (identifierNode != null) {
2315 Expression leftExpression = expression(leftNode);
2316 if (isType(SELECT_SLOT, identifierNode)) {
2317 Expression field = expression(identifierNode.getFirstChild(), true);
2318 AttributeExpression attributeExpression = new AttributeExpression(leftExpression, field, node.getType() != DOT);
2319 if (node.getType() == SPREAD_DOT) {
2320 attributeExpression.setSpreadSafe(true);
2321 }
2322 configureAST(attributeExpression, node);
2323 return attributeExpression;
2324 }
2325 if (isType(SLIST, identifierNode)) {
2326 Statement code = statementList(identifierNode);
2327 ClosureExpression closureExpression = new ClosureExpression(Parameter.EMPTY_ARRAY, code);
2328 configureAST(closureExpression, identifierNode);
2329 final PropertyExpression propertyExpression = new PropertyExpression(leftExpression, closureExpression);
2330 if (node.getType() == SPREAD_DOT) {
2331 propertyExpression.setSpreadSafe(true);
2332 }
2333 configureAST(propertyExpression, node);
2334 return propertyExpression;
2335 }
2336 Expression property = expression(identifierNode, true);
2337
2338
2339
2340
2341 if (property instanceof VariableExpression) {
2342 VariableExpression ve = (VariableExpression) property;
2343 property = new ConstantExpression(ve.getName());
2344 }
2345
2346 PropertyExpression propertyExpression = new PropertyExpression(leftExpression, property, node.getType() != DOT);
2347 if (node.getType() == SPREAD_DOT) {
2348 propertyExpression.setSpreadSafe(true);
2349 }
2350 configureAST(propertyExpression, node);
2351 return propertyExpression;
2352 }
2353 }
2354 return methodCallExpression(node);
2355 }
2356
2357 protected Expression specialConstructorCallExpression(AST methodCallNode, ClassNode special) {
2358 AST node = methodCallNode.getFirstChild();
2359 Expression arguments = arguments(node);
2360
2361 ConstructorCallExpression expression = new ConstructorCallExpression(special, arguments);
2362 configureAST(expression, methodCallNode);
2363 return expression;
2364 }
2365
2366 private int getTypeInParenthesis(AST node) {
2367 if (!isType(EXPR, node)) node = node.getFirstChild();
2368 while (node != null && isType(EXPR, node) && node.getNextSibling() == null) {
2369 node = node.getFirstChild();
2370 }
2371 if (node == null) return -1;
2372 return node.getType();
2373 }
2374
2375 protected Expression methodCallExpression(AST methodCallNode) {
2376 AST node = methodCallNode.getFirstChild();
2377 Expression objectExpression;
2378 AST selector;
2379 AST elist = node.getNextSibling();
2380 List<GenericsType> typeArgumentList = null;
2381
2382 boolean implicitThis = false;
2383 boolean safe = isType(OPTIONAL_DOT, node);
2384 boolean spreadSafe = isType(SPREAD_DOT, node);
2385 if (isType(DOT, node) || safe || spreadSafe) {
2386 AST objectNode = node.getFirstChild();
2387 objectExpression = expression(objectNode);
2388 selector = objectNode.getNextSibling();
2389 } else {
2390 implicitThis = true;
2391 objectExpression = VariableExpression.THIS_EXPRESSION;
2392 selector = node;
2393 }
2394
2395 if (isType(TYPE_ARGUMENTS, selector)) {
2396 typeArgumentList = getTypeArgumentsList(selector);
2397 selector = selector.getNextSibling();
2398 }
2399
2400 Expression name = null;
2401 if (isType(LITERAL_super, selector)) {
2402 implicitThis = true;
2403 name = new ConstantExpression("super");
2404 if (objectExpression instanceof VariableExpression && ((VariableExpression) objectExpression).isThisExpression()) {
2405 objectExpression = VariableExpression.SUPER_EXPRESSION;
2406 }
2407 } else if (isPrimitiveTypeLiteral(selector)) {
2408 throw new ASTRuntimeException(selector, "Primitive type literal: " + selector.getText()
2409 + " cannot be used as a method name");
2410 } else if (isType(SELECT_SLOT, selector)) {
2411 Expression field = expression(selector.getFirstChild(), true);
2412 AttributeExpression attributeExpression = new AttributeExpression(objectExpression, field, node.getType() != DOT);
2413 configureAST(attributeExpression, node);
2414 Expression arguments = arguments(elist);
2415 MethodCallExpression expression = new MethodCallExpression(attributeExpression, "call", arguments);
2416 setTypeArgumentsOnMethodCallExpression(expression, typeArgumentList);
2417 configureAST(expression, methodCallNode);
2418 return expression;
2419 } else if (!implicitThis || isType(DYNAMIC_MEMBER, selector) || isType(IDENT, selector) ||
2420 isType(STRING_CONSTRUCTOR, selector) || isType(STRING_LITERAL, selector)) {
2421 name = expression(selector, true);
2422 } else {
2423 implicitThis = false;
2424 name = new ConstantExpression("call");
2425 objectExpression = expression(selector, true);
2426 }
2427
2428
2429
2430 if (selector.getText().equals("this") || selector.getText().equals("super")) {
2431 throw new ASTRuntimeException(elist, "Constructor call must be the first statement in a constructor.");
2432 }
2433
2434 Expression arguments = arguments(elist);
2435 MethodCallExpression expression = new MethodCallExpression(objectExpression, name, arguments);
2436 expression.setSafe(safe);
2437 expression.setSpreadSafe(spreadSafe);
2438 expression.setImplicitThis(implicitThis);
2439 setTypeArgumentsOnMethodCallExpression(expression, typeArgumentList);
2440 Expression ret = expression;
2441
2442
2443
2444
2445 if (implicitThis && "this".equals(expression.getMethodAsString())) {
2446 ret = new ConstructorCallExpression(this.classNode, arguments);
2447 }
2448 configureAST(ret, methodCallNode);
2449 return ret;
2450 }
2451
2452 private void setTypeArgumentsOnMethodCallExpression(MethodCallExpression expression,
2453 List<GenericsType> typeArgumentList) {
2454 if (typeArgumentList != null && typeArgumentList.size() > 0) {
2455 expression.setGenericsTypes(typeArgumentList.toArray(new GenericsType[typeArgumentList.size()]));
2456 }
2457 }
2458
2459 protected Expression constructorCallExpression(AST node) {
2460 AST constructorCallNode = node;
2461 ClassNode type = makeTypeWithArguments(constructorCallNode);
2462
2463 if (isType(CTOR_CALL, node) || isType(LITERAL_new, node)) {
2464 node = node.getFirstChild();
2465 }
2466
2467 AST elist = node.getNextSibling();
2468
2469 if (elist == null && isType(ELIST, node)) {
2470 elist = node;
2471 if ("(".equals(type.getName())) {
2472 type = classNode;
2473 }
2474 }
2475
2476 if (isType(ARRAY_DECLARATOR, elist)) {
2477 AST expressionNode = elist.getFirstChild();
2478 if (expressionNode == null) {
2479 throw new ASTRuntimeException(elist, "No expression for the array constructor call");
2480 }
2481 List size = arraySizeExpression(expressionNode);
2482 ArrayExpression arrayExpression = new ArrayExpression(type, null, size);
2483 configureAST(arrayExpression, constructorCallNode);
2484 return arrayExpression;
2485 }
2486 Expression arguments = arguments(elist);
2487 ClassNode innerClass = getAnonymousInnerClassNode(arguments);
2488 ConstructorCallExpression ret = new ConstructorCallExpression(type, arguments);
2489 if (innerClass != null) {
2490 ret.setType(innerClass);
2491 ret.setUsingAnonymousInnerClass(true);
2492 innerClass.setUnresolvedSuperClass(type);
2493 }
2494
2495 configureAST(ret, constructorCallNode);
2496 return ret;
2497 }
2498
2499 private ClassNode getAnonymousInnerClassNode(Expression arguments) {
2500 if (arguments instanceof TupleExpression) {
2501 TupleExpression te = (TupleExpression) arguments;
2502 List<Expression> expressions = te.getExpressions();
2503 if (expressions.size() == 0) return null;
2504 Expression last = (Expression) expressions.remove(expressions.size() - 1);
2505 if (last instanceof AnonymousInnerClassCarrier) {
2506 AnonymousInnerClassCarrier carrier = (AnonymousInnerClassCarrier) last;
2507 return carrier.innerClass;
2508 } else {
2509 expressions.add(last);
2510 }
2511 } else if (arguments instanceof AnonymousInnerClassCarrier) {
2512 AnonymousInnerClassCarrier carrier = (AnonymousInnerClassCarrier) arguments;
2513 return carrier.innerClass;
2514 }
2515 return null;
2516 }
2517
2518 protected List arraySizeExpression(AST node) {
2519 List list;
2520 Expression size = null;
2521 if (isType(ARRAY_DECLARATOR, node)) {
2522 AST right = node.getNextSibling();
2523 if (right != null) {
2524 size = expression(right);
2525 } else {
2526 size = ConstantExpression.EMPTY_EXPRESSION;
2527 }
2528 list = arraySizeExpression(node.getFirstChild());
2529 } else {
2530 size = expression(node);
2531 list = new ArrayList();
2532 }
2533 list.add(size);
2534 return list;
2535 }
2536
2537 protected Expression arguments(AST elist) {
2538 List expressionList = new ArrayList();
2539
2540 boolean namedArguments = false;
IL_INFINITE_LOOP
2542 if (isType(ELIST, node)) {
2543 for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
2544 namedArguments |= addArgumentExpression(child, expressionList);
2545 }
2546 } else {
2547 namedArguments |= addArgumentExpression(node, expressionList);
2548 }
2549 }
2550 if (namedArguments) {
2551 if (!expressionList.isEmpty()) {
2552
2553
2554
2555 List<Expression> argumentList = new ArrayList<Expression>();
2556 for (Object next : expressionList) {
2557 Expression expression = (Expression) next;
2558 if (!(expression instanceof MapEntryExpression)) {
2559 argumentList.add(expression);
2560 }
2561 }
2562 if (!argumentList.isEmpty()) {
2563 expressionList.removeAll(argumentList);
2564 checkDuplicateNamedParams(elist, expressionList);
2565 MapExpression mapExpression = new MapExpression(expressionList);
2566 configureAST(mapExpression, elist);
2567 argumentList.add(0, mapExpression);
2568 ArgumentListExpression argumentListExpression = new ArgumentListExpression(argumentList);
2569 configureAST(argumentListExpression, elist);
2570 return argumentListExpression;
2571 }
2572 }
2573 checkDuplicateNamedParams(elist, expressionList);
2574 NamedArgumentListExpression namedArgumentListExpression = new NamedArgumentListExpression(expressionList);
2575 configureAST(namedArgumentListExpression, elist);
2576 return namedArgumentListExpression;
2577 } else {
2578 ArgumentListExpression argumentListExpression = new ArgumentListExpression(expressionList);
2579 configureAST(argumentListExpression, elist);
2580 return argumentListExpression;
2581 }
2582 }
2583
2584 private void checkDuplicateNamedParams(AST elist, List expressionList) {
2585 if (expressionList.isEmpty()) return;
2586
2587 Set<String> namedArgumentNames = new HashSet<String>();
2588 for (Object expression : expressionList) {
2589 MapEntryExpression meExp = (MapEntryExpression) expression;
2590 if (meExp.getKeyExpression() instanceof ConstantExpression) {
2591 String argName = meExp.getKeyExpression().getText();
2592 if (!namedArgumentNames.contains(argName)) {
2593 namedArgumentNames.add(argName);
2594 } else {
2595 throw new ASTRuntimeException(elist, "Duplicate named parameter '" + argName
2596 + "' found.");
2597 }
2598 }
2599 }
2600 }
2601
2602 protected boolean addArgumentExpression(AST node, List<Expression> expressionList) {
2603 if (node.getType() == SPREAD_MAP_ARG) {
2604 AST rightNode = node.getFirstChild();
2605 Expression keyExpression = spreadMapExpression(node);
2606 Expression rightExpression = expression(rightNode);
2607 MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, rightExpression);
2608 expressionList.add(mapEntryExpression);
2609 return true;
2610 } else {
2611 Expression expression = expression(node);
2612 expressionList.add(expression);
2613 return expression instanceof MapEntryExpression;
2614 }
2615 }
2616
2617 protected Expression expressionList(AST node) {
2618 List<Expression> expressionList = new ArrayList<Expression>();
2619 for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
2620 expressionList.add(expression(child));
2621 }
2622 if (expressionList.size() == 1) {
2623 return expressionList.get(0);
2624 } else {
2625 ListExpression listExpression = new ListExpression(expressionList);
2626 listExpression.setWrapped(true);
2627 configureAST(listExpression, node);
2628 return listExpression;
2629 }
2630 }
2631
2632 protected ClosureExpression closureExpression(AST node) {
2633 AST paramNode = node.getFirstChild();
2634 Parameter[] parameters = null;
2635 AST codeNode = paramNode;
2636 if (isType(PARAMETERS, paramNode) || isType(IMPLICIT_PARAMETERS, paramNode)) {
2637 parameters = parameters(paramNode);
2638 codeNode = paramNode.getNextSibling();
2639 }
2640 Statement code = statementListNoChild(codeNode, node);
2641 ClosureExpression closureExpression = new ClosureExpression(parameters, code);
2642 configureAST(closureExpression, node);
2643 return closureExpression;
2644 }
2645
2646 protected Expression blockExpression(AST node) {
2647 AST codeNode = node.getFirstChild();
2648 if (codeNode == null) return ConstantExpression.NULL;
2649 if (codeNode.getType() == EXPR && codeNode.getNextSibling() == null) {
2650
2651 return expression(codeNode);
2652 }
2653 Parameter[] parameters = Parameter.EMPTY_ARRAY;
2654 Statement code = statementListNoChild(codeNode, node);
2655 ClosureExpression closureExpression = new ClosureExpression(parameters, code);
2656 configureAST(closureExpression, node);
2657
2658 String callName = "call";
2659 Expression noArguments = new ArgumentListExpression();
2660 MethodCallExpression call = new MethodCallExpression(closureExpression, callName, noArguments);
2661 configureAST(call, node);
2662 return call;
2663 }
2664
2665 protected Expression unaryMinusExpression(AST unaryMinusExpr) {
2666 AST node = unaryMinusExpr.getFirstChild();
2667
2668
2669
2670 String text = node.getText();
2671 switch (node.getType()) {
2672 case NUM_DOUBLE:
2673 case NUM_FLOAT:
2674 case NUM_BIG_DECIMAL:
2675 ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal("-" + text));
2676 configureAST(constantExpression, unaryMinusExpr);
2677 return constantExpression;
2678
2679 case NUM_BIG_INT:
2680 case NUM_INT:
2681 case NUM_LONG:
2682 ConstantExpression constantLongExpression = new ConstantExpression(Numbers.parseInteger("-" + text));
2683 configureAST(constantLongExpression, unaryMinusExpr);
2684 return constantLongExpression;
2685
2686 default:
2687 UnaryMinusExpression unaryMinusExpression = new UnaryMinusExpression(expression(node));
2688 configureAST(unaryMinusExpression, unaryMinusExpr);
2689 return unaryMinusExpression;
2690 }
2691 }
2692
2693 protected Expression unaryPlusExpression(AST unaryPlusExpr) {
2694 AST node = unaryPlusExpr.getFirstChild();
2695 switch (node.getType()) {
2696 case NUM_DOUBLE:
2697 case NUM_FLOAT:
2698 case NUM_BIG_DECIMAL:
2699 case NUM_BIG_INT:
2700 case NUM_INT:
2701 case NUM_LONG:
2702 return expression(node);
2703
2704 default:
2705 UnaryPlusExpression unaryPlusExpression = new UnaryPlusExpression(expression(node));
2706 configureAST(unaryPlusExpression, unaryPlusExpr);
2707 return unaryPlusExpression;
2708 }
2709 }
2710
2711 protected ConstantExpression decimalExpression(AST node) {
2712 String text = node.getText();
2713 ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal(text));
2714 configureAST(constantExpression, node);
2715 return constantExpression;
2716 }
2717
2718 protected ConstantExpression integerExpression(AST node) {
2719 String text = node.getText();
2720 Object number = Numbers.parseInteger(text);
2721 ConstantExpression constantExpression = new ConstantExpression(number, number instanceof Integer);
2722 configureAST(constantExpression, node);
2723 return constantExpression;
2724 }
2725
2726 protected Expression gstring(AST gstringNode) {
2727 List strings = new ArrayList();
2728 List values = new ArrayList();
2729
2730 StringBuffer buffer = new StringBuffer();
2731
2732 boolean isPrevString = false;
2733
2734 for (AST node = gstringNode.getFirstChild(); node != null; node = node.getNextSibling()) {
2735 int type = node.getType();
2736 String text = null;
2737 switch (type) {
2738
2739 case STRING_LITERAL:
2740 if (isPrevString) assertNodeType(IDENT, node);
2741 isPrevString = true;
2742 text = node.getText();
2743 ConstantExpression constantExpression = new ConstantExpression(text);
2744 configureAST(constantExpression, node);
2745 strings.add(constantExpression);
2746 buffer.append(text);
2747 break;
2748
2749 default: {
2750 if (!isPrevString) assertNodeType(IDENT, node);
2751 isPrevString = false;
2752 Expression expression = expression(node);
2753 values.add(expression);
2754 buffer.append("$");
2755 buffer.append(expression.getText());
2756 }
2757 break;
2758 }
2759 }
2760 GStringExpression gStringExpression = new GStringExpression(buffer.toString(), strings, values);
2761 configureAST(gStringExpression, gstringNode);
2762 return gStringExpression;
2763 }
2764
2765 protected ClassNode type(AST typeNode) {
2766
2767
2768 return buildName(typeNode.getFirstChild());
2769 }
2770
2771 public static String qualifiedName(AST qualifiedNameNode) {
2772 if (isType(IDENT, qualifiedNameNode)) {
2773 return qualifiedNameNode.getText();
2774 }
2775 if (isType(DOT, qualifiedNameNode)) {
2776 AST node = qualifiedNameNode.getFirstChild();
2777 StringBuffer buffer = new StringBuffer();
2778 boolean first = true;
2779
2780 for (; node != null && !isType(TYPE_ARGUMENTS, node); node = node.getNextSibling()) {
2781 if (first) {
2782 first = false;
2783 } else {
2784 buffer.append(".");
2785 }
2786 buffer.append(qualifiedName(node));
2787 }
2788 return buffer.toString();
2789 } else {
2790 return qualifiedNameNode.getText();
2791 }
2792 }
2793
2794 private static AST getTypeArgumentsNode(AST root) {
2795 while (root != null && !isType(TYPE_ARGUMENTS, root)) {
2796 root = root.getNextSibling();
2797 }
2798 return root;
2799 }
2800
2801 private int getBoundType(AST node) {
2802 if (node == null) return -1;
2803 if (isType(TYPE_UPPER_BOUNDS, node)) return TYPE_UPPER_BOUNDS;
2804 if (isType(TYPE_LOWER_BOUNDS, node)) return TYPE_LOWER_BOUNDS;
2805 throw new ASTRuntimeException(node,
2806 "Unexpected node type: " + getTokenName(node) +
2807 " found when expecting type: " + getTokenName(TYPE_UPPER_BOUNDS) +
2808 " or type: " + getTokenName(TYPE_LOWER_BOUNDS));
2809 }
2810
2811 private GenericsType makeGenericsArgumentType(AST typeArgument) {
2812 GenericsType gt;
2813 AST rootNode = typeArgument.getFirstChild();
2814 if (isType(WILDCARD_TYPE, rootNode)) {
2815 ClassNode base = ClassHelper.makeWithoutCaching("?");
2816 if (rootNode.getNextSibling() != null) {
2817 int boundType = getBoundType(rootNode.getNextSibling());
2818 ClassNode[] gts = makeGenericsBounds(rootNode, boundType);
2819 if (boundType == TYPE_UPPER_BOUNDS) {
2820 gt = new GenericsType(base, gts, null);
2821 } else {
2822 gt = new GenericsType(base, null, gts[0]);
2823 }
2824 } else {
2825 gt = new GenericsType(base, null, null);
2826 }
2827 gt.setName("?");
2828 gt.setWildcard(true);
2829 } else {
2830 ClassNode argument = makeTypeWithArguments(rootNode);
2831 gt = new GenericsType(argument);
2832 }
2833 configureAST(gt, typeArgument);
2834 return gt;
2835 }
2836
2837 protected ClassNode makeTypeWithArguments(AST rootNode) {
2838 ClassNode basicType = makeType(rootNode);
2839 AST node = rootNode.getFirstChild();
2840 if (node == null || isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) return basicType;
2841
2842 if (!isType(DOT, node)) {
2843 node = node.getFirstChild();
2844 if (node == null) return basicType;
2845 return addTypeArguments(basicType, node);
2846 } else {
2847 node = node.getFirstChild();
WhileLoopsMustUseBraces
2849 node = node.getNextSibling();
2850 return node == null ? basicType : addTypeArguments(basicType, node);
2851 }
2852 }
2853
2854 private ClassNode addTypeArguments(ClassNode basicType, AST node) {
2855 List<GenericsType> typeArgumentList = getTypeArgumentsList(node);
2856 if (typeArgumentList.size() > 0) {
2857 basicType.setGenericsTypes(typeArgumentList.toArray(new GenericsType[typeArgumentList.size()]));
2858 }
2859 return basicType;
2860 }
2861
2862 private List<GenericsType> getTypeArgumentsList(AST node) {
2863 assertNodeType(TYPE_ARGUMENTS, node);
2864 List<GenericsType> typeArgumentList = new LinkedList<GenericsType>();
2865 AST typeArgument = node.getFirstChild();
2866
2867 while (typeArgument != null) {
2868 assertNodeType(TYPE_ARGUMENT, typeArgument);
2869 GenericsType gt = makeGenericsArgumentType(typeArgument);
2870 typeArgumentList.add(gt);
2871 typeArgument = typeArgument.getNextSibling();
2872 }
2873 return typeArgumentList;
2874 }
2875
2876 private ClassNode[] makeGenericsBounds(AST rn, int boundType) {
2877 AST boundsRoot = rn.getNextSibling();
2878 if (boundsRoot == null) return null;
2879 assertNodeType(boundType, boundsRoot);
2880 LinkedList bounds = new LinkedList();
2881 for (AST boundsNode = boundsRoot.getFirstChild();
2882 boundsNode != null;
2883 boundsNode = boundsNode.getNextSibling()
2884 ) {
2885 ClassNode bound = null;
2886 bound = makeTypeWithArguments(boundsNode);
2887 configureAST(bound, boundsNode);
2888 bounds.add(bound);
2889 }
2890 if (bounds.size() == 0) return null;
2891 return (ClassNode[]) bounds.toArray(new ClassNode[bounds.size()]);
2892 }
2893
2894 protected GenericsType[] makeGenericsType(AST rootNode) {
2895 AST typeParameter = rootNode.getFirstChild();
2896 LinkedList ret = new LinkedList();
2897 assertNodeType(TYPE_PARAMETER, typeParameter);
2898
2899 while (isType(TYPE_PARAMETER, typeParameter)) {
2900 AST typeNode = typeParameter.getFirstChild();
2901 ClassNode type = makeType(typeParameter);
2902
2903 GenericsType gt = new GenericsType(type, makeGenericsBounds(typeNode, TYPE_UPPER_BOUNDS), null);
2904 configureAST(gt, typeParameter);
2905
2906 ret.add(gt);
2907 typeParameter = typeParameter.getNextSibling();
2908 }
2909 return (GenericsType[]) ret.toArray(new GenericsType[0]);
2910 }
2911
2912 protected ClassNode makeType(AST typeNode) {
2913 ClassNode answer = ClassHelper.DYNAMIC_TYPE;
2914 AST node = typeNode.getFirstChild();
2915 if (node != null) {
2916 if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
2917 answer = makeType(node).makeArray();
2918 } else {
2919 answer = ClassHelper.make(qualifiedName(node));
2920 if (answer.isUsingGenerics()) {
2921 ClassNode newAnswer = ClassHelper.makeWithoutCaching(answer.getName());
2922 newAnswer.setRedirect(answer);
2923 answer = newAnswer;
2924 }
2925 }
2926 configureAST(answer, node);
2927 }
2928 return answer;
2929 }
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946 protected ClassNode buildName(AST node) {
2947 if (isType(TYPE, node)) {
2948 node = node.getFirstChild();
2949 }
2950 ClassNode answer = null;
2951 if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
2952 answer = ClassHelper.make(qualifiedName(node));
2953 } else if (isPrimitiveTypeLiteral(node)) {
2954 answer = ClassHelper.make(node.getText());
2955 } else if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
2956 AST child = node.getFirstChild();
2957 answer = buildName(child).makeArray();
2958 configureAST(answer, node);
2959 return answer;
2960 } else {
2961 String identifier = node.getText();
2962 answer = ClassHelper.make(identifier);
2963 }
2964 AST nextSibling = node.getNextSibling();
2965 if (isType(INDEX_OP, nextSibling) || isType(ARRAY_DECLARATOR, node)) {
2966 answer = answer.makeArray();
2967 configureAST(answer, node);
2968 return answer;
2969 } else {
2970 configureAST(answer, node);
2971 return answer;
2972 }
2973 }
2974
2975 protected boolean isPrimitiveTypeLiteral(AST node) {
2976 int type = node.getType();
2977 switch (type) {
2978 case LITERAL_boolean:
2979 case LITERAL_byte:
2980 case LITERAL_char:
2981 case LITERAL_double:
2982 case LITERAL_float:
2983 case LITERAL_int:
2984 case LITERAL_long:
2985 case LITERAL_short:
2986 return true;
2987
2988 default:
2989 return false;
2990 }
2991 }
2992
2993
2994
2995
2996 protected String identifier(AST node) {
2997 assertNodeType(IDENT, node);
2998 return node.getText();
2999 }
3000
3001 protected String label(AST labelNode) {
3002 AST node = labelNode.getFirstChild();
3003 if (node == null) {
3004 return null;
3005 }
3006 return identifier(node);
3007 }
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017 protected boolean hasVisibility(int modifiers) {
3018 return (modifiers & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) != 0;
3019 }
3020
3021 protected void configureAST(ASTNode node, AST ast) {
3022 if (ast == null)
3023 throw new ASTRuntimeException(ast, "PARSER BUG: Tried to configure " + node.getClass().getName() + " with null Node");
3024 node.setColumnNumber(ast.getColumn());
3025 node.setLineNumber(ast.getLine());
3026 if (ast instanceof GroovySourceAST) {
3027 node.setLastColumnNumber(((GroovySourceAST) ast).getColumnLast());
3028 node.setLastLineNumber(((GroovySourceAST) ast).getLineLast());
3029 }
3030
3031
3032
3033 }
3034
3035 protected static Token makeToken(int typeCode, AST node) {
3036 return Token.newSymbol(typeCode, node.getLine(), node.getColumn());
3037 }
3038
3039 protected String getFirstChildText(AST node) {
3040 AST child = node.getFirstChild();
3041 return child != null ? child.getText() : null;
3042 }
3043
3044
3045 public static boolean isType(int typeCode, AST node) {
3046 return node != null && node.getType() == typeCode;
3047 }
3048
3049 private String getTokenName(int token) {
3050 if (tokenNames == null) return "" + token;
3051 return tokenNames[token];
3052 }
3053
3054 private String getTokenName(AST node) {
3055 if (node == null) return "null";
3056 return getTokenName(node.getType());
3057 }
3058
3059 protected void assertNodeType(int type, AST node) {
3060 if (node == null) {
3061 throw new ASTRuntimeException(node, "No child node available in AST when expecting type: " + getTokenName(type));
3062 }
3063 if (node.getType() != type) {
3064 throw new ASTRuntimeException(node, "Unexpected node type: " + getTokenName(node) + " found when expecting type: " + getTokenName(type));
3065 }
3066 }
3067
3068 protected void notImplementedYet(AST node) {
3069 throw new ASTRuntimeException(node, "AST node not implemented yet for type: " + getTokenName(node));
3070 }
3071
3072 protected void unknownAST(AST node) {
3073 if (node.getType() == CLASS_DEF) {
3074 throw new ASTRuntimeException(node,
3075 "Class definition not expected here. Please define the class at an appropriate place or perhaps try using a block/Closure instead.");
3076 }
3077 if (node.getType() == METHOD_DEF) {
3078 throw new ASTRuntimeException(node,
3079 "Method definition not expected here. Please define the method at an appropriate place or perhaps try using a block/Closure instead.");
3080 }
3081 throw new ASTRuntimeException(node, "Unknown type: " + getTokenName(node));
3082 }
3083
3084 protected void dumpTree(AST ast) {
3085 for (AST node = ast.getFirstChild(); node != null; node = node.getNextSibling()) {
3086 dump(node);
3087 }
3088 }
3089
3090 protected void dump(AST node) {
SystemPrintln
3092 }
3093 }