]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-before/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/flow/FlowAnalyzer.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / core refactoring / org / eclipse / jdt / internal / corext / refactoring / code / flow / FlowAnalyzer.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 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;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
17
18 import org.eclipse.jface.text.IRegion;
19 import org.eclipse.jface.text.Region;
20
21 import org.eclipse.jdt.core.dom.ASTNode;
22 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
23 import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
24 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
25 import org.eclipse.jdt.core.dom.ArrayAccess;
26 import org.eclipse.jdt.core.dom.ArrayCreation;
27 import org.eclipse.jdt.core.dom.ArrayInitializer;
28 import org.eclipse.jdt.core.dom.ArrayType;
29 import org.eclipse.jdt.core.dom.AssertStatement;
30 import org.eclipse.jdt.core.dom.Assignment;
31 import org.eclipse.jdt.core.dom.Block;
32 import org.eclipse.jdt.core.dom.BooleanLiteral;
33 import org.eclipse.jdt.core.dom.BreakStatement;
34 import org.eclipse.jdt.core.dom.CastExpression;
35 import org.eclipse.jdt.core.dom.CatchClause;
36 import org.eclipse.jdt.core.dom.CharacterLiteral;
37 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
38 import org.eclipse.jdt.core.dom.CompilationUnit;
39 import org.eclipse.jdt.core.dom.ConditionalExpression;
40 import org.eclipse.jdt.core.dom.ConstructorInvocation;
41 import org.eclipse.jdt.core.dom.ContinueStatement;
42 import org.eclipse.jdt.core.dom.DoStatement;
43 import org.eclipse.jdt.core.dom.EmptyStatement;
44 import org.eclipse.jdt.core.dom.EnhancedForStatement;
45 import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
46 import org.eclipse.jdt.core.dom.EnumDeclaration;
47 import org.eclipse.jdt.core.dom.Expression;
48 import org.eclipse.jdt.core.dom.ExpressionStatement;
49 import org.eclipse.jdt.core.dom.FieldAccess;
50 import org.eclipse.jdt.core.dom.FieldDeclaration;
51 import org.eclipse.jdt.core.dom.ForStatement;
52 import org.eclipse.jdt.core.dom.IBinding;
53 import org.eclipse.jdt.core.dom.IMethodBinding;
54 import org.eclipse.jdt.core.dom.ITypeBinding;
55 import org.eclipse.jdt.core.dom.IVariableBinding;
56 import org.eclipse.jdt.core.dom.IfStatement;
57 import org.eclipse.jdt.core.dom.ImportDeclaration;
58 import org.eclipse.jdt.core.dom.InfixExpression;
59 import org.eclipse.jdt.core.dom.Initializer;
60 import org.eclipse.jdt.core.dom.InstanceofExpression;
61 import org.eclipse.jdt.core.dom.Javadoc;
62 import org.eclipse.jdt.core.dom.LabeledStatement;
63 import org.eclipse.jdt.core.dom.MarkerAnnotation;
64 import org.eclipse.jdt.core.dom.MemberValuePair;
65 import org.eclipse.jdt.core.dom.MethodDeclaration;
66 import org.eclipse.jdt.core.dom.MethodInvocation;
67 import org.eclipse.jdt.core.dom.Name;
68 import org.eclipse.jdt.core.dom.NormalAnnotation;
69 import org.eclipse.jdt.core.dom.NullLiteral;
70 import org.eclipse.jdt.core.dom.NumberLiteral;
71 import org.eclipse.jdt.core.dom.PackageDeclaration;
72 import org.eclipse.jdt.core.dom.ParameterizedType;
73 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
74 import org.eclipse.jdt.core.dom.PostfixExpression;
75 import org.eclipse.jdt.core.dom.PrefixExpression;
76 import org.eclipse.jdt.core.dom.PrimitiveType;
77 import org.eclipse.jdt.core.dom.QualifiedName;
78 import org.eclipse.jdt.core.dom.QualifiedType;
79 import org.eclipse.jdt.core.dom.ReturnStatement;
80 import org.eclipse.jdt.core.dom.SimpleName;
81 import org.eclipse.jdt.core.dom.SimpleType;
82 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
83 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
84 import org.eclipse.jdt.core.dom.Statement;
85 import org.eclipse.jdt.core.dom.StringLiteral;
86 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
87 import org.eclipse.jdt.core.dom.SuperFieldAccess;
88 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
89 import org.eclipse.jdt.core.dom.SwitchCase;
90 import org.eclipse.jdt.core.dom.SwitchStatement;
91 import org.eclipse.jdt.core.dom.SynchronizedStatement;
92 import org.eclipse.jdt.core.dom.ThisExpression;
93 import org.eclipse.jdt.core.dom.ThrowStatement;
94 import org.eclipse.jdt.core.dom.TryStatement;
95 import org.eclipse.jdt.core.dom.TypeDeclaration;
96 import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
97 import org.eclipse.jdt.core.dom.TypeLiteral;
98 import org.eclipse.jdt.core.dom.TypeParameter;
99 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
100 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
101 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
102 import org.eclipse.jdt.core.dom.WhileStatement;
103 import org.eclipse.jdt.core.dom.WildcardType;
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<IRegion> fRanges= new ArrayList<IRegion>(4);
121                 private List<FlowInfo> fInfos= new ArrayList<FlowInfo>(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 fRanges.toArray(new IRegion[fRanges.size()]);
134                 }
135                 public FlowInfo[] getInfos() {
136                         return fInfos.toArray(new FlowInfo[fInfos.size()]);
137                 }
138                 public FlowInfo getInfo(int index) {
139                         return fInfos.get(index);
140                 }
141         }
142
143         private HashMap<ASTNode, FlowInfo> fData = new HashMap<ASTNode, FlowInfo>(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         @Override
159         protected final boolean visitNode(ASTNode node) {
160                 return traverseNode(node);
161         }
162
163         //---- Hooks to create Flow info objects. User may introduce their own infos.
164
165         protected ReturnFlowInfo createReturn(ReturnStatement statement) {
166                 return new ReturnFlowInfo(statement);
167         }
168
169         protected ThrowFlowInfo createThrow() {
170                 return new ThrowFlowInfo();
171         }
172
173         protected BranchFlowInfo createBranch(SimpleName label) {
174                 return new BranchFlowInfo(label, fFlowContext);
175         }
176
177         protected GenericSequentialFlowInfo createSequential() {
178                 return new GenericSequentialFlowInfo();
179         }
180
181         protected ConditionalFlowInfo createConditional() {
182                 return new ConditionalFlowInfo();
183         }
184
185         protected EnhancedForFlowInfo createEnhancedFor() {
186                 return new EnhancedForFlowInfo();
187         }
188
189         protected ForFlowInfo createFor() {
190                 return new ForFlowInfo();
191         }
192
193         protected TryFlowInfo createTry() {
194                 return new TryFlowInfo();
195         }
196
197         protected WhileFlowInfo createWhile() {
198                 return new WhileFlowInfo();
199         }
200
201         protected IfFlowInfo createIf() {
202                 return new IfFlowInfo();
203         }
204
205         protected DoWhileFlowInfo createDoWhile() {
206                 return new DoWhileFlowInfo();
207         }
208
209         protected SwitchFlowInfo createSwitch() {
210                 return new SwitchFlowInfo();
211         }
212
213         protected BlockFlowInfo createBlock() {
214                 return new BlockFlowInfo();
215         }
216
217         protected MessageSendFlowInfo createMessageSendFlowInfo() {
218                 return new MessageSendFlowInfo();
219         }
220
221         protected FlowContext getFlowContext() {
222                 return fFlowContext;
223         }
224
225         //---- Helpers to access flow analysis objects ----------------------------------------
226
227         protected FlowInfo getFlowInfo(ASTNode node) {
228                 return fData.remove(node);
229         }
230
231         protected void setFlowInfo(ASTNode node, FlowInfo info) {
232                 fData.put(node, info);
233         }
234
235         protected FlowInfo assignFlowInfo(ASTNode target, ASTNode source) {
236                 FlowInfo result= getFlowInfo(source);
237                 setFlowInfo(target, result);
238                 return result;
239         }
240
241         protected FlowInfo accessFlowInfo(ASTNode node) {
242                 return fData.get(node);
243         }
244
245         //---- Helpers to process sequential flow infos -------------------------------------
246
247         protected GenericSequentialFlowInfo processSequential(ASTNode parent, List<? extends ASTNode> nodes) {
248                 GenericSequentialFlowInfo result= createSequential(parent);
249                 process(result, nodes);
250                 return result;
251         }
252
253         protected GenericSequentialFlowInfo processSequential(ASTNode parent, ASTNode node1) {
254                 GenericSequentialFlowInfo result= createSequential(parent);
255                 if (node1 != null)
256                         result.merge(getFlowInfo(node1), fFlowContext);
257                 return result;
258         }
259
260         protected GenericSequentialFlowInfo processSequential(ASTNode parent, ASTNode node1, ASTNode node2) {
261                 GenericSequentialFlowInfo result= createSequential(parent);
262                 if (node1 != null)
263                         result.merge(getFlowInfo(node1), fFlowContext);
264                 if (node2 != null)
265                         result.merge(getFlowInfo(node2), fFlowContext);
266                 return result;
267         }
268
269         protected GenericSequentialFlowInfo createSequential(ASTNode parent) {
270                 GenericSequentialFlowInfo result= createSequential();
271                 setFlowInfo(parent, result);
272                 return result;
273         }
274
275         protected GenericSequentialFlowInfo createSequential(List<? extends ASTNode> nodes) {
276                 GenericSequentialFlowInfo result= createSequential();
277                 process(result, nodes);
278                 return result;
279         }
280
281         //---- Generic merge methods --------------------------------------------------------
282
283         protected void process(GenericSequentialFlowInfo info, List<? extends ASTNode> nodes) {
284                 if (nodes == null)
285                         return;
286                 for (Iterator<? extends ASTNode> iter= nodes.iterator(); iter.hasNext();) {
287                         info.merge(getFlowInfo(iter.next()), fFlowContext);
288                 }
289         }
290
291         protected void process(GenericSequentialFlowInfo info, ASTNode node) {
292                 if (node != null)
293                         info.merge(getFlowInfo(node), fFlowContext);
294         }
295
296         protected void process(GenericSequentialFlowInfo info, ASTNode node1, ASTNode node2) {
297                 if (node1 != null)
298                         info.merge(getFlowInfo(node1), fFlowContext);
299                 if (node2 != null)
300                         info.merge(getFlowInfo(node2), fFlowContext);
301         }
302
303         //---- special visit methods -------------------------------------------------------
304
305         @Override
306         public boolean visit(EmptyStatement node) {
307                 // Empty statements aren't of any interest.
308                 return false;
309         }
310
311         @Override
312         public boolean visit(TryStatement node) {
313                 if (traverseNode(node)) {
314                         fFlowContext.pushExcptions(node);
315                         node.getBody().accept(this);
316                         fFlowContext.popExceptions();
317                         List<CatchClause> catchClauses= node.catchClauses();
318                         for (Iterator<CatchClause> iter= catchClauses.iterator(); iter.hasNext();) {
319                                 iter.next().accept(this);
320                         }
321                         Block finallyBlock= node.getFinally();
322                         if (finallyBlock != null) {
323                                 finallyBlock.accept(this);
324                         }
325                 }
326                 return false;
327         }
328
329         //---- Helper to process switch statement ----------------------------------------
330
331         protected SwitchData createSwitchData(SwitchStatement node) {
332                 SwitchData result= new SwitchData();
333                 List<Statement> statements= node.statements();
334                 if (statements.isEmpty())
335                         return result;
336
337                 int start= -1, end= -1;
338                 GenericSequentialFlowInfo info= null;
339
340                 for (Iterator<Statement> iter= statements.iterator(); iter.hasNext(); ) {
341                         Statement statement= iter.next();
342                         if (statement instanceof SwitchCase) {
343                                 SwitchCase switchCase= (SwitchCase)statement;
344                                 if (switchCase.isDefault()) {
345                                         result.setHasDefaultCase();
346                                 }
347                                 if (info == null) {
348                                         info= createSequential();
349                                         start= statement.getStartPosition();
350                                 } else {
351                                         if (info.isReturn() || info.isPartialReturn() || info.branches()) {
352                                                 result.add(new Region(start, end - start + 1), info);
353                                                 info= createSequential();
354                                                 start= statement.getStartPosition();
355                                         }
356                                 }
357                         } else {
358                                 info.merge(getFlowInfo(statement), fFlowContext);
359                         }
360                         end= statement.getStartPosition() + statement.getLength() - 1;
361                 }
362                 result.add(new Region(start, end - start + 1), info);
363                 return result;
364         }
365
366         protected void endVisit(SwitchStatement node, SwitchData data) {
367                 SwitchFlowInfo switchFlowInfo= createSwitch();
368                 setFlowInfo(node, switchFlowInfo);
369                 switchFlowInfo.mergeTest(getFlowInfo(node.getExpression()), fFlowContext);
370                 FlowInfo[] cases= data.getInfos();
371                 for (int i= 0; i < cases.length; i++)
372                         switchFlowInfo.mergeCase(cases[i], fFlowContext);
373                 switchFlowInfo.mergeDefault(data.hasDefaultCase(), fFlowContext);
374                 switchFlowInfo.removeLabel(null);
375         }
376
377         //---- concret endVisit methods ---------------------------------------------------
378
379         @Override
380         public void endVisit(AnnotationTypeDeclaration node) {
381                 if (skipNode(node))
382                         return;
383                 GenericSequentialFlowInfo info= processSequential(node, node.bodyDeclarations());
384                 info.setNoReturn();
385         }
386
387         @Override
388         public void endVisit(AnnotationTypeMemberDeclaration node) {
389                 if (skipNode(node))
390                         return;
391                 GenericSequentialFlowInfo info= processSequential(node, node.getType(), node.getDefault());
392                 info.setNoReturn();
393         }
394
395         @Override
396         public void endVisit(AnonymousClassDeclaration node) {
397                 if (skipNode(node))
398                         return;
399                 FlowInfo info= processSequential(node, node.bodyDeclarations());
400                 info.setNoReturn();
401         }
402
403         @Override
404         public void endVisit(ArrayAccess node) {
405                 if (skipNode(node))
406                         return;
407                 processSequential(node, node.getArray(), node.getIndex());
408         }
409
410         @Override
411         public void endVisit(ArrayCreation node) {
412                 if (skipNode(node))
413                         return;
414                 GenericSequentialFlowInfo info= processSequential(node, node.getType());
415                 process(info, node.dimensions());
416                 process(info, node.getInitializer());
417         }
418
419         @Override
420         public void endVisit(ArrayInitializer node) {
421                 if (skipNode(node))
422                         return;
423                 processSequential(node, node.expressions());
424         }
425
426         @Override
427         public void endVisit(ArrayType node) {
428                 if (skipNode(node))
429                         return;
430                 processSequential(node, node.getElementType());
431         }
432
433         @Override
434         public void endVisit(AssertStatement node) {
435                 if (skipNode(node))
436                         return;
437                 IfFlowInfo info= new IfFlowInfo();
438                 setFlowInfo(node, info);
439                 info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
440                 info.merge(getFlowInfo(node.getMessage()), null, fFlowContext);
441         }
442
443         @Override
444         public void endVisit(Assignment node) {
445                 if (skipNode(node))
446                         return;
447                 FlowInfo lhs= getFlowInfo(node.getLeftHandSide());
448                 FlowInfo rhs= getFlowInfo(node.getRightHandSide());
449                 if (lhs instanceof LocalFlowInfo) {
450                         LocalFlowInfo llhs= (LocalFlowInfo)lhs;
451                         llhs.setWriteAccess(fFlowContext);
452                         if (node.getOperator() != Assignment.Operator.ASSIGN) {
453                                 GenericSequentialFlowInfo tmp= createSequential();
454                                 tmp.merge(new LocalFlowInfo(llhs, FlowInfo.READ, fFlowContext), fFlowContext);
455                                 tmp.merge(rhs, fFlowContext);
456                                 rhs= tmp;
457                         }
458                 }
459                 GenericSequentialFlowInfo info= createSequential(node);
460                 // first process right and side and then left hand side.
461                 info.merge(rhs, fFlowContext);
462                 info.merge(lhs, fFlowContext);
463         }
464
465         @Override
466         public void endVisit(Block node) {
467                 if (skipNode(node))
468                         return;
469                 BlockFlowInfo info= createBlock();
470                 setFlowInfo(node, info);
471                 process(info, node.statements());
472         }
473
474         @Override
475         public void endVisit(BooleanLiteral node) {
476                 // Leaf node.
477         }
478
479         @Override
480         public void endVisit(BreakStatement node) {
481                 if (skipNode(node))
482                         return;
483                 setFlowInfo(node, createBranch(node.getLabel()));
484         }
485
486         @Override
487         public void endVisit(CastExpression node) {
488                 if (skipNode(node))
489                         return;
490                 processSequential(node, node.getType(), node.getExpression());
491         }
492
493         @Override
494         public void endVisit(CatchClause node) {
495                 if (skipNode(node))
496                         return;
497                 processSequential(node, node.getException(), node.getBody());
498         }
499
500         @Override
501         public void endVisit(CharacterLiteral node) {
502                 // Leaf node.
503         }
504
505         @Override
506         public void endVisit(ClassInstanceCreation node) {
507                 if (skipNode(node))
508                         return;
509                 GenericSequentialFlowInfo info= processSequential(node, node.getExpression());
510                 process(info, node.getType());
511                 process(info, node.arguments());
512                 process(info, node.getAnonymousClassDeclaration());
513         }
514
515         @Override
516         public void endVisit(CompilationUnit node) {
517                 if (skipNode(node))
518                         return;
519                 GenericSequentialFlowInfo info= processSequential(node, node.imports());
520                 process(info, node.types());
521         }
522
523         @Override
524         public void endVisit(ConditionalExpression node) {
525                 if (skipNode(node))
526                         return;
527                 ConditionalFlowInfo info= createConditional();
528                 setFlowInfo(node, info);
529                 info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
530                 info.merge(
531                         getFlowInfo(node.getThenExpression()),
532                         getFlowInfo(node.getElseExpression()),
533                         fFlowContext);
534         }
535
536         @Override
537         public void endVisit(ConstructorInvocation node) {
538                 if (skipNode(node))
539                         return;
540                 processSequential(node, node.arguments());
541         }
542
543         @Override
544         public void endVisit(ContinueStatement node) {
545                 if (skipNode(node))
546                         return;
547                 setFlowInfo(node, createBranch(node.getLabel()));
548         }
549
550         @Override
551         public void endVisit(DoStatement node) {
552                 if (skipNode(node))
553                         return;
554                 DoWhileFlowInfo info= createDoWhile();
555                 setFlowInfo(node, info);
556                 info.mergeAction(getFlowInfo(node.getBody()), fFlowContext);
557                 info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
558                 info.removeLabel(null);
559         }
560
561         @Override
562         public void endVisit(EmptyStatement node) {
563                 // Leaf node.
564         }
565
566         @Override
567         public void endVisit(EnhancedForStatement node) {
568                 if (skipNode(node))
569                         return;
570                 EnhancedForFlowInfo forInfo= createEnhancedFor();
571                 setFlowInfo(node, forInfo);
572                 forInfo.mergeParameter(getFlowInfo(node.getParameter()), fFlowContext);
573                 forInfo.mergeExpression(getFlowInfo(node.getExpression()), fFlowContext);
574                 forInfo.mergeAction(getFlowInfo(node.getBody()), fFlowContext);
575                 forInfo.removeLabel(null);
576         }
577
578         @Override
579         public void endVisit(EnumConstantDeclaration node) {
580                 if (skipNode(node))
581                         return;
582                 GenericSequentialFlowInfo info= processSequential(node, node.arguments());
583                 process(info, node.getAnonymousClassDeclaration());
584         }
585
586         @Override
587         public void endVisit(EnumDeclaration node) {
588                 if (skipNode(node))
589                         return;
590                 GenericSequentialFlowInfo info= processSequential(node, node.superInterfaceTypes());
591                 process(info, node.enumConstants());
592                 process(info, node.bodyDeclarations());
593                 info.setNoReturn();
594         }
595
596         @Override
597         public void endVisit(ExpressionStatement node) {
598                 if (skipNode(node))
599                         return;
600                 assignFlowInfo(node, node.getExpression());
601         }
602
603         @Override
604         public void endVisit(FieldAccess node) {
605                 if (skipNode(node))
606                         return;
607                 processSequential(node, node.getExpression(), node.getName());
608         }
609
610         @Override
611         public void endVisit(FieldDeclaration node) {
612                 if (skipNode(node))
613                         return;
614                 GenericSequentialFlowInfo info= processSequential(node, node.getType());
615                 process(info, node.fragments());
616         }
617
618         @Override
619         public void endVisit(ForStatement node) {
620                 if (skipNode(node))
621                         return;
622                 ForFlowInfo forInfo= createFor();
623                 setFlowInfo(node, forInfo);
624                 forInfo.mergeInitializer(createSequential(node.initializers()), fFlowContext);
625                 forInfo.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
626                 forInfo.mergeAction(getFlowInfo(node.getBody()), fFlowContext);
627                 // Increments are executed after the action.
628                 forInfo.mergeIncrement(createSequential(node.updaters()), fFlowContext);
629                 forInfo.removeLabel(null);
630         }
631
632         @Override
633         public void endVisit(IfStatement node) {
634                 if (skipNode(node))
635                         return;
636                 IfFlowInfo info= createIf();
637                 setFlowInfo(node, info);
638                 info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
639                 info.merge(getFlowInfo(node.getThenStatement()), getFlowInfo(node.getElseStatement()), fFlowContext);
640         }
641
642         @Override
643         public void endVisit(ImportDeclaration node) {
644                 if (skipNode(node))
645                         return;
646                 assignFlowInfo(node, node.getName());
647         }
648
649         @Override
650         public void endVisit(InfixExpression node) {
651                 if (skipNode(node))
652                         return;
653                 GenericSequentialFlowInfo info= processSequential(node, node.getLeftOperand(), node.getRightOperand());
654                 process(info, node.extendedOperands());
655         }
656
657         @Override
658         public void endVisit(InstanceofExpression node) {
659                 if (skipNode(node))
660                         return;
661                 processSequential(node, node.getLeftOperand(), node.getRightOperand());
662         }
663
664         @Override
665         public void endVisit(Initializer node) {
666                 if (skipNode(node))
667                         return;
668                 assignFlowInfo(node, node.getBody());
669         }
670
671         @Override
672         public void endVisit(Javadoc node) {
673                 // no influence on flow analysis
674         }
675
676         @Override
677         public void endVisit(LabeledStatement node) {
678                 if (skipNode(node))
679                         return;
680                 FlowInfo info= assignFlowInfo(node, node.getBody());
681                 if (info != null)
682                         info.removeLabel(node.getLabel());
683         }
684
685         @Override
686         public void endVisit(MarkerAnnotation node) {
687                 // nothing to do for marker annotations;
688         }
689
690         @Override
691         public void endVisit(MemberValuePair node) {
692                 if (skipNode(node))
693                         return;
694
695                 FlowInfo name= getFlowInfo(node.getName());
696                 FlowInfo value= getFlowInfo(node.getValue());
697                 if (name instanceof LocalFlowInfo) {
698                         LocalFlowInfo llhs= (LocalFlowInfo)name;
699                         llhs.setWriteAccess(fFlowContext);
700                 }
701                 GenericSequentialFlowInfo info= createSequential(node);
702                 // first process value and then name.
703                 info.merge(value, fFlowContext);
704                 info.merge(name, fFlowContext);
705
706         }
707
708         @Override
709         public void endVisit(MethodDeclaration node) {
710                 if (skipNode(node))
711                         return;
712                 GenericSequentialFlowInfo info= processSequential(node, node.getReturnType2());
713                 process(info, node.parameters());
714                 process(info, node.thrownExceptions());
715                 process(info, node.getBody());
716         }
717
718         @Override
719         public void endVisit(MethodInvocation node) {
720                 endVisitMethodInvocation(node, node.getExpression(), node.arguments(), getMethodBinding(node.getName()));
721         }
722
723         @Override
724         public void endVisit(NormalAnnotation node) {
725                 if (skipNode(node))
726                         return;
727                 GenericSequentialFlowInfo info= processSequential(node, node.getTypeName());
728                 process(info, node.values());
729         }
730
731         @Override
732         public void endVisit(NullLiteral node) {
733                 // Leaf node.
734         }
735
736         @Override
737         public void endVisit(NumberLiteral node) {
738                 // Leaf node.
739         }
740
741         @Override
742         public void endVisit(PackageDeclaration node) {
743                 if (skipNode(node))
744                         return;
745                 assignFlowInfo(node, node.getName());
746         }
747
748         @Override
749         public void endVisit(ParameterizedType node) {
750                 if (skipNode(node))
751                         return;
752                 GenericSequentialFlowInfo info= processSequential(node, node.getType());
753                 process(info, node.typeArguments());
754         }
755
756         @Override
757         public void endVisit(ParenthesizedExpression node) {
758                 if (skipNode(node))
759                         return;
760                 assignFlowInfo(node, node.getExpression());
761         }
762
763         @Override
764         public void endVisit(PostfixExpression node) {
765                 endVisitIncDecOperation(node, node.getOperand());
766         }
767
768         @Override
769         public void endVisit(PrefixExpression node) {
770                 PrefixExpression.Operator op= node.getOperator();
771                 if (PrefixExpression.Operator.INCREMENT.equals(op) || PrefixExpression.Operator.DECREMENT.equals(op)) {
772                         endVisitIncDecOperation(node, node.getOperand());
773                 } else {
774                         assignFlowInfo(node, node.getOperand());
775                 }
776         }
777
778         @Override
779         public void endVisit(PrimitiveType node) {
780                 // Leaf node
781         }
782
783         @Override
784         public void endVisit(QualifiedName node) {
785                 if (skipNode(node))
786                         return;
787                 processSequential(node, node.getQualifier(), node.getName());
788         }
789
790         @Override
791         public void endVisit(QualifiedType node) {
792                 if (skipNode(node))
793                         return;
794                 processSequential(node, node.getQualifier(), node.getName());
795         }
796
797         @Override
798         public void endVisit(ReturnStatement node) {
799                 if (skipNode(node))
800                         return;
801
802                 if (createReturnFlowInfo(node)) {
803                         ReturnFlowInfo info= createReturn(node);
804                         setFlowInfo(node, info);
805                         info.merge(getFlowInfo(node.getExpression()), fFlowContext);
806                 } else {
807                         assignFlowInfo(node, node.getExpression());
808                 }
809         }
810
811         @Override
812         public void endVisit(SimpleName node) {
813                 if (skipNode(node) || node.isDeclaration())
814                         return;
815                 IBinding binding= node.resolveBinding();
816                 if (binding instanceof IVariableBinding) {
817                         IVariableBinding variable= (IVariableBinding)binding;
818                         if (!variable.isField()) {
819                                 setFlowInfo(node, new LocalFlowInfo(
820                                         variable,
821                                         FlowInfo.READ,
822                                         fFlowContext));
823                         }
824                 } else if (binding instanceof ITypeBinding) {
825                         ITypeBinding type= (ITypeBinding)binding;
826                         if (type.isTypeVariable()) {
827                                 setFlowInfo(node, new TypeVariableFlowInfo(type, fFlowContext));
828                         }
829                 }
830         }
831
832         @Override
833         public void endVisit(SimpleType node) {
834                 if (skipNode(node))
835                         return;
836                 assignFlowInfo(node, node.getName());
837         }
838
839         @Override
840         public void endVisit(SingleMemberAnnotation node) {
841                 if (skipNode(node))
842                         return;
843                 assignFlowInfo(node, node.getValue());
844         }
845
846         @Override
847         public void endVisit(SingleVariableDeclaration node) {
848                 if (skipNode(node))
849                         return;
850
851                 IVariableBinding binding= node.resolveBinding();
852                 LocalFlowInfo nameInfo= null;
853                 Expression initializer= node.getInitializer();
854                 if (binding != null && !binding.isField() && initializer != null) {
855                         nameInfo= new LocalFlowInfo(binding, FlowInfo.WRITE, fFlowContext);
856                 }
857                 GenericSequentialFlowInfo info= processSequential(node, node.getType(), initializer);
858                 info.merge(nameInfo, fFlowContext);
859         }
860
861         @Override
862         public void endVisit(StringLiteral node) {
863                 // Leaf node
864         }
865
866         @Override
867         public void endVisit(SuperConstructorInvocation node) {
868                 endVisitMethodInvocation(node, node.getExpression(), node.arguments(), node.resolveConstructorBinding());
869         }
870
871         @Override
872         public void endVisit(SuperFieldAccess node) {
873                 if (skipNode(node))
874                         return;
875                 processSequential(node, node.getQualifier(), node.getName());
876         }
877
878         @Override
879         public void endVisit(SuperMethodInvocation node) {
880                 endVisitMethodInvocation(node, node.getQualifier(), node.arguments(), getMethodBinding(node.getName()));
881         }
882
883         @Override
884         public void endVisit(SwitchCase node) {
885                 endVisitNode(node);
886         }
887
888         @Override
889         public void endVisit(SwitchStatement node) {
890                 if (skipNode(node))
891                         return;
892                 endVisit(node, createSwitchData(node));
893         }
894
895         @Override
896         public void endVisit(SynchronizedStatement node) {
897                 if (skipNode(node))
898                         return;
899                 GenericSequentialFlowInfo info= processSequential(node, node.getExpression());
900                 process(info, node.getBody());
901         }
902
903         @Override
904         public void endVisit(ThisExpression node) {
905                 if (skipNode(node))
906                         return;
907                 assignFlowInfo(node, node.getQualifier());
908         }
909
910         @Override
911         public void endVisit(ThrowStatement node) {
912                 if (skipNode(node))
913                         return;
914                 ThrowFlowInfo info= createThrow();
915                 setFlowInfo(node, info);
916                 Expression expression= node.getExpression();
917                 info.merge(getFlowInfo(expression), fFlowContext);
918         }
919
920         @Override
921         public void endVisit(TryStatement node) {
922                 if (skipNode(node))
923                         return;
924                 TryFlowInfo info= createTry();
925                 setFlowInfo(node, info);
926                 info.mergeTry(getFlowInfo(node.getBody()), fFlowContext);
927                 for (Iterator<CatchClause> iter= node.catchClauses().iterator(); iter.hasNext();) {
928                         CatchClause element= iter.next();
929                         info.mergeCatch(getFlowInfo(element), fFlowContext);
930                 }
931                 info.mergeFinally(getFlowInfo(node.getFinally()), fFlowContext);
932         }
933
934         // TODO account for enums and annotations
935
936         @Override
937         public void endVisit(TypeDeclaration node) {
938                 if (skipNode(node))
939                         return;
940                 GenericSequentialFlowInfo info= processSequential(node, node.getSuperclassType());
941                 process(info, node.superInterfaceTypes());
942                 process(info, node.bodyDeclarations());
943                 info.setNoReturn();
944         }
945
946         @Override
947         public void endVisit(TypeDeclarationStatement node) {
948                 if (skipNode(node))
949                         return;
950                 assignFlowInfo(node, node.getDeclaration());
951         }
952
953         @Override
954         public void endVisit(TypeLiteral node) {
955                 if (skipNode(node))
956                         return;
957                 assignFlowInfo(node, node.getType());
958         }
959
960         @Override
961         public void endVisit(TypeParameter node) {
962                 if (skipNode(node))
963                         return;
964                 GenericSequentialFlowInfo info= processSequential(node, node.getName());
965                 process(info, node.typeBounds());
966         }
967
968         @Override
969         public void endVisit(VariableDeclarationExpression node) {
970                 if (skipNode(node))
971                         return;
972                 GenericSequentialFlowInfo info= processSequential(node, node.getType());
973                 process(info, node.fragments());
974         }
975
976         @Override
977         public void endVisit(VariableDeclarationStatement node) {
978                 if (skipNode(node))
979                         return;
980                 GenericSequentialFlowInfo info= processSequential(node, node.getType());
981                 process(info, node.fragments());
982         }
983
984         @Override
985         public void endVisit(VariableDeclarationFragment node) {
986                 if (skipNode(node))
987                         return;
988
989                 IVariableBinding binding= node.resolveBinding();
990                 LocalFlowInfo nameInfo= null;
991                 Expression initializer= node.getInitializer();
992                 if (binding != null && !binding.isField() && initializer != null) {
993                         nameInfo= new LocalFlowInfo(binding, FlowInfo.WRITE, fFlowContext);
994                 }
995                 GenericSequentialFlowInfo info= processSequential(node, initializer);
996                 info.merge(nameInfo, fFlowContext);
997         }
998
999         @Override
1000         public void endVisit(WhileStatement node) {
1001                 if (skipNode(node))
1002                         return;
1003                 WhileFlowInfo info= createWhile();
1004                 setFlowInfo(node, info);
1005                 info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
1006                 info.mergeAction(getFlowInfo(node.getBody()), fFlowContext);
1007                 info.removeLabel(null);
1008         }
1009
1010         @Override
1011         public void endVisit(WildcardType node) {
1012                 if (skipNode(node))
1013                         return;
1014                 assignFlowInfo(node, node.getBound());
1015         }
1016
1017         private void endVisitMethodInvocation(ASTNode node, ASTNode receiver, List<Expression> arguments, IMethodBinding binding) {
1018                 if (skipNode(node))
1019                         return;
1020                 MessageSendFlowInfo info= createMessageSendFlowInfo();
1021                 setFlowInfo(node, info);
1022                 for (Iterator<Expression> iter= arguments.iterator(); iter.hasNext();) {
1023                         Expression arg= iter.next();
1024                         info.mergeArgument(getFlowInfo(arg), fFlowContext);
1025                 }
1026                 info.mergeReceiver(getFlowInfo(receiver), fFlowContext);
1027         }
1028
1029         private void endVisitIncDecOperation(Expression node, Expression operand) {
1030                 if (skipNode(node))
1031                         return;
1032                 FlowInfo info= getFlowInfo(operand);
1033                 if (info instanceof LocalFlowInfo) {
1034                         // Normally we should do this in the parent node since the write access take place later.
1035                         // But I couldn't come up with a case where this influences the flow analysis. So I kept
1036                         // it here to simplify the code.
1037                         GenericSequentialFlowInfo result= createSequential(node);
1038                         result.merge(info, fFlowContext);
1039                         result.merge(
1040                                 new LocalFlowInfo((LocalFlowInfo)info, FlowInfo.WRITE, fFlowContext),
1041                                 fFlowContext);
1042                 } else {
1043                         setFlowInfo(node, info);
1044                 }
1045         }
1046
1047         private IMethodBinding getMethodBinding(Name name) {
1048                 if (name == null)
1049                         return null;
1050                 IBinding binding= name.resolveBinding();
1051                 if (binding instanceof IMethodBinding)
1052                         return (IMethodBinding)binding;
1053                 return null;
1054         }
1055 }