1 /*******************************************************************************
2 * Copyright (c) 2000, 2012 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 * Felix Pahl (fpahl@web.de) - contributed fix for:
11 * o introduce parameter throws NPE if there are compiler errors
12 * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=48325)
13 *******************************************************************************/
14 package org.eclipse.jdt.internal.corext.refactoring.code;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.LinkedHashSet;
20 import java.util.List;
22 import java.util.StringTokenizer;
24 import org.eclipse.core.runtime.Assert;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IProgressMonitor;
27 import org.eclipse.core.runtime.SubProgressMonitor;
29 import org.eclipse.jface.text.TextSelection;
31 import org.eclipse.ltk.core.refactoring.Change;
32 import org.eclipse.ltk.core.refactoring.Refactoring;
33 import org.eclipse.ltk.core.refactoring.RefactoringContribution;
34 import org.eclipse.ltk.core.refactoring.RefactoringCore;
35 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
36 import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
37 import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring;
39 import org.eclipse.jdt.core.ICompilationUnit;
40 import org.eclipse.jdt.core.IJavaElement;
41 import org.eclipse.jdt.core.IMethod;
42 import org.eclipse.jdt.core.JavaModelException;
43 import org.eclipse.jdt.core.SourceRange;
44 import org.eclipse.jdt.core.dom.AST;
45 import org.eclipse.jdt.core.dom.ASTNode;
46 import org.eclipse.jdt.core.dom.Annotation;
47 import org.eclipse.jdt.core.dom.ArrayInitializer;
48 import org.eclipse.jdt.core.dom.Assignment;
49 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
50 import org.eclipse.jdt.core.dom.Expression;
51 import org.eclipse.jdt.core.dom.FieldAccess;
52 import org.eclipse.jdt.core.dom.IBinding;
53 import org.eclipse.jdt.core.dom.ITypeBinding;
54 import org.eclipse.jdt.core.dom.MethodDeclaration;
55 import org.eclipse.jdt.core.dom.MethodInvocation;
56 import org.eclipse.jdt.core.dom.Name;
57 import org.eclipse.jdt.core.dom.NodeFinder;
58 import org.eclipse.jdt.core.dom.NullLiteral;
59 import org.eclipse.jdt.core.dom.ParameterizedType;
60 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
61 import org.eclipse.jdt.core.dom.QualifiedName;
62 import org.eclipse.jdt.core.dom.SimpleName;
63 import org.eclipse.jdt.core.dom.Type;
64 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
65 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
66 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
67 import org.eclipse.jdt.core.refactoring.descriptors.ChangeMethodSignatureDescriptor;
68 import org.eclipse.jdt.core.refactoring.descriptors.IntroduceParameterDescriptor;
70 import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
71 import org.eclipse.jdt.internal.corext.Corext;
72 import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
73 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
74 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
75 import org.eclipse.jdt.internal.corext.dom.Bindings;
76 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
77 import org.eclipse.jdt.internal.corext.dom.fragments.ASTFragmentFactory;
78 import org.eclipse.jdt.internal.corext.dom.fragments.IASTFragment;
79 import org.eclipse.jdt.internal.corext.dom.fragments.IExpressionFragment;
80 import org.eclipse.jdt.internal.corext.refactoring.Checks;
81 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
82 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
83 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
84 import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
85 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
86 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
87 import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes;
88 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
89 import org.eclipse.jdt.internal.corext.refactoring.structure.BodyUpdater;
90 import org.eclipse.jdt.internal.corext.refactoring.structure.ChangeSignatureProcessor;
91 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
92 import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating;
93 import org.eclipse.jdt.internal.corext.util.Messages;
95 import org.eclipse.jdt.ui.JavaElementLabels;
97 import org.eclipse.jdt.internal.ui.JavaPlugin;
98 import org.eclipse.jdt.internal.ui.actions.SelectionConverter;
99 import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
102 public class IntroduceParameterRefactoring extends Refactoring implements IDelegateUpdating {
104 private static final String ATTRIBUTE_ARGUMENT= "argument"; //$NON-NLS-1$
106 private static final String[] KNOWN_METHOD_NAME_PREFIXES= {"get", "is"}; //$NON-NLS-2$ //$NON-NLS-1$
108 private ICompilationUnit fSourceCU;
109 private int fSelectionStart;
110 private int fSelectionLength;
112 private IMethod fMethod;
113 private Refactoring fChangeSignatureRefactoring;
114 private ChangeSignatureProcessor fChangeSignatureProcessor;
115 private ParameterInfo fParameter;
116 private String fParameterName;
117 private JavaRefactoringArguments fArguments;
119 private Expression fSelectedExpression;
120 private String[] fExcludedParameterNames;
123 * Creates a new introduce parameter refactoring.
124 * @param unit the compilation unit, or <code>null</code> if invoked by scripting
125 * @param selectionStart start
126 * @param selectionLength length
128 public IntroduceParameterRefactoring(ICompilationUnit unit, int selectionStart, int selectionLength) {
129 Assert.isTrue(selectionStart >= 0);
130 Assert.isTrue(selectionLength >= 0);
132 fSelectionStart= selectionStart;
133 fSelectionLength= selectionLength;
136 public IntroduceParameterRefactoring(JavaRefactoringArguments arguments, RefactoringStatus status) {
138 RefactoringStatus initializeStatus= initialize(arguments);
139 status.merge(initializeStatus);
142 // ------------------- IDelegateUpdating ----------------------
144 public boolean canEnableDelegateUpdating() {
148 public boolean getDelegateUpdating() {
149 return (fChangeSignatureProcessor != null) ? fChangeSignatureProcessor.getDelegateUpdating() : false;
152 public void setDelegateUpdating(boolean updating) {
153 if (fChangeSignatureProcessor != null)
154 fChangeSignatureProcessor.setDelegateUpdating(updating);
157 public void setDeprecateDelegates(boolean deprecate) {
158 if (fChangeSignatureProcessor != null)
159 fChangeSignatureProcessor.setDeprecateDelegates(deprecate);
162 public boolean getDeprecateDelegates() {
163 return (fChangeSignatureProcessor != null) ? fChangeSignatureProcessor.getDeprecateDelegates() : false;
166 // ------------------- /IDelegateUpdating ---------------------
169 public String getName() {
170 return RefactoringCoreMessages.IntroduceParameterRefactoring_name;
173 //--- checkActivation
176 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
178 pm.beginTask("", 7); //$NON-NLS-1$
180 if (! fSourceCU.isStructureKnown())
181 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceParameterRefactoring_syntax_error);
183 IJavaElement enclosingElement= SelectionConverter.resolveEnclosingElement(fSourceCU, new TextSelection(fSelectionStart, fSelectionLength));
184 if (! (enclosingElement instanceof IMethod))
185 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceParameterRefactoring_expression_in_method);
187 fMethod= (IMethod) enclosingElement;
190 RefactoringStatus result= new RefactoringStatus();
191 if (fArguments != null) {
193 fChangeSignatureProcessor= new ChangeSignatureProcessor(fArguments, result);
194 if (!result.hasFatalError()) {
195 fChangeSignatureRefactoring= new ProcessorBasedRefactoring(fChangeSignatureProcessor);
196 fChangeSignatureRefactoring.setValidationContext(getValidationContext());
197 result.merge(fChangeSignatureProcessor.checkInitialConditions(new SubProgressMonitor(pm, 2)));
198 if (result.hasFatalError())
206 fChangeSignatureProcessor= RefactoringAvailabilityTester.isChangeSignatureAvailable(fMethod) ? new ChangeSignatureProcessor(fMethod) : null;
207 if (fChangeSignatureProcessor == null)
208 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceParameterRefactoring_expression_in_method);
209 fChangeSignatureRefactoring= new ProcessorBasedRefactoring(fChangeSignatureProcessor);
210 fChangeSignatureRefactoring.setValidationContext(getValidationContext());
211 result.merge(fChangeSignatureProcessor.checkInitialConditions(new SubProgressMonitor(pm, 1)));
212 if (result.hasFatalError()) {
213 RefactoringStatusEntry entry= result.getEntryMatchingSeverity(RefactoringStatus.FATAL);
214 if (entry.getCode() == RefactoringStatusCodes.OVERRIDES_ANOTHER_METHOD || entry.getCode() == RefactoringStatusCodes.METHOD_DECLARED_IN_INTERFACE) {
216 IMethod method= (IMethod) entry.getData();
217 fChangeSignatureProcessor= RefactoringAvailabilityTester.isChangeSignatureAvailable(method) ? new ChangeSignatureProcessor(method) : null;
218 if (fChangeSignatureProcessor == null) {
219 String msg= Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_cannot_introduce, entry.getMessage());
220 return RefactoringStatus.createFatalErrorStatus(msg);
222 fChangeSignatureRefactoring= new ProcessorBasedRefactoring(fChangeSignatureProcessor);
223 fChangeSignatureRefactoring.setValidationContext(getValidationContext());
224 result= fChangeSignatureProcessor.checkInitialConditions(new SubProgressMonitor(pm, 1));
225 if (result.hasFatalError())
235 CompilationUnitRewrite cuRewrite= fChangeSignatureProcessor.getBaseCuRewrite();
236 if (! cuRewrite.getCu().equals(fSourceCU))
237 cuRewrite= new CompilationUnitRewrite(fSourceCU); // TODO: should try to avoid throwing away this AST
239 initializeSelectedExpression(cuRewrite);
242 result.merge(checkSelection(cuRewrite, new SubProgressMonitor(pm, 3)));
243 if (result.hasFatalError())
246 initializeExcludedParameterNames(cuRewrite);
248 addParameterInfo(cuRewrite);
250 fChangeSignatureProcessor.setBodyUpdater(new BodyUpdater() {
252 public void updateBody(MethodDeclaration methodDeclaration, CompilationUnitRewrite rewrite, RefactoringStatus updaterResult) {
253 replaceSelectedExpression(rewrite);
260 if (fChangeSignatureRefactoring != null)
261 fChangeSignatureRefactoring.setValidationContext(null);
265 private void addParameterInfo(CompilationUnitRewrite cuRewrite) throws JavaModelException {
266 ITypeBinding typeBinding= Bindings.normalizeForDeclarationUse(fSelectedExpression.resolveTypeBinding(), fSelectedExpression.getAST());
267 String name= fParameterName != null ? fParameterName : guessedParameterName();
268 Expression expression= fSelectedExpression instanceof ParenthesizedExpression ? ((ParenthesizedExpression)fSelectedExpression).getExpression() : fSelectedExpression;
270 ImportRewrite importRewrite= cuRewrite.getImportRewrite();
271 ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(fSelectedExpression, importRewrite);
272 String typeName= importRewrite.addImport(typeBinding, importRewriteContext);
274 String defaultValue= null;
275 if (expression instanceof ClassInstanceCreation && typeBinding.isParameterizedType()) {
276 ClassInstanceCreation classInstanceCreation= (ClassInstanceCreation) expression;
277 Type cicType= classInstanceCreation.getType();
278 if (cicType instanceof ParameterizedType && ((ParameterizedType) cicType).typeArguments().size() == 0) {
279 // expand the diamond:
280 AST ast= cuRewrite.getAST();
281 Type type= importRewrite.addImport(typeBinding, ast, importRewriteContext);
282 classInstanceCreation.setType(type); // Should not touch the original AST ...
283 defaultValue= ASTNodes.asFormattedString(classInstanceCreation, 0, StubUtility.getLineDelimiterUsed(cuRewrite.getCu()), cuRewrite.getCu().getJavaProject().getOptions(true));
284 classInstanceCreation.setType(cicType); // ... so let's restore it right away.
288 if (defaultValue == null) {
289 defaultValue= fSourceCU.getBuffer().getText(expression.getStartPosition(), expression.getLength());
291 fParameter= ParameterInfo.createInfoForAddedParameter(typeBinding, typeName, name, defaultValue);
292 if (fArguments == null) {
293 List<ParameterInfo> parameterInfos= fChangeSignatureProcessor.getParameterInfos();
294 int parametersCount= parameterInfos.size();
295 if (parametersCount > 0 && parameterInfos.get(parametersCount - 1).isOldVarargs())
296 parameterInfos.add(parametersCount - 1, fParameter);
298 parameterInfos.add(fParameter);
302 private void replaceSelectedExpression(CompilationUnitRewrite cuRewrite) {
303 if (! fSourceCU.equals(cuRewrite.getCu()))
305 // TODO: do for all methodDeclarations and replace matching fragments?
307 // cannot use fSelectedExpression here, since it could be from another AST (if method was replaced by overridden):
308 Expression expression= (Expression) NodeFinder.perform(cuRewrite.getRoot(), fSelectedExpression.getStartPosition(), fSelectedExpression.getLength());
310 ASTNode newExpression= cuRewrite.getRoot().getAST().newSimpleName(fParameter.getNewName());
311 String description= RefactoringCoreMessages.IntroduceParameterRefactoring_replace;
312 cuRewrite.getASTRewrite().replace(expression.getParent() instanceof ParenthesizedExpression
313 ? expression.getParent() : expression, newExpression, cuRewrite.createGroupDescription(description));
316 private void initializeSelectedExpression(CompilationUnitRewrite cuRewrite) throws JavaModelException {
317 IASTFragment fragment= ASTFragmentFactory.createFragmentForSourceRange(
318 new SourceRange(fSelectionStart, fSelectionLength), cuRewrite.getRoot(), cuRewrite.getCu());
320 if (! (fragment instanceof IExpressionFragment))
323 //TODO: doesn't handle selection of partial Expressions
324 Expression expression= ((IExpressionFragment) fragment).getAssociatedExpression();
325 if (fragment.getStartPosition() != expression.getStartPosition()
326 || fragment.getLength() != expression.getLength())
329 if (Checks.isInsideJavadoc(expression))
331 //TODO: exclude invalid selections
332 if (Checks.isEnumCase(expression.getParent()))
335 fSelectedExpression= expression;
338 private RefactoringStatus checkSelection(CompilationUnitRewrite cuRewrite, IProgressMonitor pm) {
340 if (fSelectedExpression == null){
341 String message= RefactoringCoreMessages.IntroduceParameterRefactoring_select;
342 return CodeRefactoringUtil.checkMethodSyntaxErrors(fSelectionStart, fSelectionLength, cuRewrite.getRoot(), message);
345 MethodDeclaration methodDeclaration= (MethodDeclaration) ASTNodes.getParent(fSelectedExpression, MethodDeclaration.class);
346 if (methodDeclaration == null || ASTNodes.getParent(fSelectedExpression, Annotation.class) != null)
347 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceParameterRefactoring_expression_in_method);
348 if (methodDeclaration.resolveBinding() == null)
349 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.IntroduceParameterRefactoring_no_binding);
350 //TODO: check for rippleMethods -> find matching fragments, consider callers of all rippleMethods
352 RefactoringStatus result= new RefactoringStatus();
353 result.merge(checkExpression());
354 if (result.hasFatalError())
357 result.merge(checkExpressionBinding());
358 if (result.hasFatalError())
361 // if (isUsedInForInitializerOrUpdater(getSelectedExpression().getAssociatedExpression()))
362 // return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.getString("ExtractTempRefactoring.for_initializer_updater")); //$NON-NLS-1$
365 // if (isReferringToLocalVariableFromFor(getSelectedExpression().getAssociatedExpression()))
366 // return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.getString("ExtractTempRefactoring.refers_to_for_variable")); //$NON-NLS-1$
376 private RefactoringStatus checkExpression() {
377 //TODO: adjust error messages (or generalize for all refactorings on expression-selections?)
378 Expression selectedExpression= fSelectedExpression;
380 if (selectedExpression instanceof Name && selectedExpression.getParent() instanceof ClassInstanceCreation)
381 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_name_in_new);
382 //TODO: let's just take the CIC automatically (no ambiguity -> no problem -> no dialog ;-)
384 if (selectedExpression instanceof NullLiteral) {
385 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_null_literals);
386 } else if (selectedExpression instanceof ArrayInitializer) {
387 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_array_initializer);
388 } else if (selectedExpression instanceof Assignment) {
389 if (selectedExpression.getParent() instanceof Expression)
390 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_assignment);
394 } else if (selectedExpression instanceof SimpleName){
395 if ((((SimpleName)selectedExpression)).isDeclaration())
396 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_names_in_declarations);
397 if (selectedExpression.getParent() instanceof QualifiedName && selectedExpression.getLocationInParent() == QualifiedName.NAME_PROPERTY
398 || selectedExpression.getParent() instanceof FieldAccess && selectedExpression.getLocationInParent() == FieldAccess.NAME_PROPERTY)
399 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_select_expression);
405 private RefactoringStatus checkExpressionBinding() {
406 return checkExpressionFragmentIsRValue();
409 // !! +/- same as in ExtractConstantRefactoring & ExtractTempRefactoring
410 private RefactoringStatus checkExpressionFragmentIsRValue() {
411 switch(Checks.checkExpressionIsRValue(fSelectedExpression)) {
412 case Checks.IS_RVALUE_GUESSED:
413 case Checks.NOT_RVALUE_MISC:
414 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.IntroduceParameterRefactoring_select, null, Corext.getPluginId(), RefactoringStatusCodes.EXPRESSION_NOT_RVALUE, null);
415 case Checks.NOT_RVALUE_VOID:
416 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.IntroduceParameterRefactoring_no_void, null, Corext.getPluginId(), RefactoringStatusCodes.EXPRESSION_NOT_RVALUE_VOID, null);
417 case Checks.IS_RVALUE:
418 return new RefactoringStatus();
420 Assert.isTrue(false); return null;
424 public List<ParameterInfo> getParameterInfos() {
425 return fChangeSignatureProcessor.getParameterInfos();
428 public ParameterInfo getAddedParameterInfo() {
432 public String getMethodSignaturePreview() throws JavaModelException {
433 return fChangeSignatureProcessor.getNewMethodSignature();
436 //--- Input setting/validation
438 public void setParameterName(String name) {
439 Assert.isNotNull(name);
440 fParameter.setNewName(name);
444 * must only be called <i>after</i> checkActivation()
445 * @return guessed parameter name
447 public String guessedParameterName() {
448 String[] proposals= guessParameterNames();
449 if (proposals.length == 0)
450 return ""; //$NON-NLS-1$
455 // --- TODO: copied from ExtractTempRefactoring - should extract ------------------------------
458 * Must only be called <i>after</i> checkActivation().
459 * The first proposal should be used as "best guess" (if it exists).
460 * @return proposed variable names (may be empty, but not null).
462 public String[] guessParameterNames() {
463 LinkedHashSet<String> proposals= new LinkedHashSet<String>(); //retain ordering, but prevent duplicates
464 if (fSelectedExpression instanceof MethodInvocation){
465 proposals.addAll(guessTempNamesFromMethodInvocation((MethodInvocation) fSelectedExpression, fExcludedParameterNames));
467 proposals.addAll(guessTempNamesFromExpression(fSelectedExpression, fExcludedParameterNames));
468 return proposals.toArray(new String[proposals.size()]);
471 private List<String> guessTempNamesFromMethodInvocation(MethodInvocation selectedMethodInvocation, String[] excludedVariableNames) {
472 String methodName= selectedMethodInvocation.getName().getIdentifier();
473 for (int i= 0; i < KNOWN_METHOD_NAME_PREFIXES.length; i++) {
474 String prefix= KNOWN_METHOD_NAME_PREFIXES[i];
475 if (! methodName.startsWith(prefix))
476 continue; //not this prefix
477 if (methodName.length() == prefix.length())
478 return Collections.emptyList(); // prefix alone -> don't take method name
479 char firstAfterPrefix= methodName.charAt(prefix.length());
480 if (! Character.isUpperCase(firstAfterPrefix))
481 continue; //not uppercase after prefix
482 //found matching prefix
483 String proposal= Character.toLowerCase(firstAfterPrefix) + methodName.substring(prefix.length() + 1);
484 methodName= proposal;
487 String[] proposals= StubUtility.getLocalNameSuggestions(fSourceCU.getJavaProject(), methodName, 0, excludedVariableNames);
488 return Arrays.asList(proposals);
491 private List<String> guessTempNamesFromExpression(Expression selectedExpression, String[] excluded) {
492 ITypeBinding expressionBinding= Bindings.normalizeForDeclarationUse(
493 selectedExpression.resolveTypeBinding(),
494 selectedExpression.getAST());
495 String typeName= getQualifiedName(expressionBinding);
496 if (typeName.length() == 0)
497 typeName= expressionBinding.getName();
498 if (typeName.length() == 0)
499 return Collections.emptyList();
500 int typeParamStart= typeName.indexOf("<"); //$NON-NLS-1$
501 if (typeParamStart != -1)
502 typeName= typeName.substring(0, typeParamStart);
503 String[] proposals= StubUtility.getLocalNameSuggestions(fSourceCU.getJavaProject(), typeName, expressionBinding.getDimensions(), excluded);
504 return Arrays.asList(proposals);
507 // ----------------------------------------------------------------------
509 private static String getQualifiedName(ITypeBinding typeBinding) {
510 if (typeBinding.isAnonymous())
511 return getQualifiedName(typeBinding.getSuperclass());
512 if (! typeBinding.isArray())
513 return typeBinding.getQualifiedName();
515 return typeBinding.getElementType().getQualifiedName();
518 private void initializeExcludedParameterNames(CompilationUnitRewrite cuRewrite) {
519 IBinding[] bindings= new ScopeAnalyzer(cuRewrite.getRoot()).getDeclarationsInScope(
520 fSelectedExpression.getStartPosition(), ScopeAnalyzer.VARIABLES);
521 fExcludedParameterNames= new String[bindings.length];
522 for (int i= 0; i < fExcludedParameterNames.length; i++) {
523 fExcludedParameterNames[i]= bindings[i].getName();
527 public RefactoringStatus validateInput() {
528 return fChangeSignatureProcessor.checkSignature();
534 public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
535 fChangeSignatureRefactoring.setValidationContext(getValidationContext());
537 return fChangeSignatureRefactoring.checkFinalConditions(pm);
539 fChangeSignatureRefactoring.setValidationContext(null);
544 public Change createChange(IProgressMonitor pm) throws CoreException {
545 fChangeSignatureRefactoring.setValidationContext(getValidationContext());
547 Change[] changes= fChangeSignatureProcessor.getAllChanges();
548 return new DynamicValidationRefactoringChange(getRefactoringDescriptor(), RefactoringCoreMessages.IntroduceParameterRefactoring_name, changes);
550 fChangeSignatureRefactoring.setValidationContext(null);
555 private IntroduceParameterDescriptor getRefactoringDescriptor() {
556 ChangeMethodSignatureDescriptor extended= (ChangeMethodSignatureDescriptor) fChangeSignatureProcessor.createDescriptor();
557 RefactoringContribution contribution= RefactoringCore.getRefactoringContribution(IJavaRefactorings.CHANGE_METHOD_SIGNATURE);
559 Map<String, String> argumentsMap= contribution.retrieveArgumentMap(extended);
561 final Map<String, String> arguments= new HashMap<String, String>();
562 arguments.put(ATTRIBUTE_ARGUMENT, fParameter.getNewName());
563 arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION, new Integer(fSelectionStart).toString() + " " + new Integer(fSelectionLength).toString()); //$NON-NLS-1$
564 arguments.putAll(argumentsMap);
565 String signature= fChangeSignatureProcessor.getMethodName();
567 signature= fChangeSignatureProcessor.getOldMethodSignature();
568 } catch (JavaModelException exception) {
569 JavaPlugin.log(exception);
571 final String description= Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_descriptor_description_short, BasicElementLabels.getJavaElementName(fChangeSignatureProcessor.getMethod().getElementName()));
572 final String header= Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_descriptor_description, new String[] { BasicElementLabels.getJavaElementName(fParameter.getNewName()), signature, BasicElementLabels.getJavaCodeString(ASTNodes.asString(fSelectedExpression))});
573 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(extended.getProject(), this, header);
574 comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_original_pattern, JavaElementLabels.getTextLabel(fChangeSignatureProcessor.getMethod(),
575 JavaElementLabels.ALL_FULLY_QUALIFIED)));
576 comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_expression_pattern, BasicElementLabels.getJavaCodeString(ASTNodes.asString(fSelectedExpression))));
577 comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_parameter_pattern, BasicElementLabels.getJavaElementName(getAddedParameterInfo().getNewName())));
578 return RefactoringSignatureDescriptorFactory.createIntroduceParameterDescriptor(extended.getProject(), description, comment.asString(), arguments, extended.getFlags());
581 private RefactoringStatus initialize(JavaRefactoringArguments arguments) {
582 fArguments= arguments;
583 final String selection= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION);
584 if (selection != null) {
587 final StringTokenizer tokenizer= new StringTokenizer(selection);
588 if (tokenizer.hasMoreTokens())
589 offset= Integer.valueOf(tokenizer.nextToken()).intValue();
590 if (tokenizer.hasMoreTokens())
591 length= Integer.valueOf(tokenizer.nextToken()).intValue();
592 if (offset >= 0 && length >= 0) {
593 fSelectionStart= offset;
594 fSelectionLength= length;
596 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { selection, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION}));
598 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION));
599 final String handle= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
600 if (handle != null) {
601 final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), handle, false);
602 if (element == null || !element.exists() || element.getElementType() != IJavaElement.COMPILATION_UNIT)
603 return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.INTRODUCE_PARAMETER);
605 fSourceCU= (ICompilationUnit)element;
607 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
608 final String name= arguments.getAttribute(ATTRIBUTE_ARGUMENT);
609 if (name != null && !"".equals(name)) //$NON-NLS-1$
610 fParameterName= name;
612 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_ARGUMENT));
613 return new RefactoringStatus();
619 public String getDelegateUpdatingTitle(boolean plural) {
621 return RefactoringCoreMessages.DelegateCreator_keep_original_changed_plural;
623 return RefactoringCoreMessages.DelegateCreator_keep_original_changed_singular;