Link Here
|
7 |
* |
7 |
* |
8 |
* Contributors: |
8 |
* Contributors: |
9 |
* IBM Corporation - initial API and implementation |
9 |
* IBM Corporation - initial API and implementation |
|
|
10 |
* Benjamin Muskalla <bmuskalla@eclipsesource.com> - [extract method] Extract method and continue https://bugs.eclipse.org/bugs/show_bug.cgi?id=48056 |
10 |
*******************************************************************************/ |
11 |
*******************************************************************************/ |
11 |
package org.eclipse.jdt.internal.corext.refactoring.code; |
12 |
package org.eclipse.jdt.internal.corext.refactoring.code; |
12 |
|
13 |
|
Link Here
|
25 |
import org.eclipse.jdt.core.compiler.ITerminalSymbols; |
26 |
import org.eclipse.jdt.core.compiler.ITerminalSymbols; |
26 |
import org.eclipse.jdt.core.dom.AST; |
27 |
import org.eclipse.jdt.core.dom.AST; |
27 |
import org.eclipse.jdt.core.dom.ASTNode; |
28 |
import org.eclipse.jdt.core.dom.ASTNode; |
|
|
29 |
import org.eclipse.jdt.core.dom.ASTVisitor; |
28 |
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; |
30 |
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; |
29 |
import org.eclipse.jdt.core.dom.Assignment; |
31 |
import org.eclipse.jdt.core.dom.Assignment; |
30 |
import org.eclipse.jdt.core.dom.Block; |
32 |
import org.eclipse.jdt.core.dom.Block; |
Link Here
|
32 |
import org.eclipse.jdt.core.dom.ClassInstanceCreation; |
34 |
import org.eclipse.jdt.core.dom.ClassInstanceCreation; |
33 |
import org.eclipse.jdt.core.dom.CompilationUnit; |
35 |
import org.eclipse.jdt.core.dom.CompilationUnit; |
34 |
import org.eclipse.jdt.core.dom.ConstructorInvocation; |
36 |
import org.eclipse.jdt.core.dom.ConstructorInvocation; |
|
|
37 |
import org.eclipse.jdt.core.dom.ContinueStatement; |
35 |
import org.eclipse.jdt.core.dom.DoStatement; |
38 |
import org.eclipse.jdt.core.dom.DoStatement; |
|
|
39 |
import org.eclipse.jdt.core.dom.EnhancedForStatement; |
36 |
import org.eclipse.jdt.core.dom.Expression; |
40 |
import org.eclipse.jdt.core.dom.Expression; |
37 |
import org.eclipse.jdt.core.dom.FieldAccess; |
41 |
import org.eclipse.jdt.core.dom.FieldAccess; |
38 |
import org.eclipse.jdt.core.dom.ForStatement; |
42 |
import org.eclipse.jdt.core.dom.ForStatement; |
Link Here
|
40 |
import org.eclipse.jdt.core.dom.ITypeBinding; |
44 |
import org.eclipse.jdt.core.dom.ITypeBinding; |
41 |
import org.eclipse.jdt.core.dom.IVariableBinding; |
45 |
import org.eclipse.jdt.core.dom.IVariableBinding; |
42 |
import org.eclipse.jdt.core.dom.Initializer; |
46 |
import org.eclipse.jdt.core.dom.Initializer; |
|
|
47 |
import org.eclipse.jdt.core.dom.LabeledStatement; |
43 |
import org.eclipse.jdt.core.dom.Message; |
48 |
import org.eclipse.jdt.core.dom.Message; |
44 |
import org.eclipse.jdt.core.dom.MethodDeclaration; |
49 |
import org.eclipse.jdt.core.dom.MethodDeclaration; |
45 |
import org.eclipse.jdt.core.dom.Name; |
50 |
import org.eclipse.jdt.core.dom.Name; |
46 |
import org.eclipse.jdt.core.dom.PrimitiveType; |
51 |
import org.eclipse.jdt.core.dom.PrimitiveType; |
47 |
import org.eclipse.jdt.core.dom.QualifiedName; |
52 |
import org.eclipse.jdt.core.dom.QualifiedName; |
48 |
import org.eclipse.jdt.core.dom.SimpleName; |
53 |
import org.eclipse.jdt.core.dom.SimpleName; |
|
|
54 |
import org.eclipse.jdt.core.dom.Statement; |
49 |
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; |
55 |
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; |
50 |
import org.eclipse.jdt.core.dom.SuperConstructorInvocation; |
56 |
import org.eclipse.jdt.core.dom.SuperConstructorInvocation; |
51 |
import org.eclipse.jdt.core.dom.SwitchCase; |
57 |
import org.eclipse.jdt.core.dom.SwitchCase; |
Link Here
|
55 |
import org.eclipse.jdt.core.dom.VariableDeclarationExpression; |
61 |
import org.eclipse.jdt.core.dom.VariableDeclarationExpression; |
56 |
import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
62 |
import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
57 |
import org.eclipse.jdt.core.dom.VariableDeclarationStatement; |
63 |
import org.eclipse.jdt.core.dom.VariableDeclarationStatement; |
|
|
64 |
import org.eclipse.jdt.core.dom.WhileStatement; |
58 |
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; |
65 |
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; |
59 |
|
66 |
|
60 |
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; |
67 |
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; |
Link Here
|
110 |
|
117 |
|
111 |
private boolean fForceStatic; |
118 |
private boolean fForceStatic; |
112 |
private boolean fIsLastStatementSelected; |
119 |
private boolean fIsLastStatementSelected; |
113 |
|
120 |
private SimpleName fEnclosingLoopLabel; |
|
|
121 |
|
114 |
public ExtractMethodAnalyzer(ICompilationUnit unit, Selection selection) throws CoreException { |
122 |
public ExtractMethodAnalyzer(ICompilationUnit unit, Selection selection) throws CoreException { |
115 |
super(unit, selection, false); |
123 |
super(unit, selection, false); |
116 |
} |
124 |
} |
Link Here
|
314 |
fInputFlowInfo= flowAnalyzer.perform(getSelectedNodes()); |
322 |
fInputFlowInfo= flowAnalyzer.perform(getSelectedNodes()); |
315 |
|
323 |
|
316 |
if (fInputFlowInfo.branches()) { |
324 |
if (fInputFlowInfo.branches()) { |
317 |
status.addFatalError(RefactoringCoreMessages.ExtractMethodAnalyzer_branch_mismatch, JavaStatusContext.create(fCUnit, getSelection())); |
325 |
if (!canHandleBranches()) { |
318 |
fReturnKind= ERROR; |
326 |
status.addFatalError(RefactoringCoreMessages.ExtractMethodAnalyzer_branch_mismatch, JavaStatusContext.create(fCUnit, getSelection())); |
319 |
return status; |
327 |
fReturnKind= ERROR; |
|
|
328 |
return status; |
329 |
} |
320 |
} |
330 |
} |
321 |
if (fInputFlowInfo.isValueReturn()) { |
331 |
if (fInputFlowInfo.isValueReturn()) { |
322 |
fReturnKind= RETURN_STATEMENT_VALUE; |
332 |
fReturnKind= RETURN_STATEMENT_VALUE; |
Link Here
|
341 |
return status; |
351 |
return status; |
342 |
} |
352 |
} |
343 |
|
353 |
|
|
|
354 |
private boolean canHandleBranches() { |
355 |
ASTNode[] selectedNodes= getSelectedNodes(); |
356 |
final ASTNode lastSelectedNode= selectedNodes[selectedNodes.length - 1]; |
357 |
Statement body= getParentLoopBody(lastSelectedNode.getParent()); |
358 |
ASTNode lastStatmentInLoop= null; |
359 |
if (body != null) { |
360 |
if (body instanceof Block) { |
361 |
Block block= (Block)body; |
362 |
lastStatmentInLoop= (ASTNode)block.statements().get(block.statements().size() - 1); |
363 |
} |
364 |
} |
365 |
final boolean continueMatchesLoop[]= new boolean[1]; |
366 |
continueMatchesLoop[0]= false; |
367 |
for (int i= 0; i < selectedNodes.length; i++) { |
368 |
final ASTNode astNode= selectedNodes[i]; |
369 |
astNode.accept(new ASTVisitor() { |
370 |
public void endVisit(ContinueStatement node) { |
371 |
super.endVisit(node); |
372 |
final SimpleName label= node.getLabel(); |
373 |
if (label == null) { |
374 |
continueMatchesLoop[0]= true; |
375 |
} else if (fEnclosingLoopLabel != null) { |
376 |
continueMatchesLoop[0]= label.getIdentifier().equals(fEnclosingLoopLabel.getIdentifier()); |
377 |
} |
378 |
} |
379 |
}); |
380 |
} |
381 |
return lastSelectedNode == lastStatmentInLoop && continueMatchesLoop[0] && fReturnValue == null; |
382 |
} |
383 |
|
384 |
private Statement getParentLoopBody(ASTNode node) { |
385 |
Statement stmt= null; |
386 |
ASTNode start= node; |
387 |
while (start != null |
388 |
&& !(start instanceof ForStatement) |
389 |
&& !(start instanceof DoStatement) |
390 |
&& !(start instanceof WhileStatement) |
391 |
&& !(start instanceof EnhancedForStatement)) { |
392 |
start= start.getParent(); |
393 |
} |
394 |
if (start instanceof ForStatement) { |
395 |
stmt= ((ForStatement)start).getBody(); |
396 |
} else if (start instanceof DoStatement) { |
397 |
stmt= ((DoStatement)start).getBody(); |
398 |
} else if (start instanceof WhileStatement) { |
399 |
stmt= ((WhileStatement)start).getBody(); |
400 |
} else if (start instanceof EnhancedForStatement) { |
401 |
stmt= ((EnhancedForStatement)start).getBody(); |
402 |
} |
403 |
if (start.getParent() instanceof LabeledStatement) { |
404 |
LabeledStatement labeledStatement= (LabeledStatement)start.getParent(); |
405 |
fEnclosingLoopLabel= labeledStatement.getLabel(); |
406 |
} |
407 |
return stmt; |
408 |
} |
409 |
|
344 |
private boolean isVoidMethod() { |
410 |
private boolean isVoidMethod() { |
345 |
// if we have an initializer |
411 |
// if we have an initializer |
346 |
if (fEnclosingMethodBinding == null) |
412 |
if (fEnclosingMethodBinding == null) |