KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > code > flow > FlowAnalyzer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.code.flow;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.jdt.core.dom.ASTNode;
19 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
20 import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
21 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
22 import org.eclipse.jdt.core.dom.ArrayAccess;
23 import org.eclipse.jdt.core.dom.ArrayCreation;
24 import org.eclipse.jdt.core.dom.ArrayInitializer;
25 import org.eclipse.jdt.core.dom.ArrayType;
26 import org.eclipse.jdt.core.dom.AssertStatement;
27 import org.eclipse.jdt.core.dom.Assignment;
28 import org.eclipse.jdt.core.dom.Block;
29 import org.eclipse.jdt.core.dom.BooleanLiteral;
30 import org.eclipse.jdt.core.dom.BreakStatement;
31 import org.eclipse.jdt.core.dom.CastExpression;
32 import org.eclipse.jdt.core.dom.CatchClause;
33 import org.eclipse.jdt.core.dom.CharacterLiteral;
34 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
35 import org.eclipse.jdt.core.dom.CompilationUnit;
36 import org.eclipse.jdt.core.dom.ConditionalExpression;
37 import org.eclipse.jdt.core.dom.ConstructorInvocation;
38 import org.eclipse.jdt.core.dom.ContinueStatement;
39 import org.eclipse.jdt.core.dom.DoStatement;
40 import org.eclipse.jdt.core.dom.EmptyStatement;
41 import org.eclipse.jdt.core.dom.EnhancedForStatement;
42 import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
43 import org.eclipse.jdt.core.dom.EnumDeclaration;
44 import org.eclipse.jdt.core.dom.Expression;
45 import org.eclipse.jdt.core.dom.ExpressionStatement;
46 import org.eclipse.jdt.core.dom.FieldAccess;
47 import org.eclipse.jdt.core.dom.FieldDeclaration;
48 import org.eclipse.jdt.core.dom.ForStatement;
49 import org.eclipse.jdt.core.dom.IBinding;
50 import org.eclipse.jdt.core.dom.IMethodBinding;
51 import org.eclipse.jdt.core.dom.ITypeBinding;
52 import org.eclipse.jdt.core.dom.IVariableBinding;
53 import org.eclipse.jdt.core.dom.IfStatement;
54 import org.eclipse.jdt.core.dom.ImportDeclaration;
55 import org.eclipse.jdt.core.dom.InfixExpression;
56 import org.eclipse.jdt.core.dom.Initializer;
57 import org.eclipse.jdt.core.dom.InstanceofExpression;
58 import org.eclipse.jdt.core.dom.Javadoc;
59 import org.eclipse.jdt.core.dom.LabeledStatement;
60 import org.eclipse.jdt.core.dom.MarkerAnnotation;
61 import org.eclipse.jdt.core.dom.MemberValuePair;
62 import org.eclipse.jdt.core.dom.MethodDeclaration;
63 import org.eclipse.jdt.core.dom.MethodInvocation;
64 import org.eclipse.jdt.core.dom.Name;
65 import org.eclipse.jdt.core.dom.NormalAnnotation;
66 import org.eclipse.jdt.core.dom.NullLiteral;
67 import org.eclipse.jdt.core.dom.NumberLiteral;
68 import org.eclipse.jdt.core.dom.PackageDeclaration;
69 import org.eclipse.jdt.core.dom.ParameterizedType;
70 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
71 import org.eclipse.jdt.core.dom.PostfixExpression;
72 import org.eclipse.jdt.core.dom.PrefixExpression;
73 import org.eclipse.jdt.core.dom.PrimitiveType;
74 import org.eclipse.jdt.core.dom.QualifiedName;
75 import org.eclipse.jdt.core.dom.QualifiedType;
76 import org.eclipse.jdt.core.dom.ReturnStatement;
77 import org.eclipse.jdt.core.dom.SimpleName;
78 import org.eclipse.jdt.core.dom.SimpleType;
79 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
80 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
81 import org.eclipse.jdt.core.dom.Statement;
82 import org.eclipse.jdt.core.dom.StringLiteral;
83 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
84 import org.eclipse.jdt.core.dom.SuperFieldAccess;
85 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
86 import org.eclipse.jdt.core.dom.SwitchCase;
87 import org.eclipse.jdt.core.dom.SwitchStatement;
88 import org.eclipse.jdt.core.dom.SynchronizedStatement;
89 import org.eclipse.jdt.core.dom.ThisExpression;
90 import org.eclipse.jdt.core.dom.ThrowStatement;
91 import org.eclipse.jdt.core.dom.TryStatement;
92 import org.eclipse.jdt.core.dom.TypeDeclaration;
93 import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
94 import org.eclipse.jdt.core.dom.TypeLiteral;
95 import org.eclipse.jdt.core.dom.TypeParameter;
96 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
97 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
98 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
99 import org.eclipse.jdt.core.dom.WhileStatement;
100 import org.eclipse.jdt.core.dom.WildcardType;
101
102 import org.eclipse.jface.text.IRegion;
103 import org.eclipse.jface.text.Region;
104
105 import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
106
107 /**
108  * Special flow analyzer to determine the return value of the extracted method
109  * and the variables which have to be passed to the method.
110  *
111  * Note: This analyzer doesn't do a full flow analysis. For example it doesn't
112  * do dead code analysis or variable initialization analysis. It analyses the
113  * the first access to a variable (read or write) and if all execution paths
114  * return a value.
115  */

116 abstract class FlowAnalyzer extends GenericVisitor {
117
118     static protected class SwitchData {
119         private boolean fHasDefaultCase;
120         private List JavaDoc fRanges= new ArrayList JavaDoc(4);
121         private List JavaDoc fInfos= new ArrayList JavaDoc(4);
122         public void setHasDefaultCase() {
123             fHasDefaultCase= true;
124         }
125         public boolean hasDefaultCase() {
126             return fHasDefaultCase;
127         }
128         public void add(IRegion range, FlowInfo info) {
129             fRanges.add(range);
130             fInfos.add(info);
131         }
132         public IRegion[] getRanges() {
133             return (IRegion[]) fRanges.toArray(new IRegion[fRanges.size()]);
134         }
135         public FlowInfo[] getInfos() {
136             return (FlowInfo[]) fInfos.toArray(new FlowInfo[fInfos.size()]);
137         }
138         public FlowInfo getInfo(int index) {
139             return (FlowInfo)fInfos.get(index);
140         }
141     }
142
143     private HashMap JavaDoc fData = new HashMap JavaDoc(100);
144     /* package */ FlowContext fFlowContext= null;
145
146     public FlowAnalyzer(FlowContext context) {
147         fFlowContext= context;
148     }
149
150     protected abstract boolean createReturnFlowInfo(ReturnStatement node);
151
152     protected abstract boolean traverseNode(ASTNode node);
153     
154     protected boolean skipNode(ASTNode node) {
155         return !traverseNode(node);
156     }
157     
158     protected final boolean visitNode(ASTNode node) {
159         return traverseNode(node);
160     }
161     
162     //---- Hooks to create Flow info objects. User may introduce their own infos.
163

164     protected ReturnFlowInfo createReturn(ReturnStatement statement) {
165         return new ReturnFlowInfo(statement);
166     }
167     
168     protected ThrowFlowInfo createThrow() {
169         return new ThrowFlowInfo();
170     }
171     
172     protected BranchFlowInfo createBranch(SimpleName label) {
173         return new BranchFlowInfo(label, fFlowContext);
174     }
175     
176     protected GenericSequentialFlowInfo createSequential() {
177         return new GenericSequentialFlowInfo();
178     }
179     
180     protected ConditionalFlowInfo createConditional() {
181         return new ConditionalFlowInfo();
182     }
183     
184     protected EnhancedForFlowInfo createEnhancedFor() {
185         return new EnhancedForFlowInfo();
186     }
187     
188     protected ForFlowInfo createFor() {
189         return new ForFlowInfo();
190     }
191     
192     protected TryFlowInfo createTry() {
193         return new TryFlowInfo();
194     }
195     
196     protected WhileFlowInfo createWhile() {
197         return new WhileFlowInfo();
198     }
199     
200     protected IfFlowInfo createIf() {
201         return new IfFlowInfo();
202     }
203     
204     protected DoWhileFlowInfo createDoWhile() {
205         return new DoWhileFlowInfo();
206     }
207     
208     protected SwitchFlowInfo createSwitch() {
209         return new SwitchFlowInfo();
210     }
211
212     protected BlockFlowInfo createBlock() {
213         return new BlockFlowInfo();
214     }
215     
216     protected MessageSendFlowInfo createMessageSendFlowInfo() {
217         return new MessageSendFlowInfo();
218     }
219     
220     protected FlowContext getFlowContext() {
221         return fFlowContext;
222     }
223     
224     //---- Helpers to access flow analysis objects ----------------------------------------
225

226     protected FlowInfo getFlowInfo(ASTNode node) {
227         return (FlowInfo)fData.remove(node);
228     }
229     
230     protected void setFlowInfo(ASTNode node, FlowInfo info) {
231         fData.put(node, info);
232     }
233     
234     protected FlowInfo assignFlowInfo(ASTNode target, ASTNode source) {
235         FlowInfo result= getFlowInfo(source);
236         setFlowInfo(target, result);
237         return result;
238     }
239     
240     protected FlowInfo accessFlowInfo(ASTNode node) {
241         return (FlowInfo)fData.get(node);
242     }
243     
244     //---- Helpers to process sequential flow infos -------------------------------------
245

246     protected GenericSequentialFlowInfo processSequential(ASTNode parent, List JavaDoc nodes) {
247         GenericSequentialFlowInfo result= createSequential(parent);
248         process(result, nodes);
249         return result;
250     }
251     
252     protected GenericSequentialFlowInfo processSequential(ASTNode parent, ASTNode node1) {
253         GenericSequentialFlowInfo result= createSequential(parent);
254         if (node1 != null)
255             result.merge(getFlowInfo(node1), fFlowContext);
256         return result;
257     }
258     
259     protected GenericSequentialFlowInfo processSequential(ASTNode parent, ASTNode node1, ASTNode node2) {
260         GenericSequentialFlowInfo result= createSequential(parent);
261         if (node1 != null)
262             result.merge(getFlowInfo(node1), fFlowContext);
263         if (node2 != null)
264             result.merge(getFlowInfo(node2), fFlowContext);
265         return result;
266     }
267     
268     protected GenericSequentialFlowInfo createSequential(ASTNode parent) {
269         GenericSequentialFlowInfo result= createSequential();
270         setFlowInfo(parent, result);
271         return result;
272     }
273     
274     protected GenericSequentialFlowInfo createSequential(List JavaDoc nodes) {
275         GenericSequentialFlowInfo result= createSequential();
276         process(result, nodes);
277         return result;
278     }
279     
280     //---- Generic merge methods --------------------------------------------------------
281

282     protected void process(GenericSequentialFlowInfo info, List JavaDoc nodes) {
283         if (nodes == null)
284             return;
285         for (Iterator JavaDoc iter= nodes.iterator(); iter.hasNext();) {
286             info.merge(getFlowInfo((ASTNode)iter.next()), fFlowContext);
287         }
288     }
289     
290     protected void process(GenericSequentialFlowInfo info, ASTNode node) {
291         if (node != null)
292             info.merge(getFlowInfo(node), fFlowContext);
293     }
294     
295     protected void process(GenericSequentialFlowInfo info, ASTNode node1, ASTNode node2) {
296         if (node1 != null)
297             info.merge(getFlowInfo(node1), fFlowContext);
298         if (node2 != null)
299             info.merge(getFlowInfo(node2), fFlowContext);
300     }
301     
302     //---- special visit methods -------------------------------------------------------
303

304     public boolean visit(EmptyStatement node) {
305         // Empty statements aren't of any interest.
306
return false;
307     }
308     
309     public boolean visit(TryStatement node) {
310         if (traverseNode(node)) {
311             fFlowContext.pushExcptions(node);
312             node.getBody().accept(this);
313             fFlowContext.popExceptions();
314             List JavaDoc catchClauses= node.catchClauses();
315             for (Iterator JavaDoc iter= catchClauses.iterator(); iter.hasNext();) {
316                 ((CatchClause)iter.next()).accept(this);
317             }
318             Block finallyBlock= node.getFinally();
319             if (finallyBlock != null) {
320                 finallyBlock.accept(this);
321             }
322         }
323         return false;
324     }
325     
326     //---- Helper to process switch statement ----------------------------------------
327

328     protected SwitchData createSwitchData(SwitchStatement node) {
329         SwitchData result= new SwitchData();
330         List JavaDoc statements= node.statements();
331         if (statements.isEmpty())
332             return result;
333             
334         int start= -1, end= -1;
335         GenericSequentialFlowInfo info= null;
336         
337         for (Iterator JavaDoc iter= statements.iterator(); iter.hasNext(); ) {
338             Statement statement= (Statement)iter.next();
339             if (statement instanceof SwitchCase) {
340                 SwitchCase switchCase= (SwitchCase)statement;
341                 if (switchCase.isDefault()) {
342                     result.setHasDefaultCase();
343                 }
344                 if (info == null) {
345                     info= createSequential();
346                     start= statement.getStartPosition();
347                 } else {
348                     if (info.isReturn() || info.isPartialReturn() || info.branches()) {
349                         result.add(new Region(start, end - start + 1), info);
350                         info= createSequential();
351                         start= statement.getStartPosition();
352                     }
353                 }
354             } else {
355                 info.merge(getFlowInfo(statement), fFlowContext);
356             }
357             end= statement.getStartPosition() + statement.getLength() - 1;
358         }
359         result.add(new Region(start, end - start + 1), info);
360         return result;
361     }
362     
363     protected void endVisit(SwitchStatement node, SwitchData data) {
364         SwitchFlowInfo switchFlowInfo= createSwitch();
365         setFlowInfo(node, switchFlowInfo);
366         switchFlowInfo.mergeTest(getFlowInfo(node.getExpression()), fFlowContext);
367         FlowInfo[] cases= data.getInfos();
368         for (int i= 0; i < cases.length; i++)
369             switchFlowInfo.mergeCase(cases[i], fFlowContext);
370         switchFlowInfo.mergeDefault(data.hasDefaultCase(), fFlowContext);
371         switchFlowInfo.removeLabel(null);
372     }
373
374     //---- concret endVisit methods ---------------------------------------------------
375

376     public void endVisit(AnnotationTypeDeclaration node) {
377         if (skipNode(node))
378             return;
379         GenericSequentialFlowInfo info= processSequential(node, node.bodyDeclarations());
380         info.setNoReturn();
381     }
382     
383     public void endVisit(AnnotationTypeMemberDeclaration node) {
384         if (skipNode(node))
385             return;
386         GenericSequentialFlowInfo info= processSequential(node, node.getType(), node.getDefault());
387         info.setNoReturn();
388     }
389     
390     public void endVisit(AnonymousClassDeclaration node) {
391         if (skipNode(node))
392             return;
393         FlowInfo info= processSequential(node, node.bodyDeclarations());
394         info.setNoReturn();
395     }
396     
397     public void endVisit(ArrayAccess node) {
398         if (skipNode(node))
399             return;
400         processSequential(node, node.getArray(), node.getIndex());
401     }
402     
403     public void endVisit(ArrayCreation node) {
404         if (skipNode(node))
405             return;
406         GenericSequentialFlowInfo info= processSequential(node, node.getType());
407         process(info, node.dimensions());
408         process(info, node.getInitializer());
409     }
410     
411     public void endVisit(ArrayInitializer node) {
412         if (skipNode(node))
413             return;
414         processSequential(node, node.expressions());
415     }
416     
417     public void endVisit(ArrayType node) {
418         if (skipNode(node))
419             return;
420         processSequential(node, node.getElementType());
421     }
422     
423     public void endVisit(AssertStatement node) {
424         if (skipNode(node))
425             return;
426         IfFlowInfo info= new IfFlowInfo();
427         setFlowInfo(node, info);
428         info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
429         info.merge(getFlowInfo(node.getMessage()), null, fFlowContext);
430     }
431     
432     public void endVisit(Assignment node) {
433         if (skipNode(node))
434             return;
435         FlowInfo lhs= getFlowInfo(node.getLeftHandSide());
436         FlowInfo rhs= getFlowInfo(node.getRightHandSide());
437         if (lhs instanceof LocalFlowInfo) {
438             LocalFlowInfo llhs= (LocalFlowInfo)lhs;
439             llhs.setWriteAccess(fFlowContext);
440             if (node.getOperator() != Assignment.Operator.ASSIGN) {
441                 GenericSequentialFlowInfo tmp= createSequential();
442                 tmp.merge(new LocalFlowInfo(llhs, FlowInfo.READ, fFlowContext), fFlowContext);
443                 tmp.merge(rhs, fFlowContext);
444                 rhs= tmp;
445             }
446         }
447         GenericSequentialFlowInfo info= createSequential(node);
448         // first process right and side and then left hand side.
449
info.merge(rhs, fFlowContext);
450         info.merge(lhs, fFlowContext);
451     }
452     
453     public void endVisit(Block node) {
454         if (skipNode(node))
455             return;
456         BlockFlowInfo info= createBlock();
457         setFlowInfo(node, info);
458         process(info, node.statements());
459     }
460     
461     public void endVisit(BooleanLiteral node) {
462         // Leaf node.
463
}
464     
465     public void endVisit(BreakStatement node) {
466         if (skipNode(node))
467             return;
468         setFlowInfo(node, createBranch(node.getLabel()));
469     }
470     
471     public void endVisit(CastExpression node) {
472         if (skipNode(node))
473             return;
474         processSequential(node, node.getType(), node.getExpression());
475     }
476     
477     public void endVisit(CatchClause node) {
478         if (skipNode(node))
479             return;
480         processSequential(node, node.getException(), node.getBody());
481     }
482     
483     public void endVisit(CharacterLiteral node) {
484         // Leaf node.
485
}
486     
487     public void endVisit(ClassInstanceCreation node) {
488         if (skipNode(node))
489             return;
490         GenericSequentialFlowInfo info= processSequential(node, node.getExpression());
491         process(info, node.getType());
492         process(info, node.arguments());
493         process(info, node.getAnonymousClassDeclaration());
494     }
495     
496     public void endVisit(CompilationUnit node) {
497         if (skipNode(node))
498             return;
499         GenericSequentialFlowInfo info= processSequential(node, node.imports());
500         process(info, node.types());
501     }
502     
503     public void endVisit(ConditionalExpression node) {
504         if (skipNode(node))
505             return;
506         ConditionalFlowInfo info= createConditional();
507         setFlowInfo(node, info);
508         info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
509         info.merge(
510             getFlowInfo(node.getThenExpression()),
511             getFlowInfo(node.getElseExpression()),
512             fFlowContext);
513     }
514     
515     public void endVisit(ConstructorInvocation node) {
516         if (skipNode(node))
517             return;
518         processSequential(node, node.arguments());
519     }
520     
521     public void endVisit(ContinueStatement node) {
522         if (skipNode(node))
523             return;
524         setFlowInfo(node, createBranch(node.getLabel()));
525     }
526     
527     public void endVisit(DoStatement node) {
528         if (skipNode(node))
529             return;
530         DoWhileFlowInfo info= createDoWhile();
531         setFlowInfo(node, info);
532         info.mergeAction(getFlowInfo(node.getBody()), fFlowContext);
533         info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
534         info.removeLabel(null);
535     }
536     
537     public void endVisit(EmptyStatement node) {
538         // Leaf node.
539
}
540     
541     public void endVisit(EnhancedForStatement node) {
542         if (skipNode(node))
543             return;
544         EnhancedForFlowInfo forInfo= createEnhancedFor();
545         setFlowInfo(node, forInfo);
546         forInfo.mergeParameter(getFlowInfo(node.getParameter()), fFlowContext);
547         forInfo.mergeExpression(getFlowInfo(node.getExpression()), fFlowContext);
548         forInfo.mergeAction(getFlowInfo(node.getBody()), fFlowContext);
549         forInfo.removeLabel(null);
550     }
551     
552     public void endVisit(EnumConstantDeclaration node) {
553         if (skipNode(node))
554             return;
555         GenericSequentialFlowInfo info= processSequential(node, node.arguments());
556         process(info, node.getAnonymousClassDeclaration());
557     }
558     
559     public void endVisit(EnumDeclaration node) {
560         if (skipNode(node))
561             return;
562         GenericSequentialFlowInfo info= processSequential(node, node.superInterfaceTypes());
563         process(info, node.enumConstants());
564         process(info, node.bodyDeclarations());
565         info.setNoReturn();
566     }
567     
568     public void endVisit(ExpressionStatement node) {
569         if (skipNode(node))
570             return;
571         assignFlowInfo(node, node.getExpression());
572     }
573     
574     public void endVisit(FieldAccess node) {
575         if (skipNode(node))
576             return;
577         processSequential(node, node.getExpression(), node.getName());
578     }
579     
580     public void endVisit(FieldDeclaration node) {
581         if (skipNode(node))
582             return;
583         GenericSequentialFlowInfo info= processSequential(node, node.getType());
584         process(info, node.fragments());
585     }
586     
587     public void endVisit(ForStatement node) {
588         if (skipNode(node))
589             return;
590         ForFlowInfo forInfo= createFor();
591         setFlowInfo(node, forInfo);
592         forInfo.mergeInitializer(createSequential(node.initializers()), fFlowContext);
593         forInfo.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
594         forInfo.mergeAction(getFlowInfo(node.getBody()), fFlowContext);
595         // Increments are executed after the action.
596
forInfo.mergeIncrement(createSequential(node.updaters()), fFlowContext);
597         forInfo.removeLabel(null);
598     }
599     
600     public void endVisit(IfStatement node) {
601         if (skipNode(node))
602             return;
603         IfFlowInfo info= createIf();
604         setFlowInfo(node, info);
605         info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
606         info.merge(getFlowInfo(node.getThenStatement()), getFlowInfo(node.getElseStatement()), fFlowContext);
607     }
608     
609     public void endVisit(ImportDeclaration node) {
610         if (skipNode(node))
611             return;
612         assignFlowInfo(node, node.getName());
613     }
614     
615     public void endVisit(InfixExpression node) {
616         if (skipNode(node))
617             return;
618         GenericSequentialFlowInfo info= processSequential(node, node.getLeftOperand(), node.getRightOperand());
619         process(info, node.extendedOperands());
620     }
621     
622     public void endVisit(InstanceofExpression node) {
623         if (skipNode(node))
624             return;
625         processSequential(node, node.getLeftOperand(), node.getRightOperand());
626     }
627     
628     public void endVisit(Initializer node) {
629         if (skipNode(node))
630             return;
631         assignFlowInfo(node, node.getBody());
632     }
633     
634     public void endVisit(Javadoc node) {
635         // no influence on flow analysis
636
}
637     
638     public void endVisit(LabeledStatement node) {
639         if (skipNode(node))
640             return;
641         FlowInfo info= assignFlowInfo(node, node.getBody());
642         if (info != null)
643             info.removeLabel(node.getLabel());
644     }
645     
646     public void endVisit(MarkerAnnotation node) {
647         // nothing to do for marker annotations;
648
}
649     
650     public void endVisit(MemberValuePair node) {
651         if (skipNode(node))
652             return;
653
654         FlowInfo name= getFlowInfo(node.getName());
655         FlowInfo value= getFlowInfo(node.getValue());
656         if (name instanceof LocalFlowInfo) {
657             LocalFlowInfo llhs= (LocalFlowInfo)name;
658             llhs.setWriteAccess(fFlowContext);
659         }
660         GenericSequentialFlowInfo info= createSequential(node);
661         // first process value and then name.
662
info.merge(value, fFlowContext);
663         info.merge(name, fFlowContext);
664         
665     }
666     
667     public void endVisit(MethodDeclaration node) {
668         if (skipNode(node))
669             return;
670         GenericSequentialFlowInfo info= processSequential(node, node.getReturnType2());
671         process(info, node.parameters());
672         process(info, node.thrownExceptions());
673         process(info, node.getBody());
674     }
675     
676     public void endVisit(MethodInvocation node) {
677         endVisitMethodInvocation(node, node.getExpression(), node.arguments(), getMethodBinding(node.getName()));
678     }
679     
680     public void endVisit(NormalAnnotation node) {
681         if (skipNode(node))
682             return;
683         GenericSequentialFlowInfo info= processSequential(node, node.getTypeName());
684         process(info, node.values());
685     }
686     
687     public void endVisit(NullLiteral node) {
688         // Leaf node.
689
}
690     
691     public void endVisit(NumberLiteral node) {
692         // Leaf node.
693
}
694     
695     public void endVisit(PackageDeclaration node) {
696         if (skipNode(node))
697             return;
698         assignFlowInfo(node, node.getName());
699     }
700     
701     public void endVisit(ParameterizedType node) {
702         if (skipNode(node))
703             return;
704         GenericSequentialFlowInfo info= processSequential(node, node.getType());
705         process(info, node.typeArguments());
706     }
707     
708     public void endVisit(ParenthesizedExpression node) {
709         if (skipNode(node))
710             return;
711         assignFlowInfo(node, node.getExpression());
712     }
713     
714     public void endVisit(PostfixExpression node) {
715         endVisitIncDecOperation(node, node.getOperand());
716     }
717     
718     public void endVisit(PrefixExpression node) {
719         PrefixExpression.Operator op= node.getOperator();
720         if (PrefixExpression.Operator.INCREMENT.equals(op) || PrefixExpression.Operator.DECREMENT.equals(op)) {
721             endVisitIncDecOperation(node, node.getOperand());
722         } else {
723             assignFlowInfo(node, node.getOperand());
724         }
725     }
726     
727     public void endVisit(PrimitiveType node) {
728         // Leaf node
729
}
730     
731     public void endVisit(QualifiedName node) {
732         if (skipNode(node))
733             return;
734         processSequential(node, node.getQualifier(), node.getName());
735     }
736     
737     public void endVisit(QualifiedType node) {
738         if (skipNode(node))
739             return;
740         processSequential(node, node.getQualifier(), node.getName());
741     }
742     
743     public void endVisit(ReturnStatement node) {
744         if (skipNode(node))
745             return;
746             
747         if (createReturnFlowInfo(node)) {
748             ReturnFlowInfo info= createReturn(node);
749             setFlowInfo(node, info);
750             info.merge(getFlowInfo(node.getExpression()), fFlowContext);
751         } else {
752             assignFlowInfo(node, node.getExpression());
753         }
754     }
755     
756     public void endVisit(SimpleName node) {
757         if (skipNode(node) || node.isDeclaration())
758             return;
759         IBinding binding= node.resolveBinding();
760         if (binding instanceof IVariableBinding) {
761             IVariableBinding variable= (IVariableBinding)binding;
762             if (!variable.isField()) {
763                 setFlowInfo(node, new LocalFlowInfo(
764                     variable,
765                     FlowInfo.READ,
766                     fFlowContext));
767             }
768         } else if (binding instanceof ITypeBinding) {
769             ITypeBinding type= (ITypeBinding)binding;
770             if (type.isTypeVariable()) {
771                 setFlowInfo(node, new TypeVariableFlowInfo(type, fFlowContext));
772             }
773         }
774     }
775     
776     public void endVisit(SimpleType node) {
777         if (skipNode(node))
778             return;
779         assignFlowInfo(node, node.getName());
780     }
781     
782     public void endVisit(SingleMemberAnnotation node) {
783         if (skipNode(node))
784             return;
785         assignFlowInfo(node, node.getValue());
786     }
787     
788     public void endVisit(SingleVariableDeclaration node) {
789         if (skipNode(node))
790             return;
791             
792         IVariableBinding binding= node.resolveBinding();
793         LocalFlowInfo nameInfo= null;
794         Expression initializer= node.getInitializer();
795         if (binding != null && !binding.isField() && initializer != null) {
796             nameInfo= new LocalFlowInfo(binding, FlowInfo.WRITE, fFlowContext);
797         }
798         GenericSequentialFlowInfo info= processSequential(node, node.getType(), initializer);
799         info.merge(nameInfo, fFlowContext);
800     }
801     
802     public void endVisit(StringLiteral node) {
803         // Leaf node
804
}
805     
806     public void endVisit(SuperConstructorInvocation node) {
807         endVisitMethodInvocation(node, node.getExpression(), node.arguments(), node.resolveConstructorBinding());
808     }
809     
810     public void endVisit(SuperFieldAccess node) {
811         if (skipNode(node))
812             return;
813         processSequential(node, node.getQualifier(), node.getName());
814     }
815     
816     public void endVisit(SuperMethodInvocation node) {
817         endVisitMethodInvocation(node, node.getQualifier(), node.arguments(), getMethodBinding(node.getName()));
818     }
819     
820     public void endVisit(SwitchCase node) {
821         endVisitNode(node);
822     }
823     
824     public void endVisit(SwitchStatement node) {
825         if (skipNode(node))
826             return;
827         endVisit(node, createSwitchData(node));
828     }
829     
830     public void endVisit(SynchronizedStatement node) {
831         if (skipNode(node))
832             return;
833         GenericSequentialFlowInfo info= processSequential(node, node.getExpression());
834         process(info, node.getBody());
835     }
836     
837     public void endVisit(ThisExpression node) {
838         if (skipNode(node))
839             return;
840         assignFlowInfo(node, node.getQualifier());
841     }
842     
843     public void endVisit(ThrowStatement node) {
844         if (skipNode(node))
845             return;
846         ThrowFlowInfo info= createThrow();
847         setFlowInfo(node, info);
848         Expression expression= node.getExpression();
849         info.merge(getFlowInfo(expression), fFlowContext);
850         info.mergeException(expression.resolveTypeBinding(), fFlowContext);
851     }
852     
853     public void endVisit(TryStatement node) {
854         if (skipNode(node))
855             return;
856         TryFlowInfo info= createTry();
857         setFlowInfo(node, info);
858         info.mergeTry(getFlowInfo(node.getBody()), fFlowContext);
859         info.removeExceptions(node);
860         for (Iterator JavaDoc iter= node.catchClauses().iterator(); iter.hasNext();) {
861             CatchClause element= (CatchClause)iter.next();
862             info.mergeCatch(getFlowInfo(element), fFlowContext);
863         }
864         info.mergeFinally(getFlowInfo(node.getFinally()), fFlowContext);
865     }
866     
867     // TODO account for enums and annotations
868

869     public void endVisit(TypeDeclaration node) {
870         if (skipNode(node))
871             return;
872         GenericSequentialFlowInfo info= processSequential(node, node.getSuperclassType());
873         process(info, node.superInterfaceTypes());
874         process(info, node.bodyDeclarations());
875         info.setNoReturn();
876     }
877     
878     public void endVisit(TypeDeclarationStatement node) {
879         if (skipNode(node))
880             return;
881         assignFlowInfo(node, node.getDeclaration());
882     }
883     
884     public void endVisit(TypeLiteral node) {
885         if (skipNode(node))
886             return;
887         assignFlowInfo(node, node.getType());
888     }
889     
890     public void endVisit(TypeParameter node) {
891         if (skipNode(node))
892             return;
893         GenericSequentialFlowInfo info= processSequential(node, node.getName());
894         process(info, node.typeBounds());
895     }
896     
897     public void endVisit(VariableDeclarationExpression node) {
898         if (skipNode(node))
899             return;
900         GenericSequentialFlowInfo info= processSequential(node, node.getType());
901         process(info, node.fragments());
902     }
903     
904     public void endVisit(VariableDeclarationStatement node) {
905         if (skipNode(node))
906             return;
907         GenericSequentialFlowInfo info= processSequential(node, node.getType());
908         process(info, node.fragments());
909     }
910     
911     public void endVisit(VariableDeclarationFragment node) {
912         if (skipNode(node))
913             return;
914             
915         IVariableBinding binding= node.resolveBinding();
916         LocalFlowInfo nameInfo= null;
917         Expression initializer= node.getInitializer();
918         if (binding != null && !binding.isField() && initializer != null) {
919             nameInfo= new LocalFlowInfo(binding, FlowInfo.WRITE, fFlowContext);
920         }
921         GenericSequentialFlowInfo info= processSequential(node, initializer);
922         info.merge(nameInfo, fFlowContext);
923     }
924     
925     public void endVisit(WhileStatement node) {
926         if (skipNode(node))
927             return;
928         WhileFlowInfo info= createWhile();
929         setFlowInfo(node, info);
930         info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
931         info.mergeAction(getFlowInfo(node.getBody()), fFlowContext);
932         info.removeLabel(null);
933     }
934     
935     public void endVisit(WildcardType node) {
936         if (skipNode(node))
937             return;
938         assignFlowInfo(node, node.getBound());
939     }
940     
941     private void endVisitMethodInvocation(ASTNode node, ASTNode receiver, List JavaDoc arguments, IMethodBinding binding) {
942         if (skipNode(node))
943             return;
944         MessageSendFlowInfo info= createMessageSendFlowInfo();
945         setFlowInfo(node, info);
946         for (Iterator JavaDoc iter= arguments.iterator(); iter.hasNext();) {
947             Expression arg= (Expression) iter.next();
948             info.mergeArgument(getFlowInfo(arg), fFlowContext);
949         }
950         info.mergeReceiver(getFlowInfo(receiver), fFlowContext);
951         info.mergeExceptions(binding, fFlowContext);
952     }
953     
954     private void endVisitIncDecOperation(Expression node, Expression operand) {
955         if (skipNode(node))
956             return;
957         FlowInfo info= getFlowInfo(operand);
958         if (info instanceof LocalFlowInfo) {
959             // Normally we should do this in the parent node since the write access take place later.
960
// But I couldn't come up with a case where this influences the flow analysis. So I kept
961
// it here to simplify the code.
962
GenericSequentialFlowInfo result= createSequential(node);
963             result.merge(info, fFlowContext);
964             result.merge(
965                 new LocalFlowInfo((LocalFlowInfo)info, FlowInfo.WRITE, fFlowContext),
966                 fFlowContext);
967         } else {
968             setFlowInfo(node, info);
969         }
970     }
971     
972     private IMethodBinding getMethodBinding(Name name) {
973         if (name == null)
974             return null;
975         IBinding binding= name.resolveBinding();
976         if (binding instanceof IMethodBinding)
977             return (IMethodBinding)binding;
978         return null;
979     }
980 }
981
Popular Tags