Link Here
|
1 |
/******************************************************************************* |
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2000, 2008 IBM Corporation and others. |
2 |
* Copyright (c) 2000, 2009 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
5 |
* which accompanies this distribution, and is available at |
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; |
31 |
import org.eclipse.jdt.core.dom.BodyDeclaration; |
33 |
import org.eclipse.jdt.core.dom.BodyDeclaration; |
|
|
34 |
import org.eclipse.jdt.core.dom.BreakStatement; |
32 |
import org.eclipse.jdt.core.dom.ClassInstanceCreation; |
35 |
import org.eclipse.jdt.core.dom.ClassInstanceCreation; |
33 |
import org.eclipse.jdt.core.dom.CompilationUnit; |
36 |
import org.eclipse.jdt.core.dom.CompilationUnit; |
34 |
import org.eclipse.jdt.core.dom.ConstructorInvocation; |
37 |
import org.eclipse.jdt.core.dom.ConstructorInvocation; |
|
|
38 |
import org.eclipse.jdt.core.dom.ContinueStatement; |
35 |
import org.eclipse.jdt.core.dom.DoStatement; |
39 |
import org.eclipse.jdt.core.dom.DoStatement; |
|
|
40 |
import org.eclipse.jdt.core.dom.EnhancedForStatement; |
36 |
import org.eclipse.jdt.core.dom.Expression; |
41 |
import org.eclipse.jdt.core.dom.Expression; |
37 |
import org.eclipse.jdt.core.dom.FieldAccess; |
42 |
import org.eclipse.jdt.core.dom.FieldAccess; |
38 |
import org.eclipse.jdt.core.dom.ForStatement; |
43 |
import org.eclipse.jdt.core.dom.ForStatement; |
Link Here
|
40 |
import org.eclipse.jdt.core.dom.ITypeBinding; |
45 |
import org.eclipse.jdt.core.dom.ITypeBinding; |
41 |
import org.eclipse.jdt.core.dom.IVariableBinding; |
46 |
import org.eclipse.jdt.core.dom.IVariableBinding; |
42 |
import org.eclipse.jdt.core.dom.Initializer; |
47 |
import org.eclipse.jdt.core.dom.Initializer; |
|
|
48 |
import org.eclipse.jdt.core.dom.LabeledStatement; |
43 |
import org.eclipse.jdt.core.dom.Message; |
49 |
import org.eclipse.jdt.core.dom.Message; |
44 |
import org.eclipse.jdt.core.dom.MethodDeclaration; |
50 |
import org.eclipse.jdt.core.dom.MethodDeclaration; |
45 |
import org.eclipse.jdt.core.dom.Name; |
51 |
import org.eclipse.jdt.core.dom.Name; |
46 |
import org.eclipse.jdt.core.dom.PrimitiveType; |
52 |
import org.eclipse.jdt.core.dom.PrimitiveType; |
47 |
import org.eclipse.jdt.core.dom.QualifiedName; |
53 |
import org.eclipse.jdt.core.dom.QualifiedName; |
48 |
import org.eclipse.jdt.core.dom.SimpleName; |
54 |
import org.eclipse.jdt.core.dom.SimpleName; |
|
|
55 |
import org.eclipse.jdt.core.dom.Statement; |
49 |
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; |
56 |
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; |
50 |
import org.eclipse.jdt.core.dom.SuperConstructorInvocation; |
57 |
import org.eclipse.jdt.core.dom.SuperConstructorInvocation; |
51 |
import org.eclipse.jdt.core.dom.SwitchCase; |
58 |
import org.eclipse.jdt.core.dom.SwitchCase; |
Link Here
|
55 |
import org.eclipse.jdt.core.dom.VariableDeclarationExpression; |
62 |
import org.eclipse.jdt.core.dom.VariableDeclarationExpression; |
56 |
import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
63 |
import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
57 |
import org.eclipse.jdt.core.dom.VariableDeclarationStatement; |
64 |
import org.eclipse.jdt.core.dom.VariableDeclarationStatement; |
|
|
65 |
import org.eclipse.jdt.core.dom.WhileStatement; |
58 |
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; |
66 |
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; |
59 |
|
67 |
|
60 |
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; |
68 |
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; |
Link Here
|
110 |
|
118 |
|
111 |
private boolean fForceStatic; |
119 |
private boolean fForceStatic; |
112 |
private boolean fIsLastStatementSelected; |
120 |
private boolean fIsLastStatementSelected; |
113 |
|
121 |
private SimpleName fEnclosingLoopLabel; |
|
|
122 |
|
114 |
public ExtractMethodAnalyzer(ICompilationUnit unit, Selection selection) throws CoreException { |
123 |
public ExtractMethodAnalyzer(ICompilationUnit unit, Selection selection) throws CoreException { |
115 |
super(unit, selection, false); |
124 |
super(unit, selection, false); |
116 |
} |
125 |
} |
Link Here
|
314 |
fInputFlowInfo= flowAnalyzer.perform(getSelectedNodes()); |
323 |
fInputFlowInfo= flowAnalyzer.perform(getSelectedNodes()); |
315 |
|
324 |
|
316 |
if (fInputFlowInfo.branches()) { |
325 |
if (fInputFlowInfo.branches()) { |
317 |
status.addFatalError(RefactoringCoreMessages.ExtractMethodAnalyzer_branch_mismatch, JavaStatusContext.create(fCUnit, getSelection())); |
326 |
String canHandleBranchesProblem= canHandleBranches(); |
318 |
fReturnKind= ERROR; |
327 |
if (canHandleBranchesProblem != null) { |
319 |
return status; |
328 |
status.addFatalError(canHandleBranchesProblem, JavaStatusContext.create(fCUnit, getSelection())); |
|
|
329 |
fReturnKind= ERROR; |
330 |
return status; |
331 |
} |
320 |
} |
332 |
} |
321 |
if (fInputFlowInfo.isValueReturn()) { |
333 |
if (fInputFlowInfo.isValueReturn()) { |
322 |
fReturnKind= RETURN_STATEMENT_VALUE; |
334 |
fReturnKind= RETURN_STATEMENT_VALUE; |
Link Here
|
341 |
return status; |
353 |
return status; |
342 |
} |
354 |
} |
343 |
|
355 |
|
|
|
356 |
private String canHandleBranches() { |
357 |
if (fReturnValue != null) |
358 |
return RefactoringCoreMessages.ExtractMethodAnalyzer_branch_mismatch; |
359 |
|
360 |
ASTNode[] selectedNodes= getSelectedNodes(); |
361 |
final ASTNode lastSelectedNode= selectedNodes[selectedNodes.length - 1]; |
362 |
Statement body= getParentLoopBody(lastSelectedNode.getParent()); |
363 |
if (!(body instanceof Block)) |
364 |
return RefactoringCoreMessages.ExtractMethodAnalyzer_branch_mismatch; |
365 |
|
366 |
if (body != lastSelectedNode) { |
367 |
Block block= (Block)body; |
368 |
List statements= block.statements(); |
369 |
ASTNode lastStatementInLoop= (ASTNode)statements.get(statements.size() - 1); |
370 |
if (lastSelectedNode != lastStatementInLoop) |
371 |
return RefactoringCoreMessages.ExtractMethodAnalyzer_branch_mismatch; |
372 |
} |
373 |
|
374 |
final String continueMatchesLoopProblem[]= { null }; |
375 |
for (int i= 0; i < selectedNodes.length; i++) { |
376 |
final ASTNode astNode= selectedNodes[i]; |
377 |
astNode.accept(new ASTVisitor() { |
378 |
ArrayList fLocalLoopLabels= new ArrayList(); |
379 |
|
380 |
public boolean visit(BreakStatement node) { |
381 |
SimpleName label= node.getLabel(); |
382 |
if (label != null && !fLocalLoopLabels.contains(label.getIdentifier())) { |
383 |
continueMatchesLoopProblem[0]= Messages.format( |
384 |
RefactoringCoreMessages.ExtractMethodAnalyzer_branch_break_mismatch, |
385 |
new Object[] { ("break " + label.getIdentifier()) }); //$NON-NLS-1$ |
386 |
} |
387 |
return false; |
388 |
} |
389 |
|
390 |
public boolean visit(LabeledStatement node) { |
391 |
SimpleName label= node.getLabel(); |
392 |
if (label != null) |
393 |
fLocalLoopLabels.add(label.getIdentifier()); |
394 |
return true; |
395 |
} |
396 |
|
397 |
public void endVisit(ContinueStatement node) { |
398 |
SimpleName label= node.getLabel(); |
399 |
if (label != null && !fLocalLoopLabels.contains(label.getIdentifier())) { |
400 |
if (fEnclosingLoopLabel == null || ! label.getIdentifier().equals(fEnclosingLoopLabel.getIdentifier())) { |
401 |
continueMatchesLoopProblem[0]= Messages.format( |
402 |
RefactoringCoreMessages.ExtractMethodAnalyzer_branch_continue_mismatch, |
403 |
new Object[] { "continue " + label.getIdentifier() }); //$NON-NLS-1$ |
404 |
} |
405 |
} |
406 |
} |
407 |
}); |
408 |
} |
409 |
return continueMatchesLoopProblem[0]; |
410 |
} |
411 |
|
412 |
private Statement getParentLoopBody(ASTNode node) { |
413 |
Statement stmt= null; |
414 |
ASTNode start= node; |
415 |
while (start != null |
416 |
&& !(start instanceof ForStatement) |
417 |
&& !(start instanceof DoStatement) |
418 |
&& !(start instanceof WhileStatement) |
419 |
&& !(start instanceof EnhancedForStatement)) { |
420 |
start= start.getParent(); |
421 |
} |
422 |
if (start instanceof ForStatement) { |
423 |
stmt= ((ForStatement)start).getBody(); |
424 |
} else if (start instanceof DoStatement) { |
425 |
stmt= ((DoStatement)start).getBody(); |
426 |
} else if (start instanceof WhileStatement) { |
427 |
stmt= ((WhileStatement)start).getBody(); |
428 |
} else if (start instanceof EnhancedForStatement) { |
429 |
stmt= ((EnhancedForStatement)start).getBody(); |
430 |
} |
431 |
if (start.getParent() instanceof LabeledStatement) { |
432 |
LabeledStatement labeledStatement= (LabeledStatement)start.getParent(); |
433 |
fEnclosingLoopLabel= labeledStatement.getLabel(); |
434 |
} |
435 |
return stmt; |
436 |
} |
437 |
|
344 |
private boolean isVoidMethod() { |
438 |
private boolean isVoidMethod() { |
345 |
// if we have an initializer |
439 |
// if we have an initializer |
346 |
if (fEnclosingMethodBinding == null) |
440 |
if (fEnclosingMethodBinding == null) |