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