]> git.uio.no Git - ifi-stolz-refaktor.git/blame - software/no.uio.ifi.refaktor/src/no/uio/ifi/refaktor/refactorings/ExtractTempWithAssertsRefactoring.java
copy-pasted extractTempWithAsserts class from original
[ifi-stolz-refaktor.git] / software / no.uio.ifi.refaktor / src / no / uio / ifi / refaktor / refactorings / ExtractTempWithAssertsRefactoring.java
CommitLineData
f9bf275d
AE
1package no.uio.ifi.refaktor.refactorings;
2
3import java.util.ArrayList;
4import java.util.Arrays;
5import java.util.Collection;
6import java.util.Collections;
7import java.util.Comparator;
8import java.util.HashMap;
9import java.util.HashSet;
10import java.util.Iterator;
11import java.util.List;
12import java.util.Map;
13import java.util.StringTokenizer;
14
15import org.eclipse.core.runtime.Assert;
16import org.eclipse.core.runtime.CoreException;
17import org.eclipse.core.runtime.IProgressMonitor;
18import org.eclipse.core.runtime.NullProgressMonitor;
19import org.eclipse.core.runtime.SubProgressMonitor;
20
21import org.eclipse.text.edits.TextEditGroup;
22
23import org.eclipse.ltk.core.refactoring.Change;
24import org.eclipse.ltk.core.refactoring.Refactoring;
25import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
26import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
27import org.eclipse.ltk.core.refactoring.RefactoringStatus;
28import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
29
30import org.eclipse.jdt.core.ICompilationUnit;
31import org.eclipse.jdt.core.IJavaElement;
32import org.eclipse.jdt.core.IJavaProject;
33import org.eclipse.jdt.core.JavaModelException;
34import org.eclipse.jdt.core.NamingConventions;
35import org.eclipse.jdt.core.SourceRange;
36import org.eclipse.jdt.core.compiler.IProblem;
37import org.eclipse.jdt.core.dom.AST;
38import org.eclipse.jdt.core.dom.ASTNode;
39import org.eclipse.jdt.core.dom.ASTVisitor;
40import org.eclipse.jdt.core.dom.Annotation;
41import org.eclipse.jdt.core.dom.ArrayInitializer;
42import org.eclipse.jdt.core.dom.AssertStatement;
43import org.eclipse.jdt.core.dom.Assignment;
44import org.eclipse.jdt.core.dom.Block;
45import org.eclipse.jdt.core.dom.BodyDeclaration;
46import org.eclipse.jdt.core.dom.CastExpression;
47import org.eclipse.jdt.core.dom.CatchClause;
48import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
49import org.eclipse.jdt.core.dom.ClassInstanceCreation;
50import org.eclipse.jdt.core.dom.CompilationUnit;
51import org.eclipse.jdt.core.dom.ConstructorInvocation;
52import org.eclipse.jdt.core.dom.DoStatement;
53import org.eclipse.jdt.core.dom.EnhancedForStatement;
54import org.eclipse.jdt.core.dom.Expression;
55import org.eclipse.jdt.core.dom.ExpressionStatement;
56import org.eclipse.jdt.core.dom.FieldAccess;
57import org.eclipse.jdt.core.dom.ForStatement;
58import org.eclipse.jdt.core.dom.IBinding;
59import org.eclipse.jdt.core.dom.IMethodBinding;
60import org.eclipse.jdt.core.dom.ITypeBinding;
61import org.eclipse.jdt.core.dom.IVariableBinding;
62import org.eclipse.jdt.core.dom.IfStatement;
63import org.eclipse.jdt.core.dom.InfixExpression;
64import org.eclipse.jdt.core.dom.Initializer;
65import org.eclipse.jdt.core.dom.LambdaExpression;
66import org.eclipse.jdt.core.dom.MethodDeclaration;
67import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
68import org.eclipse.jdt.core.dom.Name;
69import org.eclipse.jdt.core.dom.NullLiteral;
70import org.eclipse.jdt.core.dom.ParenthesizedExpression;
71import org.eclipse.jdt.core.dom.PostfixExpression;
72import org.eclipse.jdt.core.dom.PrefixExpression;
73import org.eclipse.jdt.core.dom.QualifiedName;
74import org.eclipse.jdt.core.dom.ReturnStatement;
75import org.eclipse.jdt.core.dom.SimpleName;
76import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
77import org.eclipse.jdt.core.dom.Statement;
78import org.eclipse.jdt.core.dom.StringLiteral;
79import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
80import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
81import org.eclipse.jdt.core.dom.SwitchCase;
82import org.eclipse.jdt.core.dom.SwitchStatement;
83import org.eclipse.jdt.core.dom.TryStatement;
84import org.eclipse.jdt.core.dom.Type;
85import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
86import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
87import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
88import org.eclipse.jdt.core.dom.WhileStatement;
89import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
90import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
91import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
92import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
93import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
94import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
95import org.eclipse.jdt.core.refactoring.descriptors.ExtractLocalDescriptor;
96
97import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
98import org.eclipse.jdt.internal.corext.Corext;
99import org.eclipse.jdt.internal.corext.SourceRangeFactory;
100import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
101import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
102import org.eclipse.jdt.internal.corext.dom.ASTNodes;
103import org.eclipse.jdt.internal.corext.dom.Bindings;
104import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
105import org.eclipse.jdt.internal.corext.dom.fragments.ASTFragmentFactory;
106import org.eclipse.jdt.internal.corext.dom.fragments.IASTFragment;
107import org.eclipse.jdt.internal.corext.dom.fragments.IExpressionFragment;
108import org.eclipse.jdt.internal.corext.fix.LinkedProposalModel;
109import org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroup;
110import org.eclipse.jdt.internal.corext.refactoring.Checks;
111import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
112import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
113import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
114import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
115import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
116import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext;
117import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes;
118import org.eclipse.jdt.internal.corext.refactoring.code.CodeRefactoringUtil;
119import org.eclipse.jdt.internal.corext.refactoring.code.ExtractTempRefactoring;
120import org.eclipse.jdt.internal.corext.refactoring.rename.RefactoringAnalyzeUtil;
121import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
122import org.eclipse.jdt.internal.corext.refactoring.util.NoCommentSourceRangeComputer;
123import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
124import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
125import org.eclipse.jdt.internal.corext.util.Messages;
126
127import org.eclipse.jdt.ui.JavaElementLabels;
128
129import org.eclipse.jdt.internal.ui.JavaPlugin;
130import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
131import org.eclipse.jdt.internal.ui.text.correction.ASTResolving;
132import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
133import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
134
135/**
136 * Extract Local Variable (from selected expression inside method or initializer).
137 *
138 * @author Anna Eilertsen
139 *
140 * TODO: Copied from ExtractTemp, will replace unused code with super-calls
141 */
142public class ExtractTempWithAssertsRefactoring extends ExtractTempRefactoring {
143
144 private static final String ATTRIBUTE_REPLACE= "replace"; //$NON-NLS-1$
145 private static final String ATTRIBUTE_FINAL= "final"; //$NON-NLS-1$
146
147 private static final class ForStatementChecker extends ASTVisitor {
148
149 private final Collection<IVariableBinding> fForInitializerVariables;
150
151 private boolean fReferringToForVariable= false;
152
153 public ForStatementChecker(Collection<IVariableBinding> forInitializerVariables) {
154 Assert.isNotNull(forInitializerVariables);
155 fForInitializerVariables= forInitializerVariables;
156 }
157
158 public boolean isReferringToForVariable() {
159 return fReferringToForVariable;
160 }
161
162 @Override
163 public boolean visit(SimpleName node) {
164 IBinding binding= node.resolveBinding();
165 if (binding != null && fForInitializerVariables.contains(binding)) {
166 fReferringToForVariable= true;
167 }
168 return false;
169 }
170 }
171
172
173
174 private static boolean allArraysEqual(Object[][] arrays, int position) {
175 Object element= arrays[0][position];
176 for (int i= 0; i < arrays.length; i++) {
177 Object[] array= arrays[i];
178 if (!element.equals(array[position]))
179 return false;
180 }
181 return true;
182 }
183
184 private static boolean canReplace(IASTFragment fragment) {
185 ASTNode node= fragment.getAssociatedNode();
186 ASTNode parent= node.getParent();
187 if (parent instanceof VariableDeclarationFragment) {
188 VariableDeclarationFragment vdf= (VariableDeclarationFragment) parent;
189 if (node.equals(vdf.getName()))
190 return false;
191 }
192 if (isMethodParameter(node))
193 return false;
194 if (isThrowableInCatchBlock(node))
195 return false;
196 if (parent instanceof ExpressionStatement)
197 return false;
198 if (parent instanceof LambdaExpression)
199 return false;
200 if (isLeftValue(node))
201 return false;
202 if (isReferringToLocalVariableFromFor((Expression) node))
203 return false;
204 if (isUsedInForInitializerOrUpdater((Expression) node))
205 return false;
206 if (parent instanceof SwitchCase)
207 return false;
208 return true;
209 }
210
211 private static Object[] getArrayPrefix(Object[] array, int prefixLength) {
212 Assert.isTrue(prefixLength <= array.length);
213 Assert.isTrue(prefixLength >= 0);
214 Object[] prefix= new Object[prefixLength];
215 for (int i= 0; i < prefix.length; i++) {
216 prefix[i]= array[i];
217 }
218 return prefix;
219 }
220
221 // return List<IVariableBinding>
222 private static List<IVariableBinding> getForInitializedVariables(VariableDeclarationExpression variableDeclarations) {
223 List<IVariableBinding> forInitializerVariables= new ArrayList<IVariableBinding>(1);
224 for (Iterator<VariableDeclarationFragment> iter= variableDeclarations.fragments().iterator(); iter.hasNext();) {
225 VariableDeclarationFragment fragment= iter.next();
226 IVariableBinding binding= fragment.resolveBinding();
227 if (binding != null)
228 forInitializerVariables.add(binding);
229 }
230 return forInitializerVariables;
231 }
232
233 private static Object[] getLongestArrayPrefix(Object[][] arrays) {
234 int length= -1;
235 if (arrays.length == 0)
236 return new Object[0];
237 int minArrayLength= arrays[0].length;
238 for (int i= 1; i < arrays.length; i++)
239 minArrayLength= Math.min(minArrayLength, arrays[i].length);
240
241 for (int i= 0; i < minArrayLength; i++) {
242 if (!allArraysEqual(arrays, i))
243 break;
244 length++;
245 }
246 if (length == -1)
247 return new Object[0];
248 return getArrayPrefix(arrays[0], length + 1);
249 }
250
251 private static ASTNode[] getParents(ASTNode node) {
252 ASTNode current= node;
253 List<ASTNode> parents= new ArrayList<ASTNode>();
254 do {
255 parents.add(current.getParent());
256 current= current.getParent();
257 } while (current.getParent() != null);
258 Collections.reverse(parents);
259 return parents.toArray(new ASTNode[parents.size()]);
260 }
261
262 private static boolean isLeftValue(ASTNode node) {
263 ASTNode parent= node.getParent();
264 if (parent instanceof Assignment) {
265 Assignment assignment= (Assignment) parent;
266 if (assignment.getLeftHandSide() == node)
267 return true;
268 }
269 if (parent instanceof PostfixExpression)
270 return true;
271 if (parent instanceof PrefixExpression) {
272 PrefixExpression.Operator op= ((PrefixExpression) parent).getOperator();
273 if (op.equals(PrefixExpression.Operator.DECREMENT))
274 return true;
275 if (op.equals(PrefixExpression.Operator.INCREMENT))
276 return true;
277 return false;
278 }
279 return false;
280 }
281
282 private static boolean isMethodParameter(ASTNode node) {
283 return (node instanceof SimpleName) && (node.getParent() instanceof SingleVariableDeclaration) && (node.getParent().getParent() instanceof MethodDeclaration);
284 }
285
286 private static boolean isReferringToLocalVariableFromFor(Expression expression) {
287 ASTNode current= expression;
288 ASTNode parent= current.getParent();
289 while (parent != null && !(parent instanceof BodyDeclaration)) {
290 if (parent instanceof ForStatement) {
291 ForStatement forStmt= (ForStatement) parent;
292 if (forStmt.initializers().contains(current) || forStmt.updaters().contains(current) || forStmt.getExpression() == current) {
293 List<Expression> initializers= forStmt.initializers();
294 if (initializers.size() == 1 && initializers.get(0) instanceof VariableDeclarationExpression) {
295 List<IVariableBinding> forInitializerVariables= getForInitializedVariables((VariableDeclarationExpression) initializers.get(0));
296 ForStatementChecker checker= new ForStatementChecker(forInitializerVariables);
297 expression.accept(checker);
298 if (checker.isReferringToForVariable())
299 return true;
300 }
301 }
302 }
303 current= parent;
304 parent= current.getParent();
305 }
306 return false;
307 }
308
309 private static boolean isThrowableInCatchBlock(ASTNode node) {
310 return (node instanceof SimpleName) && (node.getParent() instanceof SingleVariableDeclaration) && (node.getParent().getParent() instanceof CatchClause);
311 }
312
313 private static boolean isUsedInForInitializerOrUpdater(Expression expression) {
314 ASTNode parent= expression.getParent();
315 if (parent instanceof ForStatement) {
316 ForStatement forStmt= (ForStatement) parent;
317 return forStmt.initializers().contains(expression) || forStmt.updaters().contains(expression);
318 }
319 return false;
320 }
321
322 private static IASTFragment[] retainOnlyReplacableMatches(IASTFragment[] allMatches) {
323 List<IASTFragment> result= new ArrayList<IASTFragment>(allMatches.length);
324 for (int i= 0; i < allMatches.length; i++) {
325 if (canReplace(allMatches[i]))
326 result.add(allMatches[i]);
327 }
328 return result.toArray(new IASTFragment[result.size()]);
329 }
330
331 private CompilationUnit fCompilationUnitNode;
332
333 private CompilationUnitRewrite fCURewrite;
334
335 private ICompilationUnit fCu;
336
337 private boolean fDeclareFinal;
338
339 private String[] fExcludedVariableNames;
340
341 private boolean fReplaceAllOccurrences;
342
343 // caches:
344 private IExpressionFragment fSelectedExpression;
345
346 private int fSelectionLength;
347
348 private int fSelectionStart;
349
350 private String fTempName;
351 private String[] fGuessedTempNames;
352
353 private boolean fCheckResultForCompileProblems;
354
355 private CompilationUnitChange fChange;
356
357 private LinkedProposalModel fLinkedProposalModel;
358 private MethodDeclaration methodDeclaration;
359
360 private static final String KEY_NAME= "name"; //$NON-NLS-1$
361 private static final String KEY_TYPE= "type"; //$NON-NLS-1$
362
363
364 /**
365 * Creates a new extract temp refactoring
366 * @param unit the compilation unit, or <code>null</code> if invoked by scripting
367 * @param selectionStart start of selection
368 * @param selectionLength length of selection
369 */
370 public ExtractTempWithAssertsRefactoring(ICompilationUnit unit, int selectionStart, int selectionLength) {
371 super(unit, selectionStart, selectionLength);
372 Assert.isTrue(selectionStart >= 0);
373 Assert.isTrue(selectionLength >= 0);
374 fSelectionStart= selectionStart;
375 fSelectionLength= selectionLength;
376 fCu= unit;
377 fCompilationUnitNode= null;
378
379 fReplaceAllOccurrences= true; // default
380 fDeclareFinal= false; // default
381 fTempName= ""; //$NON-NLS-1$
382
383 fLinkedProposalModel= null;
384 fCheckResultForCompileProblems= true;
385 }
386
387 public ExtractTempWithAssertsRefactoring(CompilationUnit astRoot, int selectionStart, int selectionLength) {
388 super(astRoot, selectionStart, selectionLength);
389 Assert.isTrue(selectionStart >= 0);
390 Assert.isTrue(selectionLength >= 0);
391 Assert.isTrue(astRoot.getTypeRoot() instanceof ICompilationUnit);
392
393 fSelectionStart= selectionStart;
394 fSelectionLength= selectionLength;
395 fCu= (ICompilationUnit) astRoot.getTypeRoot();
396 fCompilationUnitNode= astRoot;
397
398 fReplaceAllOccurrences= true; // default
399 fDeclareFinal= false; // default
400 fTempName= ""; //$NON-NLS-1$
401
402 fLinkedProposalModel= null;
403 fCheckResultForCompileProblems= true;
404 }
405
406 public ExtractTempWithAssertsRefactoring(JavaRefactoringArguments arguments, RefactoringStatus status) {
407 this((ICompilationUnit) null, 0, 0);
408 RefactoringStatus initializeStatus= initialize(arguments);
409 status.merge(initializeStatus);
410 }
411
412 public void setCheckResultForCompileProblems(boolean checkResultForCompileProblems) {
413 fCheckResultForCompileProblems= checkResultForCompileProblems;
414 }
415
416
417 public void setLinkedProposalModel(LinkedProposalModel linkedProposalModel) {
418 fLinkedProposalModel= linkedProposalModel;
419 }
420
421 private void addReplaceExpressionWithTemp() throws JavaModelException {
422 IASTFragment[] fragmentsToReplace= retainOnlyReplacableMatches(getMatchingFragments());
423 //TODO: should not have to prune duplicates here...
424 ASTRewrite rewrite= fCURewrite.getASTRewrite();
425 HashSet<IASTFragment> seen= new HashSet<IASTFragment>();
426 for (int i= 0; i < fragmentsToReplace.length; i++) {
427 IASTFragment fragment= fragmentsToReplace[i];
428 if (! seen.add(fragment))
429 continue;
430 SimpleName tempName= fCURewrite.getAST().newSimpleName(fTempName);
431 TextEditGroup description= fCURewrite.createGroupDescription(RefactoringCoreMessages.ExtractTempRefactoring_replace);
432
433 fragment.replace(rewrite, tempName, description);
434 if (fLinkedProposalModel != null)
435 fLinkedProposalModel.getPositionGroup(KEY_NAME, true).addPosition(rewrite.track(tempName), false);
436 }
437 }
438
439 private AssertStatement makeAssertStmt(String temp, String expr){
440 ASTRewrite rewrite= fCURewrite.getASTRewrite();
441 AST ast= rewrite.getAST();
442
443 AssertStatement assertStatement = ast.newAssertStatement();
444 InfixExpression infixExpression = ast.newInfixExpression();
445
446 //TODO: fetch field name
447 infixExpression.setLeftOperand(ast.newQualifiedName(ast.newSimpleName(temp) , ast.newSimpleName(expr)));
448 infixExpression.setOperator(InfixExpression.Operator.EQUALS);
449 infixExpression.setRightOperand(ast.newThisExpression());
450 assertStatement.setExpression(infixExpression);
451 StringLiteral stringLiteral = ast.newStringLiteral();
452 stringLiteral.setLiteralValue("The Move Method refactoring has broken the program due to aliasing issues!");
453 assertStatement.setMessage(stringLiteral);
454 //statementsListRewrite.insertBefore(assertStatement, (Statement) exstmt, null);
455 return assertStatement;
456 }
457
458 private RefactoringStatus checkExpression() throws JavaModelException {
459 Expression selectedExpression= getSelectedExpression().getAssociatedExpression();
460 if (selectedExpression != null) {
461 final ASTNode parent= selectedExpression.getParent();
462 if (selectedExpression instanceof NullLiteral) {
463 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_null_literals);
464 } else if (selectedExpression instanceof ArrayInitializer) {
465 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_array_initializer);
466 } else if (selectedExpression instanceof Assignment) {
467 if (parent instanceof Expression && !(parent instanceof ParenthesizedExpression))
468 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_assignment);
469 else
470 return null;
471 } else if (selectedExpression instanceof SimpleName) {
472 if ((((SimpleName) selectedExpression)).isDeclaration())
473 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_names_in_declarations);
474 if (parent instanceof QualifiedName && selectedExpression.getLocationInParent() == QualifiedName.NAME_PROPERTY || parent instanceof FieldAccess && selectedExpression.getLocationInParent() == FieldAccess.NAME_PROPERTY)
475 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_select_expression);
476 } else if (selectedExpression instanceof VariableDeclarationExpression && parent instanceof TryStatement) {
477 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_resource_in_try_with_resources);
478 }
479 }
480
481 return null;
482 }
483
484 // !! Same as in ExtractConstantRefactoring
485 private RefactoringStatus checkExpressionFragmentIsRValue() throws JavaModelException {
486 switch (Checks.checkExpressionIsRValue(getSelectedExpression().getAssociatedExpression())) {
487 case Checks.NOT_RVALUE_MISC:
488 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.ExtractTempRefactoring_select_expression, null, Corext.getPluginId(), RefactoringStatusCodes.EXPRESSION_NOT_RVALUE, null);
489 case Checks.NOT_RVALUE_VOID:
490 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.ExtractTempRefactoring_no_void, null, Corext.getPluginId(), RefactoringStatusCodes.EXPRESSION_NOT_RVALUE_VOID, null);
491 case Checks.IS_RVALUE_GUESSED:
492 case Checks.IS_RVALUE:
493 return new RefactoringStatus();
494 default:
495 Assert.isTrue(false);
496 return null;
497 }
498 }
499
500 private ITypeBinding guessBindingForReference(Expression expression) {
501 ITypeBinding binding= expression.resolveTypeBinding();
502 if (binding == null) {
503 binding= ASTResolving.guessBindingForReference(expression);
504 }
505 return binding;
506 }
507
508 @Override
509 public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
510 try {
511 pm.beginTask(RefactoringCoreMessages.ExtractTempRefactoring_checking_preconditions, 4);
512
513 fCURewrite= new CompilationUnitRewrite(fCu, fCompilationUnitNode);
514 fCURewrite.getASTRewrite().setTargetSourceRangeComputer(new NoCommentSourceRangeComputer());
515
516 doCreateChange(new SubProgressMonitor(pm, 2));
517
518 fChange= fCURewrite.createChange(RefactoringCoreMessages.ExtractTempRefactoring_change_name, true, new SubProgressMonitor(pm, 1));
519
520 RefactoringStatus result= new RefactoringStatus();
521 if (Arrays.asList(getExcludedVariableNames()).contains(fTempName))
522 result.addWarning(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_another_variable, BasicElementLabels.getJavaElementName(fTempName)));
523
524 result.merge(checkMatchingFragments());
525
526 fChange.setKeepPreviewEdits(true);
527
528 if (fCheckResultForCompileProblems) {
529 checkNewSource(new SubProgressMonitor(pm, 1), result);
530 }
531
532 return result;
533 } finally {
534 pm.done();
535 }
536 }
537
538 private final ExtractLocalDescriptor createRefactoringDescriptor() {
539 final Map<String, String> arguments= new HashMap<String, String>();
540 String project= null;
541 IJavaProject javaProject= fCu.getJavaProject();
542 if (javaProject != null)
543 project= javaProject.getElementName();
544 final String description= Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_descriptor_description_short, BasicElementLabels.getJavaElementName(fTempName));
545 final String expression= ASTNodes.asString(fSelectedExpression.getAssociatedExpression());
546 final String header= Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_descriptor_description, new String[] { BasicElementLabels.getJavaElementName(fTempName), BasicElementLabels.getJavaCodeString(expression)});
547 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
548 comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_name_pattern, BasicElementLabels.getJavaElementName(fTempName)));
549 final BodyDeclaration decl= (BodyDeclaration) ASTNodes.getParent(fSelectedExpression.getAssociatedExpression(), BodyDeclaration.class);
550 if (decl instanceof MethodDeclaration) {
551 methodDeclaration = (MethodDeclaration) decl; //TODO changed, store for later
552 final IMethodBinding method= ((MethodDeclaration) decl).resolveBinding();
553 final String label= method != null ? BindingLabelProvider.getBindingLabel(method, JavaElementLabels.ALL_FULLY_QUALIFIED) : BasicElementLabels.getJavaElementName('{' + JavaElementLabels.ELLIPSIS_STRING + '}');
554 comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_destination_pattern, label));
555 }
556 comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_expression_pattern, BasicElementLabels.getJavaCodeString(expression)));
557 if (fReplaceAllOccurrences)
558 comment.addSetting(RefactoringCoreMessages.ExtractTempRefactoring_replace_occurrences);
559 if (fDeclareFinal)
560 comment.addSetting(RefactoringCoreMessages.ExtractTempRefactoring_declare_final);
561 final ExtractLocalDescriptor descriptor= RefactoringSignatureDescriptorFactory.createExtractLocalDescriptor(project, description, comment.asString(), arguments, RefactoringDescriptor.NONE);
562 arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(project, fCu));
563 arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME, fTempName);
564 arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION, new Integer(fSelectionStart).toString() + " " + new Integer(fSelectionLength).toString()); //$NON-NLS-1$
565 arguments.put(ATTRIBUTE_REPLACE, Boolean.valueOf(fReplaceAllOccurrences).toString());
566 arguments.put(ATTRIBUTE_FINAL, Boolean.valueOf(fDeclareFinal).toString());
567 return descriptor;
568 }
569
570 private void doCreateChange(IProgressMonitor pm) throws CoreException {
571 try {
572 pm.beginTask(RefactoringCoreMessages.ExtractTempRefactoring_checking_preconditions, 1);
573 try {
574 createTempDeclaration();
575 } catch (CoreException exception) {
576 JavaPlugin.log(exception);
577 }
578 addReplaceExpressionWithTemp();
579 } finally {
580 pm.done();
581 }
582 }
583
584 private void checkNewSource(SubProgressMonitor monitor, RefactoringStatus result) throws CoreException {
585 String newCuSource= fChange.getPreviewContent(new NullProgressMonitor());
586 CompilationUnit newCUNode= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL).parse(newCuSource, fCu, true, true, monitor);
587 IProblem[] newProblems= RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, fCompilationUnitNode);
588 for (int i= 0; i < newProblems.length; i++) {
589 IProblem problem= newProblems[i];
590 if (problem.isError())
591 result.addEntry(new RefactoringStatusEntry((problem.isError() ? RefactoringStatus.ERROR : RefactoringStatus.WARNING), problem.getMessage(), new JavaStringStatusContext(newCuSource, SourceRangeFactory.create(problem))));
592 }
593 }
594
595 @Override
596 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
597 try {
598 pm.beginTask("", 6); //$NON-NLS-1$
599
600 RefactoringStatus result= Checks.validateModifiesFiles(ResourceUtil.getFiles(new ICompilationUnit[] { fCu}), getValidationContext());
601 if (result.hasFatalError())
602 return result;
603
604 if (fCompilationUnitNode == null) {
605 fCompilationUnitNode= RefactoringASTParser.parseWithASTProvider(fCu, true, new SubProgressMonitor(pm, 3));
606 } else {
607 pm.worked(3);
608 }
609
610 result.merge(checkSelection(new SubProgressMonitor(pm, 3)));
611 if (!result.hasFatalError() && isLiteralNodeSelected())
612 fReplaceAllOccurrences= false;
613 return result;
614
615 } finally {
616 pm.done();
617 }
618 }
619
620 private RefactoringStatus checkMatchingFragments() throws JavaModelException {
621 RefactoringStatus result= new RefactoringStatus();
622 IASTFragment[] matchingFragments= getMatchingFragments();
623 for (int i= 0; i < matchingFragments.length; i++) {
624 ASTNode node= matchingFragments[i].getAssociatedNode();
625 if (isLeftValue(node) && !isReferringToLocalVariableFromFor((Expression) node)) {
626 String msg= RefactoringCoreMessages.ExtractTempRefactoring_assigned_to;
627 result.addWarning(msg, JavaStatusContext.create(fCu, node));
628 }
629 }
630 return result;
631 }
632
633 private RefactoringStatus checkSelection(IProgressMonitor pm) throws JavaModelException {
634 try {
635 pm.beginTask("", 8); //$NON-NLS-1$
636
637 IExpressionFragment selectedExpression= getSelectedExpression();
638
639 if (selectedExpression == null) {
640 String message= RefactoringCoreMessages.ExtractTempRefactoring_select_expression;
641 return CodeRefactoringUtil.checkMethodSyntaxErrors(fSelectionStart, fSelectionLength, fCompilationUnitNode, message);
642 }
643 pm.worked(1);
644
645 if (isUsedInExplicitConstructorCall())
646 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_explicit_constructor);
647 pm.worked(1);
648
649 ASTNode associatedNode= selectedExpression.getAssociatedNode();
650 if (getEnclosingBodyNode() == null || ASTNodes.getParent(associatedNode, Annotation.class) != null)
651 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_expr_in_method_or_initializer);
652 pm.worked(1);
653
654 if (associatedNode instanceof Name && associatedNode.getParent() instanceof ClassInstanceCreation && associatedNode.getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY)
655 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_name_in_new);
656 pm.worked(1);
657
658 RefactoringStatus result= new RefactoringStatus();
659 result.merge(checkExpression());
660 if (result.hasFatalError())
661 return result;
662 pm.worked(1);
663
664 result.merge(checkExpressionFragmentIsRValue());
665 if (result.hasFatalError())
666 return result;
667 pm.worked(1);
668
669 if (isUsedInForInitializerOrUpdater(getSelectedExpression().getAssociatedExpression()))
670 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_for_initializer_updater);
671 pm.worked(1);
672
673 if (isReferringToLocalVariableFromFor(getSelectedExpression().getAssociatedExpression()))
674 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_refers_to_for_variable);
675 pm.worked(1);
676
677 return result;
678 } finally {
679 pm.done();
680 }
681 }
682
683 public RefactoringStatus checkTempName(String newName) {
684 RefactoringStatus status= Checks.checkTempName(newName, fCu);
685 if (Arrays.asList(getExcludedVariableNames()).contains(newName))
686 status.addWarning(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_another_variable, BasicElementLabels.getJavaElementName(newName)));
687 return status;
688 }
689
690 private void createAndInsertTempDeclaration() throws CoreException {
691 Expression initializer= getSelectedExpression().createCopyTarget(fCURewrite.getASTRewrite(), true);
692 VariableDeclarationStatement vds= createTempDeclaration(initializer);
693
694 IASTFragment[] replacableMatches= retainOnlyReplacableMatches(getMatchingFragments());
695 if (!fReplaceAllOccurrences
696 || replacableMatches.length == 0
697 || replacableMatches.length == 1 && replacableMatches[0].equals(getSelectedExpression().getAssociatedExpression())) {
698 insertAt(getSelectedExpression().getAssociatedNode(), vds);
699 return;
700 }
701
702 ASTNode[] firstReplaceNodeParents= getParents(getFirstReplacedExpression().getAssociatedNode());
703 ASTNode[] commonPath= findDeepestCommonSuperNodePathForReplacedNodes();
704 Assert.isTrue(commonPath.length <= firstReplaceNodeParents.length);
705
706 ASTNode deepestCommonParent= firstReplaceNodeParents[commonPath.length - 1];
707 if (deepestCommonParent instanceof Block)
708 insertAt(firstReplaceNodeParents[commonPath.length], vds);
709 else
710 insertAt(deepestCommonParent, vds);
711 }
712
713 private VariableDeclarationStatement createTempDeclaration(Expression initializer) throws CoreException {
714 AST ast= fCURewrite.getAST();
715
716 VariableDeclarationFragment vdf= ast.newVariableDeclarationFragment();
717 vdf.setName(ast.newSimpleName(fTempName));
718 vdf.setInitializer(initializer);
719
720 VariableDeclarationStatement vds= ast.newVariableDeclarationStatement(vdf);
721 if (fDeclareFinal) {
722 vds.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD));
723 }
724 vds.setType(createTempType());
725
726 if (fLinkedProposalModel != null) {
727 ASTRewrite rewrite= fCURewrite.getASTRewrite();
728 LinkedProposalPositionGroup nameGroup= fLinkedProposalModel.getPositionGroup(KEY_NAME, true);
729 nameGroup.addPosition(rewrite.track(vdf.getName()), true);
730
731 String[] nameSuggestions= guessTempNames();
732 if (nameSuggestions.length > 0 && !nameSuggestions[0].equals(fTempName)) {
733 nameGroup.addProposal(fTempName, null, nameSuggestions.length + 1);
734 }
735 for (int i= 0; i < nameSuggestions.length; i++) {
736 nameGroup.addProposal(nameSuggestions[i], null, nameSuggestions.length - i);
737 }
738 }
739 return vds;
740 }
741
742 private void insertAt(ASTNode target, Statement declaration) {
743 ASTRewrite rewrite= fCURewrite.getASTRewrite();
744 TextEditGroup groupDescription= fCURewrite.createGroupDescription(RefactoringCoreMessages.ExtractTempRefactoring_declare_local_variable);
745
746 ASTNode parent= target.getParent();
747 StructuralPropertyDescriptor locationInParent= target.getLocationInParent();
748 while (locationInParent != Block.STATEMENTS_PROPERTY && locationInParent != SwitchStatement.STATEMENTS_PROPERTY) {
749 if (locationInParent == IfStatement.THEN_STATEMENT_PROPERTY
750 || locationInParent == IfStatement.ELSE_STATEMENT_PROPERTY
751 || locationInParent == ForStatement.BODY_PROPERTY
752 || locationInParent == EnhancedForStatement.BODY_PROPERTY
753 || locationInParent == DoStatement.BODY_PROPERTY
754 || locationInParent == WhileStatement.BODY_PROPERTY) {
755 // create intermediate block if target was the body property of a control statement:
756 Block replacement= rewrite.getAST().newBlock();
757 ListRewrite replacementRewrite= rewrite.getListRewrite(replacement, Block.STATEMENTS_PROPERTY);
758 replacementRewrite.insertFirst(declaration, null);
759 replacementRewrite.insertLast(rewrite.createMoveTarget(target), null);
760 rewrite.replace(target, replacement, groupDescription);
761 return;
762 } else if (locationInParent == LambdaExpression.BODY_PROPERTY && ((LambdaExpression) parent).getBody() instanceof Expression) {
763 Block replacement= rewrite.getAST().newBlock();
764 ListRewrite replacementRewrite= rewrite.getListRewrite(replacement, Block.STATEMENTS_PROPERTY);
765 replacementRewrite.insertFirst(declaration, null);
766 ASTNode moveTarget= rewrite.createMoveTarget(target);
767 AST ast= rewrite.getAST();
768 if (Bindings.isVoidType(((LambdaExpression) parent).resolveMethodBinding().getReturnType())) {
769 ExpressionStatement expressionStatement= ast.newExpressionStatement((Expression) moveTarget);
770 moveTarget= expressionStatement;
771 } else {
772 ReturnStatement returnStatement= ast.newReturnStatement();
773 returnStatement.setExpression((Expression) moveTarget);
774 moveTarget= returnStatement;
775 }
776 replacementRewrite.insertLast(moveTarget, null);
777 rewrite.replace(target, replacement, groupDescription);
778 return;
779 }
780 target= parent;
781 parent= parent.getParent();
782 locationInParent= target.getLocationInParent();
783 }
784 ListRewrite listRewrite= rewrite.getListRewrite(parent, (ChildListPropertyDescriptor)locationInParent);
785 listRewrite.insertBefore(declaration, target, groupDescription);
786 }
787
788 @Override
789 public Change createChange(IProgressMonitor pm) throws CoreException {
790 try {
791 pm.beginTask(RefactoringCoreMessages.ExtractTempRefactoring_checking_preconditions, 1);
792
793 ExtractLocalDescriptor descriptor= createRefactoringDescriptor();
794 fChange.setDescriptor(new RefactoringChangeDescriptor(descriptor));
795 return fChange;
796 } finally {
797 pm.done();
798 }
799 }
800
801 private void createTempDeclaration() throws CoreException {
802 if (shouldReplaceSelectedExpressionWithTempDeclaration())
803 replaceSelectedExpressionWithTempDeclaration();
804 else
805 createAndInsertTempDeclaration();
806 }
807
808 public boolean declareFinal() {
809 return fDeclareFinal;
810 }
811
812 private ASTNode[] findDeepestCommonSuperNodePathForReplacedNodes() throws JavaModelException {
813 ASTNode[] matchNodes= getMatchNodes();
814
815 ASTNode[][] matchingNodesParents= new ASTNode[matchNodes.length][];
816 for (int i= 0; i < matchNodes.length; i++) {
817 matchingNodesParents[i]= getParents(matchNodes[i]);
818 }
819 List<Object> l= Arrays.asList(getLongestArrayPrefix(matchingNodesParents));
820 return l.toArray(new ASTNode[l.size()]);
821 }
822
823 private ASTNode getEnclosingBodyNode() throws JavaModelException {
824 ASTNode node= getSelectedExpression().getAssociatedNode();
825
826 // expression must be in a method, lambda or initializer body
827 // make sure it is not in method or parameter annotation
828 StructuralPropertyDescriptor location= null;
829 while (node != null && !(node instanceof BodyDeclaration)) {
830 location= node.getLocationInParent();
831 node= node.getParent();
832 if (node instanceof LambdaExpression) {
833 break;
834 }
835 }
836 if (location == MethodDeclaration.BODY_PROPERTY || location == Initializer.BODY_PROPERTY
837 || (location == LambdaExpression.BODY_PROPERTY && ((LambdaExpression) node).resolveMethodBinding() != null)) {
838 return (ASTNode) node.getStructuralProperty(location);
839 }
840 return null;
841 }
842
843 private String[] getExcludedVariableNames() {
844 if (fExcludedVariableNames == null) {
845 try {
846 IBinding[] bindings= new ScopeAnalyzer(fCompilationUnitNode).getDeclarationsInScope(getSelectedExpression().getStartPosition(), ScopeAnalyzer.VARIABLES
847 | ScopeAnalyzer.CHECK_VISIBILITY);
848 fExcludedVariableNames= new String[bindings.length];
849 for (int i= 0; i < bindings.length; i++) {
850 fExcludedVariableNames[i]= bindings[i].getName();
851 }
852 } catch (JavaModelException e) {
853 fExcludedVariableNames= new String[0];
854 }
855 }
856 return fExcludedVariableNames;
857 }
858
859 private IExpressionFragment getFirstReplacedExpression() throws JavaModelException {
860 if (!fReplaceAllOccurrences)
861 return getSelectedExpression();
862 IASTFragment[] nodesToReplace= retainOnlyReplacableMatches(getMatchingFragments());
863 if (nodesToReplace.length == 0)
864 return getSelectedExpression();
865 Comparator<IASTFragment> comparator= new Comparator<IASTFragment>() {
866
867 public int compare(IASTFragment o1, IASTFragment o2) {
868 return o1.getStartPosition() - o2.getStartPosition();
869 }
870 };
871 Arrays.sort(nodesToReplace, comparator);
872 return (IExpressionFragment) nodesToReplace[0];
873 }
874
875 private IASTFragment[] getMatchingFragments() throws JavaModelException {
876 if (fReplaceAllOccurrences) {
877 IASTFragment[] allMatches= ASTFragmentFactory.createFragmentForFullSubtree(getEnclosingBodyNode()).getSubFragmentsMatching(getSelectedExpression());
878 return allMatches;
879 } else
880 return new IASTFragment[] { getSelectedExpression()};
881 }
882
883 private ASTNode[] getMatchNodes() throws JavaModelException {
884 IASTFragment[] matches= retainOnlyReplacableMatches(getMatchingFragments());
885 ASTNode[] result= new ASTNode[matches.length];
886 for (int i= 0; i < matches.length; i++)
887 result[i]= matches[i].getAssociatedNode();
888 return result;
889 }
890
891 @Override
892 public String getName() {
893 return RefactoringCoreMessages.ExtractTempRefactoring_name;
894 }
895
896
897 private IExpressionFragment getSelectedExpression() throws JavaModelException {
898 if (fSelectedExpression != null)
899 return fSelectedExpression;
900 IASTFragment selectedFragment= ASTFragmentFactory.createFragmentForSourceRange(new SourceRange(fSelectionStart, fSelectionLength), fCompilationUnitNode, fCu);
901
902 if (selectedFragment instanceof IExpressionFragment && !Checks.isInsideJavadoc(selectedFragment.getAssociatedNode())) {
903 fSelectedExpression= (IExpressionFragment) selectedFragment;
904 } else if (selectedFragment != null) {
905 if (selectedFragment.getAssociatedNode() instanceof ExpressionStatement) {
906 ExpressionStatement exprStatement= (ExpressionStatement) selectedFragment.getAssociatedNode();
907 Expression expression= exprStatement.getExpression();
908 fSelectedExpression= (IExpressionFragment) ASTFragmentFactory.createFragmentForFullSubtree(expression);
909 } else if (selectedFragment.getAssociatedNode() instanceof Assignment) {
910 Assignment assignment= (Assignment) selectedFragment.getAssociatedNode();
911 fSelectedExpression= (IExpressionFragment) ASTFragmentFactory.createFragmentForFullSubtree(assignment);
912 }
913 }
914
915 if (fSelectedExpression != null && Checks.isEnumCase(fSelectedExpression.getAssociatedExpression().getParent())) {
916 fSelectedExpression= null;
917 }
918
919 return fSelectedExpression;
920 }
921
922 private Type createTempType() throws CoreException {
923 Expression expression= getSelectedExpression().getAssociatedExpression();
924
925 Type resultingType= null;
926 ITypeBinding typeBinding= expression.resolveTypeBinding();
927
928 ASTRewrite rewrite= fCURewrite.getASTRewrite();
929 AST ast= rewrite.getAST();
930
931 if (expression instanceof ClassInstanceCreation && (typeBinding == null || typeBinding.getTypeArguments().length == 0)) {
932 resultingType= (Type) rewrite.createCopyTarget(((ClassInstanceCreation) expression).getType());
933 } else if (expression instanceof CastExpression) {
934 resultingType= (Type) rewrite.createCopyTarget(((CastExpression) expression).getType());
935 } else {
936 if (typeBinding == null) {
937 typeBinding= ASTResolving.guessBindingForReference(expression);
938 }
939 if (typeBinding != null) {
940 typeBinding= Bindings.normalizeForDeclarationUse(typeBinding, ast);
941 ImportRewrite importRewrite= fCURewrite.getImportRewrite();
942 ImportRewriteContext context= new ContextSensitiveImportRewriteContext(expression, importRewrite);
943 resultingType= importRewrite.addImport(typeBinding, ast, context);
944 } else {
945 resultingType= ast.newSimpleType(ast.newSimpleName("Object")); //$NON-NLS-1$
946 }
947 }
948 if (fLinkedProposalModel != null) {
949 LinkedProposalPositionGroup typeGroup= fLinkedProposalModel.getPositionGroup(KEY_TYPE, true);
950 typeGroup.addPosition(rewrite.track(resultingType), false);
951 if (typeBinding != null) {
952 ITypeBinding[] relaxingTypes= ASTResolving.getNarrowingTypes(ast, typeBinding);
953 for (int i= 0; i < relaxingTypes.length; i++) {
954 typeGroup.addProposal(relaxingTypes[i], fCURewrite.getCu(), relaxingTypes.length - i);
955 }
956 }
957 }
958 return resultingType;
959 }
960
961 public String guessTempName() {
962 String[] proposals= guessTempNames();
963 if (proposals.length == 0)
964 return fTempName;
965 else
966 return proposals[0];
967 }
968
969 /**
970 * @return proposed variable names (may be empty, but not null). The first proposal should be used as "best guess" (if it exists).
971 */
972 public String[] guessTempNames() {
973 if (fGuessedTempNames == null) {
974 try {
975 Expression expression= getSelectedExpression().getAssociatedExpression();
976 if (expression != null) {
977 ITypeBinding binding= guessBindingForReference(expression);
978 fGuessedTempNames= StubUtility.getVariableNameSuggestions(NamingConventions.VK_LOCAL, fCu.getJavaProject(), binding, expression, Arrays.asList(getExcludedVariableNames()));
979 }
980 } catch (JavaModelException e) {
981 }
982 if (fGuessedTempNames == null)
983 fGuessedTempNames= new String[0];
984 }
985 return fGuessedTempNames;
986 }
987
988 private boolean isLiteralNodeSelected() throws JavaModelException {
989 IExpressionFragment fragment= getSelectedExpression();
990 if (fragment == null)
991 return false;
992 Expression expression= fragment.getAssociatedExpression();
993 if (expression == null)
994 return false;
995 switch (expression.getNodeType()) {
996 case ASTNode.BOOLEAN_LITERAL:
997 case ASTNode.CHARACTER_LITERAL:
998 case ASTNode.NULL_LITERAL:
999 case ASTNode.NUMBER_LITERAL:
1000 return true;
1001
1002 default:
1003 return false;
1004 }
1005 }
1006
1007 private boolean isUsedInExplicitConstructorCall() throws JavaModelException {
1008 Expression selectedExpression= getSelectedExpression().getAssociatedExpression();
1009 if (ASTNodes.getParent(selectedExpression, ConstructorInvocation.class) != null)
1010 return true;
1011 if (ASTNodes.getParent(selectedExpression, SuperConstructorInvocation.class) != null)
1012 return true;
1013 return false;
1014 }
1015
1016 public boolean replaceAllOccurrences() {
1017 return fReplaceAllOccurrences;
1018 }
1019
1020 private void replaceSelectedExpressionWithTempDeclaration() throws CoreException {
1021 ASTRewrite rewrite= fCURewrite.getASTRewrite();
1022 Expression selectedExpression= getSelectedExpression().getAssociatedExpression(); // whole expression selected
1023
1024 Expression initializer= (Expression) rewrite.createMoveTarget(selectedExpression);
1025 VariableDeclarationStatement tempDeclaration= createTempDeclaration(initializer);
1026 ASTNode replacement;
1027
1028 ASTNode parent= selectedExpression.getParent();
1029 boolean isParentLambda= parent instanceof LambdaExpression;
1030 AST ast= rewrite.getAST();
1031 if (isParentLambda) {
1032 Block blockBody= ast.newBlock();
1033 blockBody.statements().add(tempDeclaration);
1034 if (!Bindings.isVoidType(((LambdaExpression) parent).resolveMethodBinding().getReturnType())) {
1035 List<VariableDeclarationFragment> fragments= tempDeclaration.fragments();
1036 SimpleName varName= fragments.get(0).getName();
1037 ReturnStatement returnStatement= ast.newReturnStatement();
1038 returnStatement.setExpression(ast.newSimpleName(varName.getIdentifier()));
1039 blockBody.statements().add(returnStatement);
1040 }
1041 replacement= blockBody;
1042 } else if (ASTNodes.isControlStatementBody(parent.getLocationInParent())) {
1043 Block block= ast.newBlock();
1044 block.statements().add(tempDeclaration);
1045 replacement= block;
1046 } else {
1047 replacement= tempDeclaration;
1048 }
1049 ASTNode replacee= isParentLambda || !ASTNodes.hasSemicolon((ExpressionStatement) parent, fCu) ? selectedExpression : parent;
1050 rewrite.replace(replacee, replacement, fCURewrite.createGroupDescription(RefactoringCoreMessages.ExtractTempRefactoring_declare_local_variable));
1051 }
1052
1053 public void setDeclareFinal(boolean declareFinal) {
1054 fDeclareFinal= declareFinal;
1055 }
1056
1057 public void setReplaceAllOccurrences(boolean replaceAllOccurrences) {
1058 fReplaceAllOccurrences= replaceAllOccurrences;
1059 }
1060
1061 public void setTempName(String newName) {
1062 fTempName= newName;
1063 }
1064
1065 private boolean shouldReplaceSelectedExpressionWithTempDeclaration() throws JavaModelException {
1066 IExpressionFragment selectedFragment= getSelectedExpression();
1067 IExpressionFragment firstExpression= getFirstReplacedExpression();
1068 if (firstExpression.getStartPosition() < selectedFragment.getStartPosition())
1069 return false;
1070 ASTNode associatedNode= selectedFragment.getAssociatedNode();
1071 return (associatedNode.getParent() instanceof ExpressionStatement || associatedNode.getParent() instanceof LambdaExpression)
1072 && selectedFragment.matches(ASTFragmentFactory.createFragmentForFullSubtree(associatedNode));
1073 }
1074
1075 private RefactoringStatus initialize(JavaRefactoringArguments arguments) {
1076 final String selection= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION);
1077 if (selection != null) {
1078 int offset= -1;
1079 int length= -1;
1080 final StringTokenizer tokenizer= new StringTokenizer(selection);
1081 if (tokenizer.hasMoreTokens())
1082 offset= Integer.valueOf(tokenizer.nextToken()).intValue();
1083 if (tokenizer.hasMoreTokens())
1084 length= Integer.valueOf(tokenizer.nextToken()).intValue();
1085 if (offset >= 0 && length >= 0) {
1086 fSelectionStart= offset;
1087 fSelectionLength= length;
1088 } else
1089 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { selection, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION}));
1090 } else
1091 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION));
1092 final String handle= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
1093 if (handle != null) {
1094 final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), handle, false);
1095 if (element == null || !element.exists() || element.getElementType() != IJavaElement.COMPILATION_UNIT)
1096 return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.EXTRACT_LOCAL_VARIABLE);
1097 else
1098 fCu= (ICompilationUnit) element;
1099 } else
1100 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
1101 final String name= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
1102 if (name != null && !"".equals(name)) //$NON-NLS-1$
1103 fTempName= name;
1104 else
1105 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
1106 final String replace= arguments.getAttribute(ATTRIBUTE_REPLACE);
1107 if (replace != null) {
1108 fReplaceAllOccurrences= Boolean.valueOf(replace).booleanValue();
1109 } else
1110 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REPLACE));
1111 final String declareFinal= arguments.getAttribute(ATTRIBUTE_FINAL);
1112 if (declareFinal != null) {
1113 fDeclareFinal= Boolean.valueOf(declareFinal).booleanValue();
1114 } else
1115 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FINAL));
1116 return new RefactoringStatus();
1117 }
1118
1119 public MethodDeclaration getMethodDeclaration(){
1120 return methodDeclaration;
1121 }
1122}