1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package org.codehaus.groovy.control;
35
36 import groovy.lang.GroovyClassLoader;
37
38 import java.io.IOException;
39 import java.io.File;
40 import java.lang.reflect.Field;
41 import java.util.HashMap;
42 import java.util.Iterator;
43 import java.util.LinkedList;
44 import java.util.List;
45 import java.util.Map;
46 import java.net.URL;
47 import java.net.MalformedURLException;
48
49 import org.codehaus.groovy.ast.ASTNode;
50 import org.codehaus.groovy.ast.AnnotatedNode;
51 import org.codehaus.groovy.ast.AnnotationNode;
52 import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
53 import org.codehaus.groovy.ast.ClassHelper;
54 import org.codehaus.groovy.ast.ClassNode;
55 import org.codehaus.groovy.ast.CodeVisitorSupport;
56 import org.codehaus.groovy.ast.CompileUnit;
57 import org.codehaus.groovy.ast.ConstructorNode;
58 import org.codehaus.groovy.ast.DynamicVariable;
59 import org.codehaus.groovy.ast.FieldNode;
60 import org.codehaus.groovy.ast.ImportNode;
61 import org.codehaus.groovy.ast.MethodNode;
62 import org.codehaus.groovy.ast.ModuleNode;
63 import org.codehaus.groovy.ast.Parameter;
64 import org.codehaus.groovy.ast.PropertyNode;
65 import org.codehaus.groovy.ast.Variable;
66 import org.codehaus.groovy.ast.VariableScope;
67 import org.codehaus.groovy.ast.expr.BinaryExpression;
68 import org.codehaus.groovy.ast.expr.BooleanExpression;
69 import org.codehaus.groovy.ast.expr.ClassExpression;
70 import org.codehaus.groovy.ast.expr.ClosureExpression;
71 import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
72 import org.codehaus.groovy.ast.expr.DeclarationExpression;
73 import org.codehaus.groovy.ast.expr.Expression;
74 import org.codehaus.groovy.ast.expr.ExpressionTransformer;
75 import org.codehaus.groovy.ast.expr.MethodCallExpression;
76 import org.codehaus.groovy.ast.expr.PropertyExpression;
77 import org.codehaus.groovy.ast.expr.VariableExpression;
78 import org.codehaus.groovy.ast.stmt.AssertStatement;
79 import org.codehaus.groovy.ast.stmt.BlockStatement;
80 import org.codehaus.groovy.ast.stmt.CaseStatement;
81 import org.codehaus.groovy.ast.stmt.CatchStatement;
82 import org.codehaus.groovy.ast.stmt.DoWhileStatement;
83 import org.codehaus.groovy.ast.stmt.ExpressionStatement;
84 import org.codehaus.groovy.ast.stmt.ForStatement;
85 import org.codehaus.groovy.ast.stmt.IfStatement;
86 import org.codehaus.groovy.ast.stmt.ReturnStatement;
87 import org.codehaus.groovy.ast.stmt.Statement;
88 import org.codehaus.groovy.ast.stmt.SwitchStatement;
89 import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
90 import org.codehaus.groovy.ast.stmt.ThrowStatement;
91 import org.codehaus.groovy.ast.stmt.WhileStatement;
92 import org.codehaus.groovy.ast.GroovyClassVisitor;
93 import org.codehaus.groovy.classgen.Verifier;
94 import org.codehaus.groovy.control.messages.ExceptionMessage;
95 import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
96 import org.codehaus.groovy.syntax.SyntaxException;
97 import org.codehaus.groovy.syntax.Types;
98
99 /***
100 * Visitor to resolve Types and convert VariableExpression to
101 * ClassExpressions if needed.
102 *
103 * Note: the method to start the resolving is startResolving(ClassNode, SourceUnit).
104 *
105 *
106 * @author Jochen Theodorou
107 */
108 public class ResolveVisitor extends ClassCodeVisitorSupport implements ExpressionTransformer {
109 private ClassNode currentClass;
110
111 private static final String[] DEFAULT_IMPORTS = {"java.lang.", "java.io.", "java.net.", "java.util.", "groovy.lang.", "groovy.util."};
112 private CompilationUnit compilationUnit;
113 private Map cachedClasses = new HashMap();
114 private static final Object NO_CLASS = new Object();
115 private static final Object SCRIPT = new Object();
116 private SourceUnit source;
117 private VariableScope currentScope;
118
119 private boolean isTopLevelProperty = true;
120
121 public ResolveVisitor(CompilationUnit cu) {
122 compilationUnit = cu;
123 }
124
125 public void startResolving(ClassNode node,SourceUnit source) {
126 this.source = source;
127 visitClass(node);
128 }
129
130 public void visitConstructor(ConstructorNode node) {
131 VariableScope oldScope = currentScope;
132 currentScope = node.getVariableScope();
133 Parameter[] paras = node.getParameters();
134 for (int i=0; i<paras.length; i++) {
135 ClassNode t = paras[i].getType();
136 resolveOrFail(t,node);
137 }
138 ClassNode[] exceptions = node.getExceptions();
139 for (int i=0; i<exceptions.length; i++) {
140 ClassNode t = exceptions[i];
141 resolveOrFail(t,node);
142 }
143 Statement code = node.getCode();
144 if (code!=null) code.visit(this);
145 currentScope = oldScope;
146 }
147
148 public void visitSwitch(SwitchStatement statement) {
149 Expression exp = statement.getExpression();
150 statement.setExpression(transform(exp));
151 List list = statement.getCaseStatements();
152 for (Iterator iter = list.iterator(); iter.hasNext(); ) {
153 CaseStatement caseStatement = (CaseStatement) iter.next();
154 caseStatement.visit(this);
155 }
156 statement.getDefaultStatement().visit(this);
157 }
158
159 public void visitMethod(MethodNode node) {
160 VariableScope oldScope = currentScope;
161 currentScope = node.getVariableScope();
162 Parameter[] paras = node.getParameters();
163 for (int i=0; i<paras.length; i++) {
164 ClassNode t = paras[i].getType();
165 resolveOrFail(t,node);
166 if (paras[i].hasInitialExpression()) {
167 Expression init = paras[i].getInitialExpression();
168 paras[i].setInitialExpression(transform(init));
169 }
170 }
171 ClassNode[] exceptions = node.getExceptions();
172 for (int i=0; i<exceptions.length; i++) {
173 ClassNode t = exceptions[i];
174 resolveOrFail(t,node);
175 }
176 resolveOrFail(node.getReturnType(),node);
177 Statement code = node.getCode();
178 if (code!=null) code.visit(this);
179 currentScope = oldScope;
180 }
181
182 public void visitField(FieldNode node) {
183 ClassNode t = node.getType();
184 resolveOrFail(t,node);
185 Expression init = node.getInitialExpression();
186 node.setInitialValueExpression(transform(init));
187 }
188
189 public void visitProperty(PropertyNode node) {
190 ClassNode t = node.getType();
191 resolveOrFail(t,node);
192 Statement code = node.getGetterBlock();
193 if (code!=null) code.visit(this);
194 code = node.getSetterBlock();
195 if (code!=null) code.visit(this);
196 }
197
198 public void visitIfElse(IfStatement ifElse) {
199 ifElse.setBooleanExpression((BooleanExpression) (transform(ifElse.getBooleanExpression())));
200 super.visitIfElse(ifElse);
201 }
202
203 private void resolveOrFail(ClassNode type, String msg, ASTNode node) {
204 if (resolve(type)) return;
205 addError("unable to resolve class "+type.getName()+" "+msg,node);
206 }
207
208 private void resolveOrFail(ClassNode type, ASTNode node, boolean prefereImports) {
209 if (prefereImports && resolveAliasFromModule(type)) return;
210 resolveOrFail(type,node);
211 }
212
213 private void resolveOrFail(ClassNode type, ASTNode node) {
214 resolveOrFail(type,"",node);
215 }
216
217 private boolean resolve(ClassNode type) {
218 String name = type.getName();
219 return resolve(type,true,true,true);
220 }
221
222 private boolean resolve(ClassNode type, boolean testModuleImports, boolean testDefaultImports, boolean testStaticInnerClasses) {
223 if (type.isResolved()) return true;
224 if (type.isArray()) {
225 ClassNode element = type.getComponentType();
226 boolean resolved = resolve(element,testModuleImports,testDefaultImports,testStaticInnerClasses);
227 if (resolved) {
228 ClassNode cn = element.makeArray();
229 type.setRedirect(cn);
230 }
231 return resolved;
232 }
233
234
235 if (currentClass==type) return true;
236 if (currentClass.getNameWithoutPackage().equals(type.getName())) {
237 type.setRedirect(currentClass);
238 return true;
239 }
240
241 return resolveFromModule(type,testModuleImports) ||
242 resolveFromCompileUnit(type) ||
243 resovleFromDefaultImports(type,testDefaultImports) ||
244 resolveFromStaticInnerClasses(type,testStaticInnerClasses) ||
245 resolveFromClassCache(type) ||
246 resolveToClass(type) ||
247 resolveToScript(type);
248
249 }
250
251 private boolean resolveFromClassCache(ClassNode type) {
252 String name = type.getName();
253 Object val = cachedClasses.get(name);
254 if (val==null || val==NO_CLASS){
255 return false;
256 } else {
257 setClass(type,(Class) val);
258 return true;
259 }
260 }
261
262
263 private long getTimeStamp(Class cls) {
264 Field field;
265 Long o;
266 try {
267 field = cls.getField(Verifier.__TIMESTAMP);
268 o = (Long) field.get(null);
269 } catch (Exception e) {
270 return Long.MAX_VALUE;
271 }
272 return o.longValue();
273 }
274
275
276 private boolean isSourceNewer(URL source, Class cls) {
277 try {
278 long lastMod;
279
280
281
282 if (source.getProtocol().equals("file")) {
283
284 String path = source.getPath().replace('/', File.separatorChar).replace('|', ':');
285 File file = new File(path);
286 lastMod = file.lastModified();
287 }
288 else {
289 lastMod = source.openConnection().getLastModified();
290 }
291 return lastMod > getTimeStamp(cls);
292 } catch (IOException e) {
293
294 return false;
295 }
296 }
297
298
299 private boolean resolveToScript(ClassNode type) {
300 String name = type.getName();
301 if (cachedClasses.get(name)==NO_CLASS) return false;
302 if (cachedClasses.get(name)==SCRIPT) cachedClasses.put(name,NO_CLASS);
303 if (name.startsWith("java.")) return type.isResolved();
304
305 if (name.indexOf('$')!=-1) return type.isResolved();
306 ModuleNode module = currentClass.getModule();
307 if (module.hasPackageName() && name.indexOf('.')==-1) return type.isResolved();
308
309 GroovyClassLoader gcl = compilationUnit.getClassLoader();
310 URL url = null;
311 try {
312 url = gcl.getResourceLoader().loadGroovySource(name);
313 } catch (MalformedURLException e) {
314
315 }
316 if (url !=null) {
317 if (type.isResolved()) {
318 Class cls = type.getTypeClass();
319
320 if (!isSourceNewer(url,cls)) return true;
321 cachedClasses.remove(type.getName());
322 type.setRedirect(null);
323 }
324 compilationUnit.addSource(url);
325 currentClass.getCompileUnit().addClassNodeToCompile(type,url.toString());
326 return true;
327 }
328
329 return type.isResolved();
330 }
331
332
333 private boolean resolveFromStaticInnerClasses(ClassNode type, boolean testStaticInnerClasses) {
334
335 testStaticInnerClasses &= type.hasPackageName();
336 if (testStaticInnerClasses) {
337 String name = type.getName();
338 String replacedPointType = name;
339 int lastPoint = replacedPointType.lastIndexOf('.');
340 replacedPointType = new StringBuffer()
341 .append(replacedPointType.substring(0, lastPoint))
342 .append("$")
343 .append(replacedPointType.substring(lastPoint + 1))
344 .toString();
345 type.setName(replacedPointType);
346 if (resolve(type,false,false,true)) return true;
347 type.setName(name);
348 }
349 return false;
350 }
351
352 private boolean resovleFromDefaultImports(ClassNode type, boolean testDefaultImports) {
353
354 testDefaultImports &= !type.hasPackageName();
355 if (testDefaultImports) {
356 for (int i = 0, size = DEFAULT_IMPORTS.length; i < size; i++) {
357 String packagePrefix = DEFAULT_IMPORTS[i];
358 String name = type.getName();
359 String fqn = packagePrefix+name;
360 type.setName(fqn);
361 if (resolve(type,false,false,false)) return true;
362 type.setName(name);
363 }
364 String name = type.getName();
365 if (name.equals("BigInteger")) {
366 type.setRedirect(ClassHelper.BigInteger_TYPE);
367 return true;
368 } else if (name.equals("BigDecimal")) {
369 type.setRedirect(ClassHelper.BigDecimal_TYPE);
370 return true;
371 }
372 }
373 return false;
374 }
375
376 private boolean resolveFromCompileUnit(ClassNode type) {
377
378 CompileUnit compileUnit = currentClass.getCompileUnit();
379 if (compileUnit == null) return false;
380 ClassNode cuClass = compileUnit.getClass(type.getName());
381 if (cuClass!=null) {
382 if (type!=cuClass) type.setRedirect(cuClass);
383 return true;
384 }
385 return false;
386 }
387
388
389 private void setClass(ClassNode n, Class cls) {
390 ClassNode cn = ClassHelper.make(cls);
391 n.setRedirect(cn);
392 }
393
394 private void ambigousClass(ClassNode type, ClassNode iType, String name, boolean resolved){
395 if (resolved && !type.getName().equals(iType.getName())) {
396 addError("reference to "+name+" is ambigous, both class "+type.getName()+" and "+iType.getName()+" match",type);
397 } else {
398 type.setRedirect(iType);
399 }
400 }
401
402 private boolean resolveAliasFromModule(ClassNode type) {
403 ModuleNode module = currentClass.getModule();
404 if (module==null) return false;
405 String name = type.getName();
406
407
408
409
410 String pname = name;
411 int index = name.length();
412
413
414
415
416
417 while (true) {
418 pname = name.substring(0,index);
419 ClassNode aliasedNode = module.getImport(pname);
420 if (aliasedNode!=null) {
421 if (pname.length()==name.length()){
422
423 type.setRedirect(aliasedNode);
424 return true;
425 } else {
426
427 String newName = aliasedNode.getName()+name.substring(pname.length());
428 type.setName(newName);
429 if (resolve(type,true,true,true)) return true;
430
431 type.setName(name);
432 }
433 }
434 index = pname.lastIndexOf('.');
435 if (index==-1) break;
436 }
437 return false;
438
439 }
440
441 private boolean resolveFromModule(ClassNode type, boolean testModuleImports) {
442 ModuleNode module = currentClass.getModule();
443 if (module==null) return false;
444
445 String name = type.getName();
446
447 if (!type.hasPackageName() && module.hasPackageName()){
448 type.setName(module.getPackageName()+name);
449 }
450
451 List moduleClasses = module.getClasses();
452 for (Iterator iter = moduleClasses.iterator(); iter.hasNext();) {
453 ClassNode mClass = (ClassNode) iter.next();
454 if (mClass.getName().equals(type.getName())){
455 if (mClass!=type) type.setRedirect(mClass);
456 return true;
457 }
458 }
459 type.setName(name);
460
461 if (testModuleImports) {
462 if (resolveAliasFromModule(type)) return true;
463
464 boolean resolved = false;
465 if (module.hasPackageName()) {
466
467 type.setName(module.getPackageName()+name);
468 resolved = resolve(type,false,false,false);
469 }
470
471 List packages = module.getImportPackages();
472 ClassNode iType = ClassHelper.makeWithoutCaching(name);
473 for (Iterator iter = packages.iterator(); iter.hasNext();) {
474 String packagePrefix = (String) iter.next();
475 String fqn = packagePrefix+name;
476 iType.setName(fqn);
477 if (resolve(iType,false,false,true)) {
478 ambigousClass(type,iType,name,resolved);
479 return true;
480 }
481 iType.setName(name);
482 }
483 if (!resolved) type.setName(name);
484 return resolved;
485 }
486 return false;
487 }
488
489 private boolean resolveToClass(ClassNode type) {
490 String name = type.getName();
491 if (cachedClasses.get(name)==NO_CLASS) return false;
492 if (currentClass.getModule().hasPackageName() && name.indexOf('.')==-1) return false;
493 GroovyClassLoader loader = compilationUnit.getClassLoader();
494 Class cls = null;
495 try {
496
497
498
499 cls = loader.loadClass(name,false,true);
500 } catch (ClassNotFoundException cnfe) {
501 cachedClasses.put(name,SCRIPT);
502 return false;
503 } catch (CompilationFailedException cfe) {
504 compilationUnit.getErrorCollector().addErrorAndContinue(new ExceptionMessage(cfe,true,source));
505 return false;
506 }
507
508
509
510
511
512
513
514
515
516 if (cls==null) return false;
517 cachedClasses.put(name,cls);
518 setClass(type,cls);
519
520
521
522
523 return cls.getClassLoader()==loader;
524 }
525
526
527
528 public Expression transform(Expression exp) {
529 if (exp==null) return null;
530 if (exp instanceof VariableExpression) {
531 return transformVariableExpression((VariableExpression) exp);
532 } else if (exp instanceof PropertyExpression) {
533 return transformPropertyExpression((PropertyExpression) exp);
534 } else if (exp instanceof DeclarationExpression) {
535 return transformDeclarationExpression((DeclarationExpression)exp);
536 } else if (exp instanceof BinaryExpression) {
537 return transformBinaryExpression((BinaryExpression)exp);
538 } else if (exp instanceof MethodCallExpression) {
539 return transformMethodCallExpression((MethodCallExpression)exp);
540 } else if (exp instanceof ClosureExpression) {
541 return transformClosureExpression((ClosureExpression) exp);
542 } else if (exp instanceof ConstructorCallExpression) {
543 return transformConstructorCallExpression((ConstructorCallExpression) exp);
544 } else {
545 resolveOrFail(exp.getType(),exp);
546 return exp.transformExpression(this);
547 }
548 }
549
550
551 private String lookupClassName(PropertyExpression pe) {
552 String name = "";
553 for (Expression it = pe; it!=null; it = ((PropertyExpression)it).getObjectExpression()) {
554 if (it instanceof VariableExpression) {
555 VariableExpression ve = (VariableExpression) it;
556
557 if (ve==VariableExpression.SUPER_EXPRESSION || ve==VariableExpression.THIS_EXPRESSION) {
558 return null;
559 }
560 name= ve.getName()+"."+name;
561 break;
562 }
563
564
565 else if (!(it instanceof PropertyExpression)) {
566 return null;
567 } else {
568 PropertyExpression current = (PropertyExpression) it;
569 String propertyPart = current.getProperty();
570
571 if (propertyPart.equals("class")) {
572 return null;
573 }
574 name = propertyPart+"."+name;
575 }
576 }
577 if (name.length()>0) return name.substring(0,name.length()-1);
578 return null;
579 }
580
581
582
583
584
585 private Expression correctClassClassChain(PropertyExpression pe){
586 LinkedList stack = new LinkedList();
587 ClassExpression found = null;
588 for (Expression it = pe; it!=null; it = ((PropertyExpression)it).getObjectExpression()) {
589 if (it instanceof ClassExpression) {
590 found = (ClassExpression) it;
591 break;
592 } else if (! (it instanceof PropertyExpression)) {
593 return pe;
594 }
595 stack.addFirst(it);
596 }
597 if (found==null) return pe;
598
599 if (stack.isEmpty()) return pe;
600 Object stackElement = stack.removeFirst();
601 if (!(stackElement instanceof PropertyExpression)) return pe;
602 PropertyExpression classPropertyExpression = (PropertyExpression) stackElement;
603 if (! classPropertyExpression.getProperty().equals("class")) return pe;
604
605 if (stack.isEmpty()) return found;
606 stackElement = stack.removeFirst();
607 if (!(stackElement instanceof PropertyExpression)) return pe;
608 PropertyExpression classPropertyExpressionContainer = (PropertyExpression) stackElement;
609
610 classPropertyExpressionContainer.setObjectExpression(found);
611 return pe;
612 }
613
614 protected Expression transformPropertyExpression(PropertyExpression pe) {
615 boolean itlp = isTopLevelProperty;
616
617 Expression objectExpression = pe.getObjectExpression();
618 isTopLevelProperty = !(objectExpression instanceof PropertyExpression);
619 objectExpression = transform(objectExpression);
620 isTopLevelProperty = itlp;
621
622 pe.setObjectExpression(objectExpression);
623
624 String className = lookupClassName(pe);
625 if (className!=null) {
626 ClassNode type = ClassHelper.make(className);
627 if (resolve(type)) return new ClassExpression(type);
628 }
629 if (objectExpression instanceof ClassExpression ){
630
631 ClassExpression ce = (ClassExpression) objectExpression;
632 ClassNode type = ClassHelper.make(ce.getType().getName()+"$"+pe.getProperty());
633 if (resolve(type,false,false,false)) return new ClassExpression(type);
634 }
635 if (isTopLevelProperty) return correctClassClassChain(pe);
636
637 return pe;
638 }
639
640 protected Expression transformVariableExpression(VariableExpression ve) {
641 if (ve.getName().equals("this")) return VariableExpression.THIS_EXPRESSION;
642 if (ve.getName().equals("super")) return VariableExpression.SUPER_EXPRESSION;
643 Variable v = ve.getAccessedVariable();
644 if (v instanceof DynamicVariable) {
645 ClassNode t = ClassHelper.make(ve.getName());
646 if (resolve(t)) {
647
648
649
650
651 for (VariableScope scope = currentScope; scope!=null && !scope.isRoot(); scope = scope.getParent()) {
652 if (scope.isRoot()) break;
653 if (scope.getReferencedClassVariables().remove(ve.getName())==null) break;
654 }
655 return new ClassExpression(t);
656 }
657 }
658 resolveOrFail(ve.getType(),ve);
659 return ve;
660 }
661
662 protected Expression transformBinaryExpression(BinaryExpression be) {
663 Expression left = transform(be.getLeftExpression());
664 if (be.getOperation().getType()==Types.ASSIGNMENT_OPERATOR && left instanceof ClassExpression){
665 ClassExpression ce = (ClassExpression) left;
666 addError("you tried to assign a value to "+ce.getType().getName(),be.getLeftExpression());
667 return be;
668 }
669 Expression right = transform(be.getRightExpression());
670 Expression ret = new BinaryExpression(left,be.getOperation(),right);
671 ret.setSourcePosition(be);
672 return ret;
673 }
674
675 protected Expression transformClosureExpression(ClosureExpression ce) {
676 Parameter[] paras = ce.getParameters();
677 if (paras!=null) {
678 for (int i=0; i<paras.length; i++) {
679 ClassNode t = paras[i].getType();
680 resolveOrFail(t,ce);
681 }
682 }
683 Statement code = ce.getCode();
684 if (code!=null) code.visit(this);
685 ClosureExpression newCe= new ClosureExpression(paras,code);
686 newCe.setVariableScope(ce.getVariableScope());
687 newCe.setSourcePosition(ce);
688 return newCe;
689 }
690
691 protected Expression transformConstructorCallExpression(ConstructorCallExpression cce){
692 ClassNode type = cce.getType();
693 resolveOrFail(type,cce);
694 Expression expr = cce.transformExpression(this);
695 return expr;
696 }
697
698 protected Expression transformMethodCallExpression(MethodCallExpression mce) {
699 Expression obj = mce.getObjectExpression();
700 Expression newObject = transform(obj);
701 Expression args = transform(mce.getArguments());
702 MethodCallExpression ret = new MethodCallExpression(newObject,mce.getMethod(),args);
703 ret.setSafe(mce.isSafe());
704 ret.setImplicitThis(mce.isImplicitThis());
705 ret.setSpreadSafe(mce.isSpreadSafe());
706 ret.setSourcePosition(mce);
707 return ret;
708 }
709
710 protected Expression transformDeclarationExpression(DeclarationExpression de) {
711 Expression oldLeft = de.getLeftExpression();
712 Expression left = transform(oldLeft);
713 if (left!=oldLeft){
714 ClassExpression ce = (ClassExpression) left;
715 addError("you tried to assign a value to "+ce.getType().getName(),oldLeft);
716 return de;
717 }
718 Expression right = transform(de.getRightExpression());
719 if (right==de.getRightExpression()) return de;
720 return new DeclarationExpression((VariableExpression) left,de.getOperation(),right);
721 }
722
723 public void visitAnnotations(AnnotatedNode node) {
724 Map annotionMap = node.getAnnotations();
725 if (annotionMap.isEmpty()) return;
726 Iterator it = annotionMap.values().iterator();
727 while (it.hasNext()) {
728 AnnotationNode an = (AnnotationNode) it.next();
729
730 if (an.isBuiltIn()) continue;
731 ClassNode type = an.getClassNode();
732 resolveOrFail(type,"unable to find class for annotation",an);
733 }
734 }
735
736 public void visitClass(ClassNode node) {
737 ClassNode oldNode = currentClass;
738 currentClass = node;
739
740 ModuleNode module = node.getModule();
741 if (!module.hasImportsResolved()) {
742 List l = module.getImports();
743 for (Iterator iter = l.iterator(); iter.hasNext();) {
744 ImportNode element = (ImportNode) iter.next();
745 ClassNode type = element.getType();
746 if (resolve(type,false,false,false)) continue;
747 addError("unable to resolve class "+type.getName(),type);
748 }
749 module.setImportsResolved(true);
750 }
751
752 ClassNode sn = node.getUnresolvedSuperClass();
753 if (sn!=null) resolveOrFail(sn,node,true);
754 ClassNode[] interfaces = node.getInterfaces();
755 for (int i=0; i<interfaces.length; i++) {
756 resolveOrFail(interfaces[i],node,true);
757 }
758 super.visitClass(node);
759 currentClass = oldNode;
760 }
761
762 public void visitReturnStatement(ReturnStatement statement) {
763 statement.setExpression(transform(statement.getExpression()));
764 }
765
766 public void visitAssertStatement(AssertStatement as) {
767 as.setBooleanExpression((BooleanExpression) (transform(as.getBooleanExpression())));
768 as.setMessageExpression(transform(as.getMessageExpression()));
769 }
770
771 public void visitCaseStatement(CaseStatement statement) {
772 statement.setExpression(transform(statement.getExpression()));
773 statement.getCode().visit(this);
774 }
775
776 public void visitCatchStatement(CatchStatement cs) {
777 resolveOrFail(cs.getExceptionType(),cs);
778 super.visitCatchStatement(cs);
779 }
780
781 public void visitDoWhileLoop(DoWhileStatement loop) {
782 loop.setBooleanExpression((BooleanExpression) (transform(loop.getBooleanExpression())));
783 super.visitDoWhileLoop(loop);
784 }
785
786 public void visitForLoop(ForStatement forLoop) {
787 forLoop.setCollectionExpression(transform(forLoop.getCollectionExpression()));
788 resolveOrFail(forLoop.getVariableType(),forLoop);
789 super.visitForLoop(forLoop);
790 }
791
792 public void visitSynchronizedStatement(SynchronizedStatement sync) {
793 sync.setExpression(transform(sync.getExpression()));
794 super.visitSynchronizedStatement(sync);
795 }
796
797 public void visitThrowStatement(ThrowStatement ts) {
798 ts.setExpression(transform(ts.getExpression()));
799 }
800
801 public void visitWhileLoop(WhileStatement loop) {
802 loop.setBooleanExpression((BooleanExpression) transform(loop.getBooleanExpression()));
803 super.visitWhileLoop(loop);
804 }
805
806 public void visitExpressionStatement(ExpressionStatement es) {
807 es.setExpression(transform(es.getExpression()));
808 }
809
810 public void visitBlockStatement(BlockStatement block) {
811 VariableScope oldScope = currentScope;
812 currentScope = block.getVariableScope();
813 super.visitBlockStatement(block);
814 currentScope = oldScope;
815 }
816
817 protected SourceUnit getSourceUnit() {
818 return source;
819 }
820 }