1 package no.uio.ifi.refaktor.refactorings;
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.Comparator;
8 import java.util.HashMap;
9 import java.util.HashSet;
10 import java.util.Iterator;
11 import java.util.List;
13 import java.util.StringTokenizer;
15 import org.eclipse.core.runtime.Assert;
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.core.runtime.IProgressMonitor;
18 import org.eclipse.core.runtime.NullProgressMonitor;
19 import org.eclipse.core.runtime.SubProgressMonitor;
20 import org.eclipse.text.edits.MalformedTreeException;
21 import org.eclipse.text.edits.TextEditGroup;
23 import org.eclipse.ltk.core.refactoring.Change;
24 import org.eclipse.ltk.core.refactoring.Refactoring;
25 import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
26 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
27 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
28 import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
30 import org.eclipse.jdt.core.ICompilationUnit;
31 import org.eclipse.jdt.core.IJavaElement;
32 import org.eclipse.jdt.core.IJavaProject;
33 import org.eclipse.jdt.core.JavaModelException;
34 import org.eclipse.jdt.core.NamingConventions;
35 import org.eclipse.jdt.core.SourceRange;
36 import org.eclipse.jdt.core.compiler.IProblem;
37 import org.eclipse.jdt.core.dom.AST;
38 import org.eclipse.jdt.core.dom.ASTMatcher;
39 import org.eclipse.jdt.core.dom.ASTNode;
40 import org.eclipse.jdt.core.dom.ASTVisitor;
41 import org.eclipse.jdt.core.dom.Annotation;
42 import org.eclipse.jdt.core.dom.ArrayInitializer;
43 import org.eclipse.jdt.core.dom.AssertStatement;
44 import org.eclipse.jdt.core.dom.Assignment;
45 import org.eclipse.jdt.core.dom.Block;
46 import org.eclipse.jdt.core.dom.BodyDeclaration;
47 import org.eclipse.jdt.core.dom.CastExpression;
48 import org.eclipse.jdt.core.dom.CatchClause;
49 import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
50 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
51 import org.eclipse.jdt.core.dom.CompilationUnit;
52 import org.eclipse.jdt.core.dom.ConstructorInvocation;
53 import org.eclipse.jdt.core.dom.DoStatement;
54 import org.eclipse.jdt.core.dom.EnhancedForStatement;
55 import org.eclipse.jdt.core.dom.Expression;
56 import org.eclipse.jdt.core.dom.ExpressionStatement;
57 import org.eclipse.jdt.core.dom.FieldAccess;
58 import org.eclipse.jdt.core.dom.ForStatement;
59 import org.eclipse.jdt.core.dom.IBinding;
60 import org.eclipse.jdt.core.dom.IMethodBinding;
61 import org.eclipse.jdt.core.dom.ITypeBinding;
62 import org.eclipse.jdt.core.dom.IVariableBinding;
63 import org.eclipse.jdt.core.dom.IfStatement;
64 import org.eclipse.jdt.core.dom.InfixExpression;
65 import org.eclipse.jdt.core.dom.Initializer;
66 import org.eclipse.jdt.core.dom.LambdaExpression;
67 import org.eclipse.jdt.core.dom.MethodDeclaration;
68 import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
69 import org.eclipse.jdt.core.dom.Name;
70 import org.eclipse.jdt.core.dom.NullLiteral;
71 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
72 import org.eclipse.jdt.core.dom.PostfixExpression;
73 import org.eclipse.jdt.core.dom.PrefixExpression;
74 import org.eclipse.jdt.core.dom.QualifiedName;
75 import org.eclipse.jdt.core.dom.ReturnStatement;
76 import org.eclipse.jdt.core.dom.SimpleName;
77 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
78 import org.eclipse.jdt.core.dom.Statement;
79 import org.eclipse.jdt.core.dom.StringLiteral;
80 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
81 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
82 import org.eclipse.jdt.core.dom.SwitchCase;
83 import org.eclipse.jdt.core.dom.SwitchStatement;
84 import org.eclipse.jdt.core.dom.TryStatement;
85 import org.eclipse.jdt.core.dom.Type;
86 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
87 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
88 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
89 import org.eclipse.jdt.core.dom.WhileStatement;
90 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
91 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
92 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
93 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
94 import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
95 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
96 import org.eclipse.jdt.core.refactoring.descriptors.ExtractLocalDescriptor;
98 import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
99 import org.eclipse.jdt.internal.corext.Corext;
100 import org.eclipse.jdt.internal.corext.SourceRangeFactory;
101 import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
102 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
103 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
104 import org.eclipse.jdt.internal.corext.dom.Bindings;
105 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
106 import org.eclipse.jdt.internal.corext.dom.fragments.ASTFragmentFactory;
107 import org.eclipse.jdt.internal.corext.dom.fragments.IASTFragment;
108 import org.eclipse.jdt.internal.corext.dom.fragments.IExpressionFragment;
109 import org.eclipse.jdt.internal.corext.fix.LinkedProposalModel;
110 import org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroup;
111 import org.eclipse.jdt.internal.corext.refactoring.Checks;
112 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
113 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
114 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
115 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
116 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
117 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext;
118 import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes;
119 import org.eclipse.jdt.internal.corext.refactoring.code.CodeRefactoringUtil;
120 import org.eclipse.jdt.internal.corext.refactoring.code.ExtractTempRefactoring;
121 import org.eclipse.jdt.internal.corext.refactoring.rename.RefactoringAnalyzeUtil;
122 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
123 import org.eclipse.jdt.internal.corext.refactoring.util.NoCommentSourceRangeComputer;
124 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
125 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
126 import org.eclipse.jdt.internal.corext.util.Messages;
128 import org.eclipse.jdt.ui.JavaElementLabels;
130 import org.eclipse.jdt.internal.ui.JavaPlugin;
131 import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
132 import org.eclipse.jdt.internal.ui.text.correction.ASTResolving;
133 import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
134 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
137 * Extract Local Variable (from selected expression inside method or initializer).
139 * @author Anna Eilertsen
141 * TODO: Copied from ExtractTemp, will replace unused code with super-calls
143 public class ExtractTempWithAssertsRefactoring extends ExtractTempRefactoring {
145 private static final String ATTRIBUTE_REPLACE= "replace"; //$NON-NLS-1$
146 private static final String ATTRIBUTE_FINAL= "final"; //$NON-NLS-1$
148 private static final class ForStatementChecker extends ASTVisitor {
150 private final Collection<IVariableBinding> fForInitializerVariables;
152 private boolean fReferringToForVariable= false;
154 public ForStatementChecker(Collection<IVariableBinding> forInitializerVariables) {
155 Assert.isNotNull(forInitializerVariables);
156 fForInitializerVariables= forInitializerVariables;
159 public boolean isReferringToForVariable() {
160 return fReferringToForVariable;
164 public boolean visit(SimpleName node) {
165 IBinding binding= node.resolveBinding();
166 if (binding != null && fForInitializerVariables.contains(binding)) {
167 fReferringToForVariable= true;
175 private static boolean allArraysEqual(Object[][] arrays, int position) {
176 Object element= arrays[0][position];
177 for (int i= 0; i < arrays.length; i++) {
178 Object[] array= arrays[i];
179 if (!element.equals(array[position]))
185 private static boolean canReplace(IASTFragment fragment) {
186 ASTNode node= fragment.getAssociatedNode();
187 ASTNode parent= node.getParent();
188 if (parent instanceof VariableDeclarationFragment) {
189 VariableDeclarationFragment vdf= (VariableDeclarationFragment) parent;
190 if (node.equals(vdf.getName()))
193 if (isMethodParameter(node))
195 if (isThrowableInCatchBlock(node))
197 if (parent instanceof ExpressionStatement)
199 if (parent instanceof LambdaExpression)
201 if (isLeftValue(node))
203 if (isReferringToLocalVariableFromFor((Expression) node))
205 if (isUsedInForInitializerOrUpdater((Expression) node))
207 if (parent instanceof SwitchCase)
212 private static Object[] getArrayPrefix(Object[] array, int prefixLength) {
213 Assert.isTrue(prefixLength <= array.length);
214 Assert.isTrue(prefixLength >= 0);
215 Object[] prefix= new Object[prefixLength];
216 for (int i= 0; i < prefix.length; i++) {
222 // return List<IVariableBinding>
223 private static List<IVariableBinding> getForInitializedVariables(VariableDeclarationExpression variableDeclarations) {
224 List<IVariableBinding> forInitializerVariables= new ArrayList<IVariableBinding>(1);
225 for (Iterator<VariableDeclarationFragment> iter= variableDeclarations.fragments().iterator(); iter.hasNext();) {
226 VariableDeclarationFragment fragment= iter.next();
227 IVariableBinding binding= fragment.resolveBinding();
229 forInitializerVariables.add(binding);
231 return forInitializerVariables;
234 private static Object[] getLongestArrayPrefix(Object[][] arrays) {
236 if (arrays.length == 0)
237 return new Object[0];
238 int minArrayLength= arrays[0].length;
239 for (int i= 1; i < arrays.length; i++)
240 minArrayLength= Math.min(minArrayLength, arrays[i].length);
242 for (int i= 0; i < minArrayLength; i++) {
243 if (!allArraysEqual(arrays, i))
248 return new Object[0];
249 return getArrayPrefix(arrays[0], length + 1);
252 private static ASTNode[] getParents(ASTNode node) {
253 ASTNode current= node;
254 List<ASTNode> parents= new ArrayList<ASTNode>();
256 parents.add(current.getParent());
257 current= current.getParent();
258 } while (current.getParent() != null);
259 Collections.reverse(parents);
260 return parents.toArray(new ASTNode[parents.size()]);
263 private static boolean isLeftValue(ASTNode node) {
264 ASTNode parent= node.getParent();
265 if (parent instanceof Assignment) {
266 Assignment assignment= (Assignment) parent;
267 if (assignment.getLeftHandSide() == node)
270 if (parent instanceof PostfixExpression)
272 if (parent instanceof PrefixExpression) {
273 PrefixExpression.Operator op= ((PrefixExpression) parent).getOperator();
274 if (op.equals(PrefixExpression.Operator.DECREMENT))
276 if (op.equals(PrefixExpression.Operator.INCREMENT))
283 private static boolean isMethodParameter(ASTNode node) {
284 return (node instanceof SimpleName) && (node.getParent() instanceof SingleVariableDeclaration) && (node.getParent().getParent() instanceof MethodDeclaration);
287 private static boolean isReferringToLocalVariableFromFor(Expression expression) {
288 ASTNode current= expression;
289 ASTNode parent= current.getParent();
290 while (parent != null && !(parent instanceof BodyDeclaration)) {
291 if (parent instanceof ForStatement) {
292 ForStatement forStmt= (ForStatement) parent;
293 if (forStmt.initializers().contains(current) || forStmt.updaters().contains(current) || forStmt.getExpression() == current) {
294 List<Expression> initializers= forStmt.initializers();
295 if (initializers.size() == 1 && initializers.get(0) instanceof VariableDeclarationExpression) {
296 List<IVariableBinding> forInitializerVariables= getForInitializedVariables((VariableDeclarationExpression) initializers.get(0));
297 ForStatementChecker checker= new ForStatementChecker(forInitializerVariables);
298 expression.accept(checker);
299 if (checker.isReferringToForVariable())
305 parent= current.getParent();
310 private static boolean isThrowableInCatchBlock(ASTNode node) {
311 return (node instanceof SimpleName) && (node.getParent() instanceof SingleVariableDeclaration) && (node.getParent().getParent() instanceof CatchClause);
314 private static boolean isUsedInForInitializerOrUpdater(Expression expression) {
315 ASTNode parent= expression.getParent();
316 if (parent instanceof ForStatement) {
317 ForStatement forStmt= (ForStatement) parent;
318 return forStmt.initializers().contains(expression) || forStmt.updaters().contains(expression);
323 private static IASTFragment[] retainOnlyReplacableMatches(IASTFragment[] allMatches) {
324 List<IASTFragment> result= new ArrayList<IASTFragment>(allMatches.length);
325 for (int i= 0; i < allMatches.length; i++) {
326 if (canReplace(allMatches[i]))
327 result.add(allMatches[i]);
329 return result.toArray(new IASTFragment[result.size()]);
332 private CompilationUnit fCompilationUnitNode;
334 private CompilationUnitRewrite fCURewrite;
336 private ICompilationUnit fCu;
338 private boolean fDeclareFinal;
340 private String[] fExcludedVariableNames;
342 private boolean fReplaceAllOccurrences;
345 private IExpressionFragment fSelectedExpression;
347 private int fSelectionLength;
349 private int fSelectionStart;
351 private String fTempName;
352 private String[] fGuessedTempNames;
354 private boolean fCheckResultForCompileProblems;
356 private CompilationUnitChange fChange;
358 private LinkedProposalModel fLinkedProposalModel;
359 private MethodDeclaration methodDeclaration;
360 private String fSelectedText;
362 private static final String KEY_NAME= "name"; //$NON-NLS-1$
363 private static final String KEY_TYPE= "type"; //$NON-NLS-1$
367 * Creates a new extract temp refactoring
368 * @param unit the compilation unit, or <code>null</code> if invoked by scripting
369 * @param selectionStart start of selection
370 * @param selectionLength length of selection
373 public ExtractTempWithAssertsRefactoring(ICompilationUnit unit, int selectionStart, int selectionLength, String selectedText) {
374 super(unit, selectionStart, selectionLength);
375 Assert.isTrue(selectionStart >= 0);
376 Assert.isTrue(selectionLength >= 0);
377 fSelectionStart= selectionStart;
378 fSelectionLength= selectionLength;
379 fSelectedText = selectedText;
381 fCompilationUnitNode= null;
383 fReplaceAllOccurrences= true; // default
384 fDeclareFinal= false; // default
385 fTempName= ""; //$NON-NLS-1$
387 fLinkedProposalModel= null;
388 fCheckResultForCompileProblems= true;
391 public ExtractTempWithAssertsRefactoring(CompilationUnit astRoot, int selectionStart, int selectionLength) {
392 super(astRoot, selectionStart, selectionLength);
393 Assert.isTrue(selectionStart >= 0);
394 Assert.isTrue(selectionLength >= 0);
395 Assert.isTrue(astRoot.getTypeRoot() instanceof ICompilationUnit);
397 fSelectionStart= selectionStart;
398 fSelectionLength= selectionLength;
399 fCu= (ICompilationUnit) astRoot.getTypeRoot();
400 fCompilationUnitNode= astRoot;
402 fReplaceAllOccurrences= true; // default
403 fDeclareFinal= false; // default
404 fTempName= ""; //$NON-NLS-1$
406 fLinkedProposalModel= null;
407 fCheckResultForCompileProblems= true;
410 public void setCheckResultForCompileProblems(boolean checkResultForCompileProblems) {
411 fCheckResultForCompileProblems= checkResultForCompileProblems;
415 public void setLinkedProposalModel(LinkedProposalModel linkedProposalModel) {
416 fLinkedProposalModel= linkedProposalModel;
419 @SuppressWarnings("restriction")
420 private void addReplaceExpressionWithTemp() throws JavaModelException {
421 IASTFragment[] fragmentsToReplace= retainOnlyReplacableMatches(getMatchingFragments());
422 //TODO: should not have to prune duplicates here...
423 ASTRewrite rewrite= fCURewrite.getASTRewrite();
424 HashSet<IASTFragment> seen= new HashSet<IASTFragment>();
425 for (int i= 0; i < fragmentsToReplace.length; i++) {
426 IASTFragment fragment= fragmentsToReplace[i];
427 if (! seen.add(fragment))
429 SimpleName tempName= fCURewrite.getAST().newSimpleName(fTempName);
430 TextEditGroup description= fCURewrite.createGroupDescription(RefactoringCoreMessages.ExtractTempRefactoring_replace);
433 * Anna's code from here
435 if(fragmentsToReplace.length>1){
437 ASTNode fullStatement = getStatementFromFragment(fragment);
439 Statement assertStatement = getAssertStatement(fCURewrite.getAST());
443 StructuralPropertyDescriptor locationInParent = fullStatement.getLocationInParent();
444 if (isControlStatementBody(locationInParent)) {
445 Block replacement= rewrite.getAST().newBlock();
446 ListRewrite replacementRewrite= rewrite.getListRewrite(replacement, Block.STATEMENTS_PROPERTY);
447 replacementRewrite.insertFirst(assertStatement, null);
448 replacementRewrite.insertLast(rewrite.createMoveTarget(fullStatement), null);
449 rewrite.replace(fullStatement, replacement, null);
452 ASTNode block = fullStatement.getParent();
454 if(block instanceof SwitchStatement)
455 lr = rewrite.getListRewrite(block, SwitchStatement.STATEMENTS_PROPERTY);
457 lr = rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY);
458 lr.insertBefore(assertStatement, fullStatement, null);
462 * TODO: ask Volker about the following solution:
463 * less awkward than always adding and then removing, but problem
464 * of similarly structured nodes, since we don't connect so to say
465 * the index to the objects
468 // //remove duplicates
469 // List<Statement> ls = lr.getRewrittenList();
470 // boolean check = false;
471 // for (int j = 0; j < ls.size()-1; j++) {
472 // Statement statement = ls.get(j);
473 // Statement nextStatement = ls.get(j+1);
474 // if(statement.subtreeMatch(new ASTMatcher(), assertStatement) &&
475 // nextStatement.subtreeMatch(new ASTMatcher(), fullStatement)){
477 // //lr.remove(statement, null);
481 // if(!check) lr.insertBefore(assertStatement, fullStatement, null);
484 // The following code should never be needed, but is kept in case it will be useful
485 // //remove duplicates
486 // List<Statement> ls = lr.getRewrittenList();
487 // for (int j = 0; j < ls.size()-1; j++) {
488 // Statement statement = ls.get(j);
489 // Statement nextStatement = ls.get(j+1);
490 // if(statement.subtreeMatch(new ASTMatcher(), assertStatement) &&
491 // nextStatement.subtreeMatch(new ASTMatcher(), assertStatement)){
492 // lr.remove(nextStatement, null);
502 fragment.replace(rewrite, tempName, description);
505 if (fLinkedProposalModel != null)
506 fLinkedProposalModel.getPositionGroup(KEY_NAME, true).addPosition(rewrite.track(tempName), false);
510 private boolean isControlStatementBody(StructuralPropertyDescriptor locationInParent) {
511 return locationInParent == IfStatement.THEN_STATEMENT_PROPERTY
512 || locationInParent == IfStatement.ELSE_STATEMENT_PROPERTY
513 || locationInParent == ForStatement.BODY_PROPERTY
514 || locationInParent == EnhancedForStatement.BODY_PROPERTY
515 || locationInParent == DoStatement.BODY_PROPERTY
516 || locationInParent == WhileStatement.BODY_PROPERTY;
519 @SuppressWarnings("restriction")
520 private ASTNode getStatementFromFragment(IASTFragment fragment) {
521 ASTNode fullStatement = fragment.getAssociatedNode();
522 while( !isFullStatement(fullStatement)){
523 Object c = fullStatement.getClass();
524 System.out.println(fullStatement + " has class ");
525 System.out.println(c);
526 fullStatement = fullStatement.getParent();
528 System.out.println("Decided on " + fullStatement + " because it is a " + fullStatement.getClass());
529 return fullStatement;
532 private boolean isFullStatement(ASTNode fullStatement) {
533 return fullStatement.getLocationInParent() == Block.STATEMENTS_PROPERTY || fullStatement.getLocationInParent() == SwitchStatement.STATEMENTS_PROPERTY;
534 // return fullStatement instanceof ExpressionStatement
535 // || fullStatement instanceof ReturnStatement
536 // || fullStatement instanceof IfStatement
537 // || fullStatement instanceof ForStatement;
542 * @param ast the AST the Statement will belong to
543 * @return the assert statement, belonging to the input AST, asserting that the temp == selectedExpression
545 private Statement getAssertStatement(AST ast){
546 AssertStatement assertStatement = ast.newAssertStatement();
547 InfixExpression infixExpression = ast.newInfixExpression();
549 infixExpression.setLeftOperand(ast.newSimpleName(fTempName));
550 infixExpression.setOperator(InfixExpression.Operator.EQUALS);
552 infixExpression.setRightOperand(ast.newName(fSelectedText));
553 assertStatement.setExpression(infixExpression);
554 StringLiteral stringLiteral = ast.newStringLiteral();
555 stringLiteral.setLiteralValue("The Extract Local refactoring has broken the program due to aliasing issues!");
556 assertStatement.setMessage(stringLiteral);
557 return assertStatement;
560 private RefactoringStatus checkExpression() throws JavaModelException {
561 Expression selectedExpression= getSelectedExpression().getAssociatedExpression();
562 if (selectedExpression != null) {
563 final ASTNode parent= selectedExpression.getParent();
564 if (selectedExpression instanceof NullLiteral) {
565 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_null_literals);
566 } else if (selectedExpression instanceof ArrayInitializer) {
567 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_array_initializer);
568 } else if (selectedExpression instanceof Assignment) {
569 if (parent instanceof Expression && !(parent instanceof ParenthesizedExpression))
570 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_assignment);
573 } else if (selectedExpression instanceof SimpleName) {
574 if ((((SimpleName) selectedExpression)).isDeclaration())
575 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_names_in_declarations);
576 if (parent instanceof QualifiedName && selectedExpression.getLocationInParent() == QualifiedName.NAME_PROPERTY || parent instanceof FieldAccess && selectedExpression.getLocationInParent() == FieldAccess.NAME_PROPERTY)
577 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_select_expression);
578 } else if (selectedExpression instanceof VariableDeclarationExpression && parent instanceof TryStatement) {
579 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_resource_in_try_with_resources);
586 // !! Same as in ExtractConstantRefactoring
587 private RefactoringStatus checkExpressionFragmentIsRValue() throws JavaModelException {
588 switch (Checks.checkExpressionIsRValue(getSelectedExpression().getAssociatedExpression())) {
589 case Checks.NOT_RVALUE_MISC:
590 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.ExtractTempRefactoring_select_expression, null, Corext.getPluginId(), RefactoringStatusCodes.EXPRESSION_NOT_RVALUE, null);
591 case Checks.NOT_RVALUE_VOID:
592 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.ExtractTempRefactoring_no_void, null, Corext.getPluginId(), RefactoringStatusCodes.EXPRESSION_NOT_RVALUE_VOID, null);
593 case Checks.IS_RVALUE_GUESSED:
594 case Checks.IS_RVALUE:
595 return new RefactoringStatus();
597 Assert.isTrue(false);
602 private ITypeBinding guessBindingForReference(Expression expression) {
603 ITypeBinding binding= expression.resolveTypeBinding();
604 if (binding == null) {
605 binding= ASTResolving.guessBindingForReference(expression);
611 public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
613 pm.beginTask(RefactoringCoreMessages.ExtractTempRefactoring_checking_preconditions, 4);
615 fCURewrite= new CompilationUnitRewrite(fCu, fCompilationUnitNode);
616 fCURewrite.getASTRewrite().setTargetSourceRangeComputer(new NoCommentSourceRangeComputer());
618 doCreateChange(new SubProgressMonitor(pm, 2));
620 fChange= fCURewrite.createChange(RefactoringCoreMessages.ExtractTempRefactoring_change_name, true, new SubProgressMonitor(pm, 1));
622 RefactoringStatus result= new RefactoringStatus();
623 if (Arrays.asList(getExcludedVariableNames()).contains(fTempName))
624 result.addWarning(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_another_variable, BasicElementLabels.getJavaElementName(fTempName)));
626 result.merge(checkMatchingFragments());
628 fChange.setKeepPreviewEdits(true);
630 if (fCheckResultForCompileProblems) {
631 checkNewSource(new SubProgressMonitor(pm, 1), result);
635 }catch (MalformedTreeException e){
636 System.out.println("Debug: catched malformedTreeException for change w parent " + e.getParent() + " and child " + e.getChild());
644 private final ExtractLocalDescriptor createRefactoringDescriptor() {
645 final Map<String, String> arguments= new HashMap<String, String>();
646 String project= null;
647 IJavaProject javaProject= fCu.getJavaProject();
648 if (javaProject != null)
649 project= javaProject.getElementName();
650 final String description= Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_descriptor_description_short, BasicElementLabels.getJavaElementName(fTempName));
651 final String expression= ASTNodes.asString(fSelectedExpression.getAssociatedExpression());
652 final String header= Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_descriptor_description, new String[] { BasicElementLabels.getJavaElementName(fTempName), BasicElementLabels.getJavaCodeString(expression)});
653 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
654 comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_name_pattern, BasicElementLabels.getJavaElementName(fTempName)));
655 final BodyDeclaration decl= (BodyDeclaration) ASTNodes.getParent(fSelectedExpression.getAssociatedExpression(), BodyDeclaration.class);
656 if (decl instanceof MethodDeclaration) {
657 final IMethodBinding method= ((MethodDeclaration) decl).resolveBinding();
658 final String label= method != null ? BindingLabelProvider.getBindingLabel(method, JavaElementLabels.ALL_FULLY_QUALIFIED) : BasicElementLabels.getJavaElementName('{' + JavaElementLabels.ELLIPSIS_STRING + '}');
659 comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_destination_pattern, label));
661 comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_expression_pattern, BasicElementLabels.getJavaCodeString(expression)));
662 if (fReplaceAllOccurrences)
663 comment.addSetting(RefactoringCoreMessages.ExtractTempRefactoring_replace_occurrences);
665 comment.addSetting(RefactoringCoreMessages.ExtractTempRefactoring_declare_final);
666 final ExtractLocalDescriptor descriptor= RefactoringSignatureDescriptorFactory.createExtractLocalDescriptor(project, description, comment.asString(), arguments, RefactoringDescriptor.NONE);
667 arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(project, fCu));
668 arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME, fTempName);
669 arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION, new Integer(fSelectionStart).toString() + " " + new Integer(fSelectionLength).toString()); //$NON-NLS-1$
670 arguments.put(ATTRIBUTE_REPLACE, Boolean.valueOf(fReplaceAllOccurrences).toString());
671 arguments.put(ATTRIBUTE_FINAL, Boolean.valueOf(fDeclareFinal).toString());
675 private void doCreateChange(IProgressMonitor pm) throws CoreException {
677 pm.beginTask(RefactoringCoreMessages.ExtractTempRefactoring_checking_preconditions, 1);
679 createTempDeclaration();
680 } catch (CoreException exception) {
681 JavaPlugin.log(exception);
683 addReplaceExpressionWithTemp();
689 private void checkNewSource(SubProgressMonitor monitor, RefactoringStatus result) throws CoreException {
690 String newCuSource= fChange.getPreviewContent(new NullProgressMonitor());
691 CompilationUnit newCUNode= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL).parse(newCuSource, fCu, true, true, monitor);
692 IProblem[] newProblems= RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, fCompilationUnitNode);
693 for (int i= 0; i < newProblems.length; i++) {
694 IProblem problem= newProblems[i];
695 if (problem.isError())
696 result.addEntry(new RefactoringStatusEntry((problem.isError() ? RefactoringStatus.ERROR : RefactoringStatus.WARNING), problem.getMessage(), new JavaStringStatusContext(newCuSource, SourceRangeFactory.create(problem))));
701 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
703 pm.beginTask("", 6); //$NON-NLS-1$
705 RefactoringStatus result= Checks.validateModifiesFiles(ResourceUtil.getFiles(new ICompilationUnit[] { fCu}), getValidationContext());
706 if (result.hasFatalError())
709 if (fCompilationUnitNode == null) {
710 fCompilationUnitNode= RefactoringASTParser.parseWithASTProvider(fCu, true, new SubProgressMonitor(pm, 3));
715 result.merge(checkSelection(new SubProgressMonitor(pm, 3)));
716 if (!result.hasFatalError() && isLiteralNodeSelected())
717 fReplaceAllOccurrences= false;
725 private RefactoringStatus checkMatchingFragments() throws JavaModelException {
726 RefactoringStatus result= new RefactoringStatus();
727 IASTFragment[] matchingFragments= getMatchingFragments();
728 for (int i= 0; i < matchingFragments.length; i++) {
729 ASTNode node= matchingFragments[i].getAssociatedNode();
730 if (isLeftValue(node) && !isReferringToLocalVariableFromFor((Expression) node)) {
731 String msg= RefactoringCoreMessages.ExtractTempRefactoring_assigned_to;
732 result.addWarning(msg, JavaStatusContext.create(fCu, node));
738 private RefactoringStatus checkSelection(IProgressMonitor pm) throws JavaModelException {
740 pm.beginTask("", 8); //$NON-NLS-1$
742 IExpressionFragment selectedExpression= getSelectedExpression();
744 if (selectedExpression == null) {
745 String message= RefactoringCoreMessages.ExtractTempRefactoring_select_expression;
746 return CodeRefactoringUtil.checkMethodSyntaxErrors(fSelectionStart, fSelectionLength, fCompilationUnitNode, message);
750 if (isUsedInExplicitConstructorCall())
751 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_explicit_constructor);
754 ASTNode associatedNode= selectedExpression.getAssociatedNode();
755 if (getEnclosingBodyNode() == null || ASTNodes.getParent(associatedNode, Annotation.class) != null)
756 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_expr_in_method_or_initializer);
759 if (associatedNode instanceof Name && associatedNode.getParent() instanceof ClassInstanceCreation && associatedNode.getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY)
760 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_name_in_new);
763 RefactoringStatus result= new RefactoringStatus();
764 result.merge(checkExpression());
765 if (result.hasFatalError())
769 result.merge(checkExpressionFragmentIsRValue());
770 if (result.hasFatalError())
774 if (isUsedInForInitializerOrUpdater(getSelectedExpression().getAssociatedExpression()))
775 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_for_initializer_updater);
778 if (isReferringToLocalVariableFromFor(getSelectedExpression().getAssociatedExpression()))
779 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_refers_to_for_variable);
788 public RefactoringStatus checkTempName(String newName) {
789 RefactoringStatus status= Checks.checkTempName(newName, fCu);
790 if (Arrays.asList(getExcludedVariableNames()).contains(newName))
791 status.addWarning(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_another_variable, BasicElementLabels.getJavaElementName(newName)));
795 private void createAndInsertTempDeclaration() throws CoreException {
796 Expression initializer= getSelectedExpression().createCopyTarget(fCURewrite.getASTRewrite(), true);
797 VariableDeclarationStatement vds= createTempDeclaration(initializer);
799 IASTFragment[] replacableMatches= retainOnlyReplacableMatches(getMatchingFragments());
800 if (!fReplaceAllOccurrences
801 || replacableMatches.length == 0
802 || replacableMatches.length == 1 && replacableMatches[0].equals(getSelectedExpression().getAssociatedExpression())) {
803 insertAt(getSelectedExpression().getAssociatedNode(), vds);
807 ASTNode[] firstReplaceNodeParents= getParents(getFirstReplacedExpression().getAssociatedNode());
808 ASTNode[] commonPath= findDeepestCommonSuperNodePathForReplacedNodes();
809 Assert.isTrue(commonPath.length <= firstReplaceNodeParents.length);
811 ASTNode deepestCommonParent= firstReplaceNodeParents[commonPath.length - 1];
812 if (deepestCommonParent instanceof Block)
813 insertAt(firstReplaceNodeParents[commonPath.length], vds);
815 insertAt(deepestCommonParent, vds);
818 private VariableDeclarationStatement createTempDeclaration(Expression initializer) throws CoreException {
819 AST ast= fCURewrite.getAST();
821 VariableDeclarationFragment vdf= ast.newVariableDeclarationFragment();
822 vdf.setName(ast.newSimpleName(fTempName));
823 vdf.setInitializer(initializer);
825 VariableDeclarationStatement vds= ast.newVariableDeclarationStatement(vdf);
827 vds.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD));
829 vds.setType(createTempType());
831 if (fLinkedProposalModel != null) {
832 ASTRewrite rewrite= fCURewrite.getASTRewrite();
833 LinkedProposalPositionGroup nameGroup= fLinkedProposalModel.getPositionGroup(KEY_NAME, true);
834 nameGroup.addPosition(rewrite.track(vdf.getName()), true);
836 String[] nameSuggestions= guessTempNames();
837 if (nameSuggestions.length > 0 && !nameSuggestions[0].equals(fTempName)) {
838 nameGroup.addProposal(fTempName, null, nameSuggestions.length + 1);
840 for (int i= 0; i < nameSuggestions.length; i++) {
841 nameGroup.addProposal(nameSuggestions[i], null, nameSuggestions.length - i);
847 private void insertAt(ASTNode target, Statement declaration) {
848 ASTRewrite rewrite= fCURewrite.getASTRewrite();
849 TextEditGroup groupDescription= fCURewrite.createGroupDescription(RefactoringCoreMessages.ExtractTempRefactoring_declare_local_variable);
851 ASTNode parent= target.getParent();
852 StructuralPropertyDescriptor locationInParent= target.getLocationInParent();
853 while (locationInParent != Block.STATEMENTS_PROPERTY && locationInParent != SwitchStatement.STATEMENTS_PROPERTY) {
854 if (isControlStatementBody(locationInParent)) {
855 // create intermediate block if target was the body property of a control statement:
856 Block replacement= rewrite.getAST().newBlock();
857 ListRewrite replacementRewrite= rewrite.getListRewrite(replacement, Block.STATEMENTS_PROPERTY);
858 replacementRewrite.insertFirst(declaration, null);
859 replacementRewrite.insertLast(rewrite.createMoveTarget(target), null);
860 rewrite.replace(target, replacement, groupDescription);
862 } else if (locationInParent == LambdaExpression.BODY_PROPERTY && ((LambdaExpression) parent).getBody() instanceof Expression) {
863 Block replacement= rewrite.getAST().newBlock();
864 ListRewrite replacementRewrite= rewrite.getListRewrite(replacement, Block.STATEMENTS_PROPERTY);
865 replacementRewrite.insertFirst(declaration, null);
866 ASTNode moveTarget= rewrite.createMoveTarget(target);
867 AST ast= rewrite.getAST();
868 if (Bindings.isVoidType(((LambdaExpression) parent).resolveMethodBinding().getReturnType())) {
869 ExpressionStatement expressionStatement= ast.newExpressionStatement((Expression) moveTarget);
870 moveTarget= expressionStatement;
872 ReturnStatement returnStatement= ast.newReturnStatement();
873 returnStatement.setExpression((Expression) moveTarget);
874 moveTarget= returnStatement;
876 replacementRewrite.insertLast(moveTarget, null);
877 rewrite.replace(target, replacement, groupDescription);
881 parent= parent.getParent();
882 locationInParent= target.getLocationInParent();
884 ListRewrite listRewrite= rewrite.getListRewrite(parent, (ChildListPropertyDescriptor)locationInParent);
885 listRewrite.insertBefore(declaration, target, groupDescription);
889 public Change createChange(IProgressMonitor pm) throws CoreException {
891 pm.beginTask(RefactoringCoreMessages.ExtractTempRefactoring_checking_preconditions, 1);
893 ExtractLocalDescriptor descriptor= createRefactoringDescriptor();
894 fChange.setDescriptor(new RefactoringChangeDescriptor(descriptor));
901 private void createTempDeclaration() throws CoreException {
902 if (shouldReplaceSelectedExpressionWithTempDeclaration())
903 replaceSelectedExpressionWithTempDeclaration();
905 createAndInsertTempDeclaration();
908 public boolean declareFinal() {
909 return fDeclareFinal;
912 private ASTNode[] findDeepestCommonSuperNodePathForReplacedNodes() throws JavaModelException {
913 ASTNode[] matchNodes= getMatchNodes();
915 ASTNode[][] matchingNodesParents= new ASTNode[matchNodes.length][];
916 for (int i= 0; i < matchNodes.length; i++) {
917 matchingNodesParents[i]= getParents(matchNodes[i]);
919 List<Object> l= Arrays.asList(getLongestArrayPrefix(matchingNodesParents));
920 return l.toArray(new ASTNode[l.size()]);
923 private ASTNode getEnclosingBodyNode() throws JavaModelException {
924 ASTNode node= getSelectedExpression().getAssociatedNode();
926 // expression must be in a method, lambda or initializer body
927 // make sure it is not in method or parameter annotation
928 StructuralPropertyDescriptor location= null;
929 while (node != null && !(node instanceof BodyDeclaration)) {
930 location= node.getLocationInParent();
931 node= node.getParent();
932 if (node instanceof LambdaExpression) {
936 if (location == MethodDeclaration.BODY_PROPERTY || location == Initializer.BODY_PROPERTY
937 || (location == LambdaExpression.BODY_PROPERTY && ((LambdaExpression) node).resolveMethodBinding() != null)) {
938 return (ASTNode) node.getStructuralProperty(location);
943 private String[] getExcludedVariableNames() {
944 if (fExcludedVariableNames == null) {
946 IBinding[] bindings= new ScopeAnalyzer(fCompilationUnitNode).getDeclarationsInScope(getSelectedExpression().getStartPosition(), ScopeAnalyzer.VARIABLES
947 | ScopeAnalyzer.CHECK_VISIBILITY);
948 fExcludedVariableNames= new String[bindings.length];
949 for (int i= 0; i < bindings.length; i++) {
950 fExcludedVariableNames[i]= bindings[i].getName();
952 } catch (JavaModelException e) {
953 fExcludedVariableNames= new String[0];
956 return fExcludedVariableNames;
959 private IExpressionFragment getFirstReplacedExpression() throws JavaModelException {
960 if (!fReplaceAllOccurrences)
961 return getSelectedExpression();
962 IASTFragment[] nodesToReplace= retainOnlyReplacableMatches(getMatchingFragments());
963 if (nodesToReplace.length == 0)
964 return getSelectedExpression();
965 Comparator<IASTFragment> comparator= new Comparator<IASTFragment>() {
967 public int compare(IASTFragment o1, IASTFragment o2) {
968 return o1.getStartPosition() - o2.getStartPosition();
971 Arrays.sort(nodesToReplace, comparator);
972 return (IExpressionFragment) nodesToReplace[0];
975 private IASTFragment[] getMatchingFragments() throws JavaModelException {
976 if (fReplaceAllOccurrences) {
977 IASTFragment[] allMatches= ASTFragmentFactory.createFragmentForFullSubtree(getEnclosingBodyNode()).getSubFragmentsMatching(getSelectedExpression());
980 return new IASTFragment[] { getSelectedExpression()};
983 private ASTNode[] getMatchNodes() throws JavaModelException {
984 IASTFragment[] matches= retainOnlyReplacableMatches(getMatchingFragments());
985 ASTNode[] result= new ASTNode[matches.length];
986 for (int i= 0; i < matches.length; i++)
987 result[i]= matches[i].getAssociatedNode();
992 public String getName() {
993 return RefactoringCoreMessages.ExtractTempRefactoring_name;
997 private IExpressionFragment getSelectedExpression() throws JavaModelException {
998 if (fSelectedExpression != null)
999 return fSelectedExpression;
1000 IASTFragment selectedFragment= ASTFragmentFactory.createFragmentForSourceRange(new SourceRange(fSelectionStart, fSelectionLength), fCompilationUnitNode, fCu);
1002 if (selectedFragment instanceof IExpressionFragment && !Checks.isInsideJavadoc(selectedFragment.getAssociatedNode())) {
1003 fSelectedExpression= (IExpressionFragment) selectedFragment;
1004 } else if (selectedFragment != null) {
1005 if (selectedFragment.getAssociatedNode() instanceof ExpressionStatement) {
1006 ExpressionStatement exprStatement= (ExpressionStatement) selectedFragment.getAssociatedNode();
1007 Expression expression= exprStatement.getExpression();
1008 fSelectedExpression= (IExpressionFragment) ASTFragmentFactory.createFragmentForFullSubtree(expression);
1009 } else if (selectedFragment.getAssociatedNode() instanceof Assignment) {
1010 Assignment assignment= (Assignment) selectedFragment.getAssociatedNode();
1011 fSelectedExpression= (IExpressionFragment) ASTFragmentFactory.createFragmentForFullSubtree(assignment);
1015 if (fSelectedExpression != null && Checks.isEnumCase(fSelectedExpression.getAssociatedExpression().getParent())) {
1016 fSelectedExpression= null;
1019 return fSelectedExpression;
1022 private Type createTempType() throws CoreException {
1023 Expression expression= getSelectedExpression().getAssociatedExpression();
1025 Type resultingType= null;
1026 ITypeBinding typeBinding= expression.resolveTypeBinding();
1028 ASTRewrite rewrite= fCURewrite.getASTRewrite();
1029 AST ast= rewrite.getAST();
1031 if (expression instanceof ClassInstanceCreation && (typeBinding == null || typeBinding.getTypeArguments().length == 0)) {
1032 resultingType= (Type) rewrite.createCopyTarget(((ClassInstanceCreation) expression).getType());
1033 } else if (expression instanceof CastExpression) {
1034 resultingType= (Type) rewrite.createCopyTarget(((CastExpression) expression).getType());
1036 if (typeBinding == null) {
1037 typeBinding= ASTResolving.guessBindingForReference(expression);
1039 if (typeBinding != null) {
1040 typeBinding= Bindings.normalizeForDeclarationUse(typeBinding, ast);
1041 ImportRewrite importRewrite= fCURewrite.getImportRewrite();
1042 ImportRewriteContext context= new ContextSensitiveImportRewriteContext(expression, importRewrite);
1043 resultingType= importRewrite.addImport(typeBinding, ast, context);
1045 resultingType= ast.newSimpleType(ast.newSimpleName("Object")); //$NON-NLS-1$
1048 if (fLinkedProposalModel != null) {
1049 LinkedProposalPositionGroup typeGroup= fLinkedProposalModel.getPositionGroup(KEY_TYPE, true);
1050 typeGroup.addPosition(rewrite.track(resultingType), false);
1051 if (typeBinding != null) {
1052 ITypeBinding[] relaxingTypes= ASTResolving.getNarrowingTypes(ast, typeBinding);
1053 for (int i= 0; i < relaxingTypes.length; i++) {
1054 typeGroup.addProposal(relaxingTypes[i], fCURewrite.getCu(), relaxingTypes.length - i);
1058 return resultingType;
1061 public String guessTempName() {
1062 String[] proposals= guessTempNames();
1063 if (proposals.length == 0)
1066 return proposals[0];
1070 * @return proposed variable names (may be empty, but not null). The first proposal should be used as "best guess" (if it exists).
1072 public String[] guessTempNames() {
1073 if (fGuessedTempNames == null) {
1075 Expression expression= getSelectedExpression().getAssociatedExpression();
1076 if (expression != null) {
1077 ITypeBinding binding= guessBindingForReference(expression);
1078 fGuessedTempNames= StubUtility.getVariableNameSuggestions(NamingConventions.VK_LOCAL, fCu.getJavaProject(), binding, expression, Arrays.asList(getExcludedVariableNames()));
1080 } catch (JavaModelException e) {
1082 if (fGuessedTempNames == null)
1083 fGuessedTempNames= new String[0];
1085 return fGuessedTempNames;
1088 private boolean isLiteralNodeSelected() throws JavaModelException {
1089 IExpressionFragment fragment= getSelectedExpression();
1090 if (fragment == null)
1092 Expression expression= fragment.getAssociatedExpression();
1093 if (expression == null)
1095 switch (expression.getNodeType()) {
1096 case ASTNode.BOOLEAN_LITERAL:
1097 case ASTNode.CHARACTER_LITERAL:
1098 case ASTNode.NULL_LITERAL:
1099 case ASTNode.NUMBER_LITERAL:
1107 private boolean isUsedInExplicitConstructorCall() throws JavaModelException {
1108 Expression selectedExpression= getSelectedExpression().getAssociatedExpression();
1109 if (ASTNodes.getParent(selectedExpression, ConstructorInvocation.class) != null)
1111 if (ASTNodes.getParent(selectedExpression, SuperConstructorInvocation.class) != null)
1116 public boolean replaceAllOccurrences() {
1117 return fReplaceAllOccurrences;
1120 private void replaceSelectedExpressionWithTempDeclaration() throws CoreException {
1121 ASTRewrite rewrite= fCURewrite.getASTRewrite();
1122 Expression selectedExpression= getSelectedExpression().getAssociatedExpression(); // whole expression selected
1124 Expression initializer= (Expression) rewrite.createMoveTarget(selectedExpression);
1125 VariableDeclarationStatement tempDeclaration= createTempDeclaration(initializer);
1126 ASTNode replacement;
1128 ASTNode parent= selectedExpression.getParent();
1129 boolean isParentLambda= parent instanceof LambdaExpression;
1130 AST ast= rewrite.getAST();
1131 if (isParentLambda) {
1132 Block blockBody= ast.newBlock();
1133 blockBody.statements().add(tempDeclaration);
1134 if (!Bindings.isVoidType(((LambdaExpression) parent).resolveMethodBinding().getReturnType())) {
1135 List<VariableDeclarationFragment> fragments= tempDeclaration.fragments();
1136 SimpleName varName= fragments.get(0).getName();
1137 ReturnStatement returnStatement= ast.newReturnStatement();
1138 returnStatement.setExpression(ast.newSimpleName(varName.getIdentifier()));
1139 blockBody.statements().add(returnStatement);
1141 replacement= blockBody;
1142 } else if (ASTNodes.isControlStatementBody(parent.getLocationInParent())) {
1143 Block block= ast.newBlock();
1144 block.statements().add(tempDeclaration);
1147 replacement= tempDeclaration;
1149 ASTNode replacee= isParentLambda || !ASTNodes.hasSemicolon((ExpressionStatement) parent, fCu) ? selectedExpression : parent;
1150 rewrite.replace(replacee, replacement, fCURewrite.createGroupDescription(RefactoringCoreMessages.ExtractTempRefactoring_declare_local_variable));
1153 public void setDeclareFinal(boolean declareFinal) {
1154 fDeclareFinal= declareFinal;
1157 public void setReplaceAllOccurrences(boolean replaceAllOccurrences) {
1158 fReplaceAllOccurrences= replaceAllOccurrences;
1161 public void setTempName(String newName) {
1165 private boolean shouldReplaceSelectedExpressionWithTempDeclaration() throws JavaModelException {
1166 IExpressionFragment selectedFragment= getSelectedExpression();
1167 IExpressionFragment firstExpression= getFirstReplacedExpression();
1168 if (firstExpression.getStartPosition() < selectedFragment.getStartPosition())
1170 ASTNode associatedNode= selectedFragment.getAssociatedNode();
1171 return (associatedNode.getParent() instanceof ExpressionStatement || associatedNode.getParent() instanceof LambdaExpression)
1172 && selectedFragment.matches(ASTFragmentFactory.createFragmentForFullSubtree(associatedNode));
1175 private RefactoringStatus initialize(JavaRefactoringArguments arguments) {
1176 final String selection= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION);
1177 if (selection != null) {
1180 final StringTokenizer tokenizer= new StringTokenizer(selection);
1181 if (tokenizer.hasMoreTokens())
1182 offset= Integer.valueOf(tokenizer.nextToken()).intValue();
1183 if (tokenizer.hasMoreTokens())
1184 length= Integer.valueOf(tokenizer.nextToken()).intValue();
1185 if (offset >= 0 && length >= 0) {
1186 fSelectionStart= offset;
1187 fSelectionLength= length;
1189 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { selection, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION}));
1191 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION));
1192 final String handle= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
1193 if (handle != null) {
1194 final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), handle, false);
1195 if (element == null || !element.exists() || element.getElementType() != IJavaElement.COMPILATION_UNIT)
1196 return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.EXTRACT_LOCAL_VARIABLE);
1198 fCu= (ICompilationUnit) element;
1200 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
1201 final String name= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
1202 if (name != null && !"".equals(name)) //$NON-NLS-1$
1205 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
1206 final String replace= arguments.getAttribute(ATTRIBUTE_REPLACE);
1207 if (replace != null) {
1208 fReplaceAllOccurrences= Boolean.valueOf(replace).booleanValue();
1210 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REPLACE));
1211 final String declareFinal= arguments.getAttribute(ATTRIBUTE_FINAL);
1212 if (declareFinal != null) {
1213 fDeclareFinal= Boolean.valueOf(declareFinal).booleanValue();
1215 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FINAL));
1216 return new RefactoringStatus();
1219 public MethodDeclaration getMethodDeclaration(){
1220 return methodDeclaration;