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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.corext.refactoring.code.flow;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
18 import org.eclipse.jface.text.IRegion;
19 import org.eclipse.jface.text.Region;
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;
105 import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
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.
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
116 abstract class FlowAnalyzer extends GenericVisitor {
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;
125 public boolean hasDefaultCase() {
126 return fHasDefaultCase;
128 public void add(IRegion range, FlowInfo info) {
132 public IRegion[] getRanges() {
133 return fRanges.toArray(new IRegion[fRanges.size()]);
135 public FlowInfo[] getInfos() {
136 return fInfos.toArray(new FlowInfo[fInfos.size()]);
138 public FlowInfo getInfo(int index) {
139 return fInfos.get(index);
143 private HashMap<ASTNode, FlowInfo> fData = new HashMap<ASTNode, FlowInfo>(100);
144 /* package */ FlowContext fFlowContext= null;
146 public FlowAnalyzer(FlowContext context) {
147 fFlowContext= context;
150 protected abstract boolean createReturnFlowInfo(ReturnStatement node);
152 protected abstract boolean traverseNode(ASTNode node);
154 protected boolean skipNode(ASTNode node) {
155 return !traverseNode(node);
159 protected final boolean visitNode(ASTNode node) {
160 return traverseNode(node);
163 //---- Hooks to create Flow info objects. User may introduce their own infos.
165 protected ReturnFlowInfo createReturn(ReturnStatement statement) {
166 return new ReturnFlowInfo(statement);
169 protected ThrowFlowInfo createThrow() {
170 return new ThrowFlowInfo();
173 protected BranchFlowInfo createBranch(SimpleName label) {
174 return new BranchFlowInfo(label, fFlowContext);
177 protected GenericSequentialFlowInfo createSequential() {
178 return new GenericSequentialFlowInfo();
181 protected ConditionalFlowInfo createConditional() {
182 return new ConditionalFlowInfo();
185 protected EnhancedForFlowInfo createEnhancedFor() {
186 return new EnhancedForFlowInfo();
189 protected ForFlowInfo createFor() {
190 return new ForFlowInfo();
193 protected TryFlowInfo createTry() {
194 return new TryFlowInfo();
197 protected WhileFlowInfo createWhile() {
198 return new WhileFlowInfo();
201 protected IfFlowInfo createIf() {
202 return new IfFlowInfo();
205 protected DoWhileFlowInfo createDoWhile() {
206 return new DoWhileFlowInfo();
209 protected SwitchFlowInfo createSwitch() {
210 return new SwitchFlowInfo();
213 protected BlockFlowInfo createBlock() {
214 return new BlockFlowInfo();
217 protected MessageSendFlowInfo createMessageSendFlowInfo() {
218 return new MessageSendFlowInfo();
221 protected FlowContext getFlowContext() {
225 //---- Helpers to access flow analysis objects ----------------------------------------
227 protected FlowInfo getFlowInfo(ASTNode node) {
228 return fData.remove(node);
231 protected void setFlowInfo(ASTNode node, FlowInfo info) {
232 fData.put(node, info);
235 protected FlowInfo assignFlowInfo(ASTNode target, ASTNode source) {
236 FlowInfo result= getFlowInfo(source);
237 setFlowInfo(target, result);
241 protected FlowInfo accessFlowInfo(ASTNode node) {
242 return fData.get(node);
245 //---- Helpers to process sequential flow infos -------------------------------------
247 protected GenericSequentialFlowInfo processSequential(ASTNode parent, List<? extends ASTNode> nodes) {
248 GenericSequentialFlowInfo result= createSequential(parent);
249 process(result, nodes);
253 protected GenericSequentialFlowInfo processSequential(ASTNode parent, ASTNode node1) {
254 GenericSequentialFlowInfo result= createSequential(parent);
256 result.merge(getFlowInfo(node1), fFlowContext);
260 protected GenericSequentialFlowInfo processSequential(ASTNode parent, ASTNode node1, ASTNode node2) {
261 GenericSequentialFlowInfo result= createSequential(parent);
263 result.merge(getFlowInfo(node1), fFlowContext);
265 result.merge(getFlowInfo(node2), fFlowContext);
269 protected GenericSequentialFlowInfo createSequential(ASTNode parent) {
270 GenericSequentialFlowInfo result= createSequential();
271 setFlowInfo(parent, result);
275 protected GenericSequentialFlowInfo createSequential(List<? extends ASTNode> nodes) {
276 GenericSequentialFlowInfo result= createSequential();
277 process(result, nodes);
281 //---- Generic merge methods --------------------------------------------------------
283 protected void process(GenericSequentialFlowInfo info, List<? extends ASTNode> nodes) {
286 for (Iterator<? extends ASTNode> iter= nodes.iterator(); iter.hasNext();) {
287 info.merge(getFlowInfo(iter.next()), fFlowContext);
291 protected void process(GenericSequentialFlowInfo info, ASTNode node) {
293 info.merge(getFlowInfo(node), fFlowContext);
296 protected void process(GenericSequentialFlowInfo info, ASTNode node1, ASTNode node2) {
298 info.merge(getFlowInfo(node1), fFlowContext);
300 info.merge(getFlowInfo(node2), fFlowContext);
303 //---- special visit methods -------------------------------------------------------
306 public boolean visit(EmptyStatement node) {
307 // Empty statements aren't of any interest.
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);
321 Block finallyBlock= node.getFinally();
322 if (finallyBlock != null) {
323 finallyBlock.accept(this);
329 //---- Helper to process switch statement ----------------------------------------
331 protected SwitchData createSwitchData(SwitchStatement node) {
332 SwitchData result= new SwitchData();
333 List<Statement> statements= node.statements();
334 if (statements.isEmpty())
337 int start= -1, end= -1;
338 GenericSequentialFlowInfo info= null;
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();
348 info= createSequential();
349 start= statement.getStartPosition();
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();
358 info.merge(getFlowInfo(statement), fFlowContext);
360 end= statement.getStartPosition() + statement.getLength() - 1;
362 result.add(new Region(start, end - start + 1), info);
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);
377 //---- concret endVisit methods ---------------------------------------------------
380 public void endVisit(AnnotationTypeDeclaration node) {
383 GenericSequentialFlowInfo info= processSequential(node, node.bodyDeclarations());
388 public void endVisit(AnnotationTypeMemberDeclaration node) {
391 GenericSequentialFlowInfo info= processSequential(node, node.getType(), node.getDefault());
396 public void endVisit(AnonymousClassDeclaration node) {
399 FlowInfo info= processSequential(node, node.bodyDeclarations());
404 public void endVisit(ArrayAccess node) {
407 processSequential(node, node.getArray(), node.getIndex());
411 public void endVisit(ArrayCreation node) {
414 GenericSequentialFlowInfo info= processSequential(node, node.getType());
415 process(info, node.dimensions());
416 process(info, node.getInitializer());
420 public void endVisit(ArrayInitializer node) {
423 processSequential(node, node.expressions());
427 public void endVisit(ArrayType node) {
430 processSequential(node, node.getElementType());
434 public void endVisit(AssertStatement node) {
437 IfFlowInfo info= new IfFlowInfo();
438 setFlowInfo(node, info);
439 info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
440 info.merge(getFlowInfo(node.getMessage()), null, fFlowContext);
444 public void endVisit(Assignment node) {
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);
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);
466 public void endVisit(Block node) {
469 BlockFlowInfo info= createBlock();
470 setFlowInfo(node, info);
471 process(info, node.statements());
475 public void endVisit(BooleanLiteral node) {
480 public void endVisit(BreakStatement node) {
483 setFlowInfo(node, createBranch(node.getLabel()));
487 public void endVisit(CastExpression node) {
490 processSequential(node, node.getType(), node.getExpression());
494 public void endVisit(CatchClause node) {
497 processSequential(node, node.getException(), node.getBody());
501 public void endVisit(CharacterLiteral node) {
506 public void endVisit(ClassInstanceCreation node) {
509 GenericSequentialFlowInfo info= processSequential(node, node.getExpression());
510 process(info, node.getType());
511 process(info, node.arguments());
512 process(info, node.getAnonymousClassDeclaration());
516 public void endVisit(CompilationUnit node) {
519 GenericSequentialFlowInfo info= processSequential(node, node.imports());
520 process(info, node.types());
524 public void endVisit(ConditionalExpression node) {
527 ConditionalFlowInfo info= createConditional();
528 setFlowInfo(node, info);
529 info.mergeCondition(getFlowInfo(node.getExpression()), fFlowContext);
531 getFlowInfo(node.getThenExpression()),
532 getFlowInfo(node.getElseExpression()),
537 public void endVisit(ConstructorInvocation node) {
540 processSequential(node, node.arguments());
544 public void endVisit(ContinueStatement node) {
547 setFlowInfo(node, createBranch(node.getLabel()));
551 public void endVisit(DoStatement node) {
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);
562 public void endVisit(EmptyStatement node) {
567 public void endVisit(EnhancedForStatement node) {
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);
579 public void endVisit(EnumConstantDeclaration node) {
582 GenericSequentialFlowInfo info= processSequential(node, node.arguments());
583 process(info, node.getAnonymousClassDeclaration());
587 public void endVisit(EnumDeclaration node) {
590 GenericSequentialFlowInfo info= processSequential(node, node.superInterfaceTypes());
591 process(info, node.enumConstants());
592 process(info, node.bodyDeclarations());
597 public void endVisit(ExpressionStatement node) {
600 assignFlowInfo(node, node.getExpression());
604 public void endVisit(FieldAccess node) {
607 processSequential(node, node.getExpression(), node.getName());
611 public void endVisit(FieldDeclaration node) {
614 GenericSequentialFlowInfo info= processSequential(node, node.getType());
615 process(info, node.fragments());
619 public void endVisit(ForStatement node) {
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);
633 public void endVisit(IfStatement node) {
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);
643 public void endVisit(ImportDeclaration node) {
646 assignFlowInfo(node, node.getName());
650 public void endVisit(InfixExpression node) {
653 GenericSequentialFlowInfo info= processSequential(node, node.getLeftOperand(), node.getRightOperand());
654 process(info, node.extendedOperands());
658 public void endVisit(InstanceofExpression node) {
661 processSequential(node, node.getLeftOperand(), node.getRightOperand());
665 public void endVisit(Initializer node) {
668 assignFlowInfo(node, node.getBody());
672 public void endVisit(Javadoc node) {
673 // no influence on flow analysis
677 public void endVisit(LabeledStatement node) {
680 FlowInfo info= assignFlowInfo(node, node.getBody());
682 info.removeLabel(node.getLabel());
686 public void endVisit(MarkerAnnotation node) {
687 // nothing to do for marker annotations;
691 public void endVisit(MemberValuePair node) {
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);
701 GenericSequentialFlowInfo info= createSequential(node);
702 // first process value and then name.
703 info.merge(value, fFlowContext);
704 info.merge(name, fFlowContext);
709 public void endVisit(MethodDeclaration node) {
712 GenericSequentialFlowInfo info= processSequential(node, node.getReturnType2());
713 process(info, node.parameters());
714 process(info, node.thrownExceptions());
715 process(info, node.getBody());
719 public void endVisit(MethodInvocation node) {
720 endVisitMethodInvocation(node, node.getExpression(), node.arguments(), getMethodBinding(node.getName()));
724 public void endVisit(NormalAnnotation node) {
727 GenericSequentialFlowInfo info= processSequential(node, node.getTypeName());
728 process(info, node.values());
732 public void endVisit(NullLiteral node) {
737 public void endVisit(NumberLiteral node) {
742 public void endVisit(PackageDeclaration node) {
745 assignFlowInfo(node, node.getName());
749 public void endVisit(ParameterizedType node) {
752 GenericSequentialFlowInfo info= processSequential(node, node.getType());
753 process(info, node.typeArguments());
757 public void endVisit(ParenthesizedExpression node) {
760 assignFlowInfo(node, node.getExpression());
764 public void endVisit(PostfixExpression node) {
765 endVisitIncDecOperation(node, node.getOperand());
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());
774 assignFlowInfo(node, node.getOperand());
779 public void endVisit(PrimitiveType node) {
784 public void endVisit(QualifiedName node) {
787 processSequential(node, node.getQualifier(), node.getName());
791 public void endVisit(QualifiedType node) {
794 processSequential(node, node.getQualifier(), node.getName());
798 public void endVisit(ReturnStatement node) {
802 if (createReturnFlowInfo(node)) {
803 ReturnFlowInfo info= createReturn(node);
804 setFlowInfo(node, info);
805 info.merge(getFlowInfo(node.getExpression()), fFlowContext);
807 assignFlowInfo(node, node.getExpression());
812 public void endVisit(SimpleName node) {
813 if (skipNode(node) || node.isDeclaration())
815 IBinding binding= node.resolveBinding();
816 if (binding instanceof IVariableBinding) {
817 IVariableBinding variable= (IVariableBinding)binding;
818 if (!variable.isField()) {
819 setFlowInfo(node, new LocalFlowInfo(
824 } else if (binding instanceof ITypeBinding) {
825 ITypeBinding type= (ITypeBinding)binding;
826 if (type.isTypeVariable()) {
827 setFlowInfo(node, new TypeVariableFlowInfo(type, fFlowContext));
833 public void endVisit(SimpleType node) {
836 assignFlowInfo(node, node.getName());
840 public void endVisit(SingleMemberAnnotation node) {
843 assignFlowInfo(node, node.getValue());
847 public void endVisit(SingleVariableDeclaration node) {
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);
857 GenericSequentialFlowInfo info= processSequential(node, node.getType(), initializer);
858 info.merge(nameInfo, fFlowContext);
862 public void endVisit(StringLiteral node) {
867 public void endVisit(SuperConstructorInvocation node) {
868 endVisitMethodInvocation(node, node.getExpression(), node.arguments(), node.resolveConstructorBinding());
872 public void endVisit(SuperFieldAccess node) {
875 processSequential(node, node.getQualifier(), node.getName());
879 public void endVisit(SuperMethodInvocation node) {
880 endVisitMethodInvocation(node, node.getQualifier(), node.arguments(), getMethodBinding(node.getName()));
884 public void endVisit(SwitchCase node) {
889 public void endVisit(SwitchStatement node) {
892 endVisit(node, createSwitchData(node));
896 public void endVisit(SynchronizedStatement node) {
899 GenericSequentialFlowInfo info= processSequential(node, node.getExpression());
900 process(info, node.getBody());
904 public void endVisit(ThisExpression node) {
907 assignFlowInfo(node, node.getQualifier());
911 public void endVisit(ThrowStatement node) {
914 ThrowFlowInfo info= createThrow();
915 setFlowInfo(node, info);
916 Expression expression= node.getExpression();
917 info.merge(getFlowInfo(expression), fFlowContext);
921 public void endVisit(TryStatement node) {
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);
931 info.mergeFinally(getFlowInfo(node.getFinally()), fFlowContext);
934 // TODO account for enums and annotations
937 public void endVisit(TypeDeclaration node) {
940 GenericSequentialFlowInfo info= processSequential(node, node.getSuperclassType());
941 process(info, node.superInterfaceTypes());
942 process(info, node.bodyDeclarations());
947 public void endVisit(TypeDeclarationStatement node) {
950 assignFlowInfo(node, node.getDeclaration());
954 public void endVisit(TypeLiteral node) {
957 assignFlowInfo(node, node.getType());
961 public void endVisit(TypeParameter node) {
964 GenericSequentialFlowInfo info= processSequential(node, node.getName());
965 process(info, node.typeBounds());
969 public void endVisit(VariableDeclarationExpression node) {
972 GenericSequentialFlowInfo info= processSequential(node, node.getType());
973 process(info, node.fragments());
977 public void endVisit(VariableDeclarationStatement node) {
980 GenericSequentialFlowInfo info= processSequential(node, node.getType());
981 process(info, node.fragments());
985 public void endVisit(VariableDeclarationFragment node) {
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);
995 GenericSequentialFlowInfo info= processSequential(node, initializer);
996 info.merge(nameInfo, fFlowContext);
1000 public void endVisit(WhileStatement node) {
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);
1011 public void endVisit(WildcardType node) {
1014 assignFlowInfo(node, node.getBound());
1017 private void endVisitMethodInvocation(ASTNode node, ASTNode receiver, List<Expression> arguments, IMethodBinding binding) {
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);
1026 info.mergeReceiver(getFlowInfo(receiver), fFlowContext);
1029 private void endVisitIncDecOperation(Expression node, Expression operand) {
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);
1040 new LocalFlowInfo((LocalFlowInfo)info, FlowInfo.WRITE, fFlowContext),
1043 setFlowInfo(node, info);
1047 private IMethodBinding getMethodBinding(Name name) {
1050 IBinding binding= name.resolveBinding();
1051 if (binding instanceof IMethodBinding)
1052 return (IMethodBinding)binding;