KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > structure > ChangeSignatureRefactoring


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.structure;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.LinkedHashMap JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.Set JavaDoc;
22 import java.util.StringTokenizer JavaDoc;
23
24 import org.eclipse.text.edits.TextEditGroup;
25
26 import org.eclipse.core.runtime.Assert;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IProgressMonitor;
29 import org.eclipse.core.runtime.NullProgressMonitor;
30 import org.eclipse.core.runtime.OperationCanceledException;
31 import org.eclipse.core.runtime.SubProgressMonitor;
32
33 import org.eclipse.core.resources.IFile;
34
35 import org.eclipse.ltk.core.refactoring.Change;
36 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
37 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
38 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
39 import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
40 import org.eclipse.ltk.core.refactoring.TextChange;
41 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
42
43 import org.eclipse.jdt.core.Flags;
44 import org.eclipse.jdt.core.ICompilationUnit;
45 import org.eclipse.jdt.core.IJavaElement;
46 import org.eclipse.jdt.core.IJavaProject;
47 import org.eclipse.jdt.core.IMethod;
48 import org.eclipse.jdt.core.IType;
49 import org.eclipse.jdt.core.ITypeHierarchy;
50 import org.eclipse.jdt.core.JavaModelException;
51 import org.eclipse.jdt.core.Signature;
52 import org.eclipse.jdt.core.compiler.IProblem;
53 import org.eclipse.jdt.core.dom.AST;
54 import org.eclipse.jdt.core.dom.ASTNode;
55 import org.eclipse.jdt.core.dom.ASTParser;
56 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
57 import org.eclipse.jdt.core.dom.Block;
58 import org.eclipse.jdt.core.dom.BodyDeclaration;
59 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
60 import org.eclipse.jdt.core.dom.CompilationUnit;
61 import org.eclipse.jdt.core.dom.ConstructorInvocation;
62 import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
63 import org.eclipse.jdt.core.dom.EnumDeclaration;
64 import org.eclipse.jdt.core.dom.Expression;
65 import org.eclipse.jdt.core.dom.IMethodBinding;
66 import org.eclipse.jdt.core.dom.ITypeBinding;
67 import org.eclipse.jdt.core.dom.ImportDeclaration;
68 import org.eclipse.jdt.core.dom.Javadoc;
69 import org.eclipse.jdt.core.dom.MemberRef;
70 import org.eclipse.jdt.core.dom.MethodDeclaration;
71 import org.eclipse.jdt.core.dom.MethodInvocation;
72 import org.eclipse.jdt.core.dom.MethodRef;
73 import org.eclipse.jdt.core.dom.MethodRefParameter;
74 import org.eclipse.jdt.core.dom.Modifier;
75 import org.eclipse.jdt.core.dom.Name;
76 import org.eclipse.jdt.core.dom.PrimitiveType;
77 import org.eclipse.jdt.core.dom.QualifiedName;
78 import org.eclipse.jdt.core.dom.SimpleName;
79 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
80 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
81 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
82 import org.eclipse.jdt.core.dom.TagElement;
83 import org.eclipse.jdt.core.dom.TextElement;
84 import org.eclipse.jdt.core.dom.Type;
85 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
86 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
87 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
88 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
89 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
90 import org.eclipse.jdt.core.search.IJavaSearchConstants;
91 import org.eclipse.jdt.core.search.IJavaSearchScope;
92 import org.eclipse.jdt.core.search.SearchPattern;
93
94 import org.eclipse.jdt.internal.corext.Corext;
95 import org.eclipse.jdt.internal.corext.SourceRange;
96 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
97 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
98 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
99 import org.eclipse.jdt.internal.corext.dom.Bindings;
100 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
101 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
102 import org.eclipse.jdt.internal.corext.dom.Selection;
103 import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer;
104 import org.eclipse.jdt.internal.corext.refactoring.Checks;
105 import org.eclipse.jdt.internal.corext.refactoring.ExceptionInfo;
106 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
107 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
108 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
109 import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
110 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
111 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
112 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine;
113 import org.eclipse.jdt.internal.corext.refactoring.ReturnTypeInfo;
114 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
115 import org.eclipse.jdt.internal.corext.refactoring.StubTypeContext;
116 import org.eclipse.jdt.internal.corext.refactoring.TypeContextChecker;
117 import org.eclipse.jdt.internal.corext.refactoring.TypeContextChecker.IProblemVerifier;
118 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
119 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext;
120 import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes;
121 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
122 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
123 import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator;
124 import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks;
125 import org.eclipse.jdt.internal.corext.refactoring.rename.RefactoringAnalyzeUtil;
126 import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2;
127 import org.eclipse.jdt.internal.corext.refactoring.rename.TempOccurrenceAnalyzer;
128 import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating;
129 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
130 import org.eclipse.jdt.internal.corext.refactoring.util.JavadocUtil;
131 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
132 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
133 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
134 import org.eclipse.jdt.internal.corext.refactoring.util.TightSourceRangeComputer;
135 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
136 import org.eclipse.jdt.internal.corext.util.JdtFlags;
137 import org.eclipse.jdt.internal.corext.util.Messages;
138
139 import org.eclipse.jdt.ui.JavaElementLabels;
140
141 import org.eclipse.jdt.internal.ui.JavaPlugin;
142
143 public class ChangeSignatureRefactoring extends ScriptableRefactoring implements IDelegateUpdating {
144     
145     private static final String JavaDoc ATTRIBUTE_RETURN= "return"; //$NON-NLS-1$
146
private static final String JavaDoc ATTRIBUTE_VISIBILITY= "visibility"; //$NON-NLS-1$
147
private static final String JavaDoc ATTRIBUTE_PARAMETER= "parameter"; //$NON-NLS-1$
148
private static final String JavaDoc ATTRIBUTE_DEFAULT= "default"; //$NON-NLS-1$
149
private static final String JavaDoc ATTRIBUTE_KIND= "kind"; //$NON-NLS-1$
150
private static final String JavaDoc ATTRIBUTE_DELEGATE= "delegate"; //$NON-NLS-1$
151
private static final String JavaDoc ATTRIBUTE_DEPRECATE= "deprecate"; //$NON-NLS-1$
152

153     private List JavaDoc fParameterInfos;
154
155     private CompilationUnitRewrite fBaseCuRewrite;
156     private List JavaDoc fExceptionInfos;
157     protected TextChangeManager fChangeManager;
158     protected List JavaDoc/*<Change>*/ fOtherChanges;
159     private IMethod fMethod;
160     private IMethod fTopMethod;
161     private IMethod[] fRippleMethods;
162     private SearchResultGroup[] fOccurrences;
163     private ReturnTypeInfo fReturnTypeInfo;
164     private String JavaDoc fMethodName;
165     private int fVisibility;
166     private static final String JavaDoc CONST_CLASS_DECL = "class A{";//$NON-NLS-1$
167
private static final String JavaDoc CONST_ASSIGN = " i="; //$NON-NLS-1$
168
private static final String JavaDoc CONST_CLOSE = ";}"; //$NON-NLS-1$
169

170     private StubTypeContext fContextCuStartEnd;
171     private int fOldVarargIndex; // initialized in checkVarargs()
172

173     private BodyUpdater fBodyUpdater;
174     private IDefaultValueAdvisor fDefaultValueAdvisor;
175
176     private ITypeHierarchy fCachedTypeHierarchy= null;
177     private boolean fDelegateUpdating;
178     private boolean fDelegateDeprecation;
179
180     /**
181      * Creates a new change signature refactoring.
182      * @param method the method, or <code>null</code> if invoked by scripting framework
183      * @throws JavaModelException
184      */

185     public ChangeSignatureRefactoring(IMethod method) throws JavaModelException {
186         fMethod= method;
187         fOldVarargIndex= -1;
188         fDelegateUpdating= false;
189         fDelegateDeprecation= true;
190         if (fMethod != null) {
191             fParameterInfos= createParameterInfoList(method);
192             // fExceptionInfos is created in checkInitialConditions
193
fReturnTypeInfo= new ReturnTypeInfo(Signature.toString(Signature.getReturnType(fMethod.getSignature())));
194             fMethodName= fMethod.getElementName();
195             fVisibility= JdtFlags.getVisibilityCode(fMethod);
196         }
197     }
198
199     private static List JavaDoc createParameterInfoList(IMethod method) {
200         try {
201             String JavaDoc[] typeNames= method.getParameterTypes();
202             String JavaDoc[] oldNames= method.getParameterNames();
203             List JavaDoc result= new ArrayList JavaDoc(typeNames.length);
204             for (int i= 0; i < oldNames.length; i++){
205                 ParameterInfo parameterInfo;
206                 if (i == oldNames.length - 1 && Flags.isVarargs(method.getFlags())) {
207                     String JavaDoc varargSignature= typeNames[i];
208                     int arrayCount= Signature.getArrayCount(varargSignature);
209                     String JavaDoc baseSignature= Signature.getElementType(varargSignature);
210                     if (arrayCount > 1)
211                         baseSignature= Signature.createArraySignature(baseSignature, arrayCount - 1);
212                     parameterInfo= new ParameterInfo(Signature.toString(baseSignature) + ParameterInfo.ELLIPSIS, oldNames[i], i);
213                 } else {
214                     parameterInfo= new ParameterInfo(Signature.toString(typeNames[i]), oldNames[i], i);
215                 }
216                 result.add(parameterInfo);
217             }
218             return result;
219         } catch(JavaModelException e) {
220             JavaPlugin.log(e);
221             return new ArrayList JavaDoc(0);
222         }
223     }
224
225     /*
226      * @see org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring#getName()
227      */

228     public String JavaDoc getName() {
229         return RefactoringCoreMessages.ChangeSignatureRefactoring_modify_Parameters;
230     }
231     
232     public IMethod getMethod() {
233         return fMethod;
234     }
235     
236     public String JavaDoc getMethodName() {
237         return fMethodName;
238     }
239     
240     public String JavaDoc getReturnTypeString() {
241         return fReturnTypeInfo.getNewTypeName();
242     }
243
244     public void setNewMethodName(String JavaDoc newMethodName){
245         Assert.isNotNull(newMethodName);
246         fMethodName= newMethodName;
247     }
248     
249     public void setNewReturnTypeName(String JavaDoc newReturnTypeName){
250         Assert.isNotNull(newReturnTypeName);
251         fReturnTypeInfo.setNewTypeName(newReturnTypeName);
252     }
253     
254     public boolean canChangeNameAndReturnType(){
255         try {
256             return ! fMethod.isConstructor();
257         } catch (JavaModelException e) {
258             JavaPlugin.log(e);
259             return false;
260         }
261     }
262     
263     /**
264      * @return visibility
265      * @see org.eclipse.jdt.core.dom.Modifier
266      */

267     public int getVisibility(){
268         return fVisibility;
269     }
270
271     /**
272      * @param visibility new visibility
273      * @see org.eclipse.jdt.core.dom.Modifier
274      */

275     public void setVisibility(int visibility){
276         Assert.isTrue( visibility == Modifier.PUBLIC ||
277                         visibility == Modifier.PROTECTED ||
278                         visibility == Modifier.NONE ||
279                         visibility == Modifier.PRIVATE);
280         fVisibility= visibility;
281     }
282     
283     /*
284      * @see JdtFlags
285      */

286     public int[] getAvailableVisibilities() throws JavaModelException{
287         if (fTopMethod.getDeclaringType().isInterface())
288             return new int[]{Modifier.PUBLIC};
289         else if (fTopMethod.getDeclaringType().isEnum() && fTopMethod.isConstructor())
290             return new int[]{ Modifier.NONE,
291                                 Modifier.PRIVATE};
292         else
293             return new int[]{ Modifier.PUBLIC,
294                                 Modifier.PROTECTED,
295                                 Modifier.NONE,
296                                 Modifier.PRIVATE};
297     }
298     
299     /**
300      *
301      * @return List of <code>ParameterInfo</code> objects.
302      */

303     public List JavaDoc getParameterInfos(){
304         return fParameterInfos;
305     }
306     
307     /**
308      * @return List of <code>ExceptionInfo</code> objects.
309      */

310     public List JavaDoc getExceptionInfos(){
311         return fExceptionInfos;
312     }
313     
314     public void setBodyUpdater(BodyUpdater bodyUpdater) {
315         fBodyUpdater= bodyUpdater;
316     }
317     
318     public CompilationUnitRewrite getBaseCuRewrite() {
319         return fBaseCuRewrite;
320     }
321     
322     //------------------- IDelegateUpdating ----------------------
323

324     public boolean canEnableDelegateUpdating() {
325         return true;
326     }
327
328     public boolean getDelegateUpdating() {
329         return fDelegateUpdating;
330     }
331
332     public void setDelegateUpdating(boolean updating) {
333         fDelegateUpdating= updating;
334     }
335
336     public void setDeprecateDelegates(boolean deprecate) {
337         fDelegateDeprecation= deprecate;
338     }
339
340     public boolean getDeprecateDelegates() {
341         return fDelegateDeprecation;
342     }
343
344     //------------------- /IDelegateUpdating ---------------------
345

346     public RefactoringStatus checkSignature() {
347         return checkSignature(false, doGetProblemVerifier());
348     }
349     
350     private RefactoringStatus checkSignature(boolean resolveBindings, IProblemVerifier problemVerifier) {
351         RefactoringStatus result= new RefactoringStatus();
352         checkMethodName(result);
353         if (result.hasFatalError())
354             return result;
355         
356         checkParameterNamesAndValues(result);
357         if (result.hasFatalError())
358             return result;
359         
360         checkForDuplicateParameterNames(result);
361         if (result.hasFatalError())
362             return result;
363         
364         try {
365             RefactoringStatus[] typeStati;
366             if (resolveBindings)
367                 typeStati= TypeContextChecker.checkAndResolveMethodTypes(fMethod, getStubTypeContext(), getNotDeletedInfos(), fReturnTypeInfo, problemVerifier);
368             else
369                 typeStati= TypeContextChecker.checkMethodTypesSyntax(fMethod, getNotDeletedInfos(), fReturnTypeInfo);
370             for (int i= 0; i < typeStati.length; i++)
371                 result.merge(typeStati[i]);
372             
373             result.merge(checkVarargs());
374         } catch (CoreException e) {
375             //cannot do anything here
376
throw new RuntimeException JavaDoc(e);
377         }
378         
379         //checkExceptions() unnecessary (IType always ok)
380
return result;
381     }
382     
383     public boolean isSignatureSameAsInitial() throws JavaModelException {
384         if (! isVisibilitySameAsInitial())
385             return false;
386         if (! isMethodNameSameAsInitial())
387             return false;
388         if (! isReturnTypeSameAsInitial())
389             return false;
390         if (! areExceptionsSameAsInitial())
391             return false;
392         
393         if (fMethod.getNumberOfParameters() == 0 && fParameterInfos.isEmpty())
394             return true;
395         
396         if (areNamesSameAsInitial() && isOrderSameAsInitial() && areParameterTypesSameAsInitial())
397             return true;
398         
399         return false;
400     }
401     
402     /**
403      * @return true if the new method cannot coexist with the old method since
404      * the signatures are too much alike
405      * @throws JavaModelException
406      */

407     public boolean isSignatureClashWithInitial() throws JavaModelException {
408
409         if (!isMethodNameSameAsInitial())
410             return false; // name has changed.
411

412         if (fMethod.getNumberOfParameters() == 0 && fParameterInfos.isEmpty())
413             return true; // name is equal and both parameter lists are empty
414

415         // name is equal and there are some parameters.
416
// check if there are more or less parameters than before
417

418         int no= getNotDeletedInfos().size();
419
420         if (fMethod.getNumberOfParameters() != no)
421             return false;
422
423         // name is equal and parameter count is equal.
424
// check whether types remained the same
425

426         if (isOrderSameAsInitial())
427             return areParameterTypesSameAsInitial();
428         else
429             return false; // could be more specific here
430
}
431
432     private boolean areParameterTypesSameAsInitial() {
433         for (Iterator JavaDoc iter= fParameterInfos.iterator(); iter.hasNext();) {
434             ParameterInfo info= (ParameterInfo) iter.next();
435             if (! info.isAdded() && ! info.isDeleted() && info.isTypeNameChanged())
436                 return false;
437         }
438         return true;
439     }
440     
441     private boolean isReturnTypeSameAsInitial() throws JavaModelException {
442         return ! fReturnTypeInfo.isTypeNameChanged();
443     }
444     
445     private boolean isMethodNameSameAsInitial() {
446         return fMethodName.equals(fMethod.getElementName());
447     }
448     
449     private boolean areExceptionsSameAsInitial() {
450         for (Iterator JavaDoc iter= fExceptionInfos.iterator(); iter.hasNext();) {
451             ExceptionInfo info= (ExceptionInfo) iter.next();
452             if (! info.isOld())
453                 return false;
454         }
455         return true;
456     }
457     
458     private void checkParameterNamesAndValues(RefactoringStatus result) {
459         int i= 1;
460         for (Iterator JavaDoc iter= fParameterInfos.iterator(); iter.hasNext(); i++) {
461             ParameterInfo info= (ParameterInfo) iter.next();
462             if (info.isDeleted())
463                 continue;
464             checkParameterName(result, info, i);
465             if (result.hasFatalError())
466                 return;
467             if (info.isAdded()) {
468                 checkParameterDefaultValue(result, info);
469                 if (result.hasFatalError())
470                     return;
471             }
472         }
473     }
474     
475     private void checkParameterName(RefactoringStatus result, ParameterInfo info, int position) {
476         if (info.getNewName().trim().length() == 0) {
477             result.addFatalError(Messages.format(
478                     RefactoringCoreMessages.ChangeSignatureRefactoring_param_name_not_empty, Integer.toString(position)));
479         } else {
480             result.merge(Checks.checkTempName(info.getNewName()));
481         }
482     }
483
484     private void checkMethodName(RefactoringStatus result) {
485         if (isMethodNameSameAsInitial() || ! canChangeNameAndReturnType())
486             return;
487         if ("".equals(fMethodName.trim())) { //$NON-NLS-1$
488
String JavaDoc msg= RefactoringCoreMessages.ChangeSignatureRefactoring_method_name_not_empty;
489             result.addFatalError(msg);
490             return;
491         }
492         if (fMethodName.equals(fMethod.getDeclaringType().getElementName())) {
493             String JavaDoc msg= RefactoringCoreMessages.ChangeSignatureRefactoring_constructor_name;
494             result.addWarning(msg);
495         }
496         result.merge(Checks.checkMethodName(fMethodName));
497     }
498
499     private void checkParameterDefaultValue(RefactoringStatus result, ParameterInfo info) {
500         if (fDefaultValueAdvisor != null)
501             return;
502         if (info.isNewVarargs()) {
503             if (! isValidVarargsExpression(info.getDefaultValue())){
504                 String JavaDoc msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_invalid_expression, new String JavaDoc[]{info.getDefaultValue()});
505                 result.addFatalError(msg);
506             }
507             return;
508         }
509         
510         if (info.getDefaultValue().trim().equals("")){ //$NON-NLS-1$
511
String JavaDoc msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_default_value, new String JavaDoc[]{info.getNewName()});
512             result.addFatalError(msg);
513             return;
514         }
515         if (! isValidExpression(info.getDefaultValue())){
516             String JavaDoc msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_invalid_expression, new String JavaDoc[]{info.getDefaultValue()});
517             result.addFatalError(msg);
518         }
519     }
520     
521     private RefactoringStatus checkVarargs() throws JavaModelException {
522         RefactoringStatus result= checkOriginalVarargs();
523         if (result != null)
524             return result;
525             
526         if (fRippleMethods != null) {
527             for (int iRipple= 0; iRipple < fRippleMethods.length; iRipple++) {
528                 IMethod rippleMethod= fRippleMethods[iRipple];
529                 if (! JdtFlags.isVarargs(rippleMethod))
530                     continue;
531                 
532                 // Vararg method can override method that takes an array as last argument
533
fOldVarargIndex= rippleMethod.getNumberOfParameters() - 1;
534                 List JavaDoc notDeletedInfos= getNotDeletedInfos();
535                 for (int i= 0; i < notDeletedInfos.size(); i++) {
536                     ParameterInfo info= (ParameterInfo) notDeletedInfos.get(i);
537                     if (fOldVarargIndex != -1 && info.getOldIndex() == fOldVarargIndex && ! info.isNewVarargs()) {
538                         String JavaDoc rippleMethodType= JavaModelUtil.getFullyQualifiedName(rippleMethod.getDeclaringType());
539                         String JavaDoc message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_ripple_cannot_convert_vararg, new Object JavaDoc[] {info.getNewName(), rippleMethodType});
540                         return RefactoringStatus.createFatalErrorStatus(message, JavaStatusContext.create(rippleMethod));
541                     }
542                 }
543             }
544         }
545         
546         return null;
547     }
548
549     private RefactoringStatus checkOriginalVarargs() throws JavaModelException {
550         if (JdtFlags.isVarargs(fMethod))
551             fOldVarargIndex= fMethod.getNumberOfParameters() - 1;
552         List JavaDoc notDeletedInfos= getNotDeletedInfos();
553         for (int i= 0; i < notDeletedInfos.size(); i++) {
554             ParameterInfo info= (ParameterInfo) notDeletedInfos.get(i);
555             if (info.isOldVarargs() && ! info.isNewVarargs())
556                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_cannot_convert_vararg, info.getNewName()));
557             if (i != notDeletedInfos.size() - 1) {
558                 // not the last parameter
559
if (info.isNewVarargs())
560                     return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_vararg_must_be_last, info.getNewName()));
561             }
562         }
563         return null;
564     }
565     
566     private RefactoringStatus checkTypeVariables() throws JavaModelException {
567         if (fRippleMethods.length == 1)
568             return null;
569         
570         RefactoringStatus result= new RefactoringStatus();
571         if (fReturnTypeInfo.isTypeNameChanged() && fReturnTypeInfo.getNewTypeBinding() != null) {
572             HashSet JavaDoc typeVariablesCollector= new HashSet JavaDoc();
573             collectTypeVariables(fReturnTypeInfo.getNewTypeBinding(), typeVariablesCollector);
574             if (typeVariablesCollector.size() != 0) {
575                 ITypeBinding first= (ITypeBinding) typeVariablesCollector.iterator().next();
576                 String JavaDoc msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_return_type_contains_type_variable, new String JavaDoc[] {fReturnTypeInfo.getNewTypeName(), first.getName()});
577                 result.addError(msg);
578             }
579         }
580         
581         for (Iterator JavaDoc iter= getNotDeletedInfos().iterator(); iter.hasNext();) {
582             ParameterInfo info= (ParameterInfo) iter.next();
583             if (info.isTypeNameChanged() && info.getNewTypeBinding() != null) {
584                 HashSet JavaDoc typeVariablesCollector= new HashSet JavaDoc();
585                 collectTypeVariables(info.getNewTypeBinding(), typeVariablesCollector);
586                 if (typeVariablesCollector.size() != 0) {
587                     ITypeBinding first= (ITypeBinding) typeVariablesCollector.iterator().next();
588                     String JavaDoc msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_parameter_type_contains_type_variable, new String JavaDoc[] {info.getNewTypeName(), info.getNewName(), first.getName()});
589                     result.addError(msg);
590                 }
591             }
592         }
593         return result;
594     }
595     
596     private void collectTypeVariables(ITypeBinding typeBinding, Set JavaDoc typeVariablesCollector) {
597         if (typeBinding.isTypeVariable()) {
598             typeVariablesCollector.add(typeBinding);
599             ITypeBinding[] typeBounds= typeBinding.getTypeBounds();
600             for (int i= 0; i < typeBounds.length; i++)
601                 collectTypeVariables(typeBounds[i], typeVariablesCollector);
602             
603         } else if (typeBinding.isArray()) {
604             collectTypeVariables(typeBinding.getElementType(), typeVariablesCollector);
605             
606         } else if (typeBinding.isParameterizedType()) {
607             ITypeBinding[] typeArguments= typeBinding.getTypeArguments();
608             for (int i= 0; i < typeArguments.length; i++)
609                 collectTypeVariables(typeArguments[i], typeVariablesCollector);
610         
611         } else if (typeBinding.isWildcardType()) {
612             ITypeBinding bound= typeBinding.getBound();
613             if (bound != null) {
614                 collectTypeVariables(bound, typeVariablesCollector);
615             }
616         }
617     }
618     
619     public static boolean isValidExpression(String JavaDoc string){
620         String JavaDoc trimmed= string.trim();
621         if ("".equals(trimmed)) //speed up for a common case //$NON-NLS-1$
622
return false;
623         StringBuffer JavaDoc cuBuff= new StringBuffer JavaDoc();
624         cuBuff.append(CONST_CLASS_DECL)
625               .append("Object") //$NON-NLS-1$
626
.append(CONST_ASSIGN);
627         int offset= cuBuff.length();
628         cuBuff.append(trimmed)
629               .append(CONST_CLOSE);
630         ASTParser p= ASTParser.newParser(AST.JLS3);
631         p.setSource(cuBuff.toString().toCharArray());
632         CompilationUnit cu= (CompilationUnit) p.createAST(null);
633         Selection selection= Selection.createFromStartLength(offset, trimmed.length());
634         SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false);
635         cu.accept(analyzer);
636         ASTNode selected= analyzer.getFirstSelectedNode();
637         return (selected instanceof Expression) &&
638                 trimmed.equals(cuBuff.substring(cu.getExtendedStartPosition(selected), cu.getExtendedStartPosition(selected) + cu.getExtendedLength(selected)));
639     }
640     
641     public static boolean isValidVarargsExpression(String JavaDoc string) {
642         String JavaDoc trimmed= string.trim();
643         if ("".equals(trimmed)) //speed up for a common case //$NON-NLS-1$
644
return true;
645         StringBuffer JavaDoc cuBuff= new StringBuffer JavaDoc();
646         cuBuff.append("class A{ {m("); //$NON-NLS-1$
647
int offset= cuBuff.length();
648         cuBuff.append(trimmed)
649               .append(");}}"); //$NON-NLS-1$
650
ASTParser p= ASTParser.newParser(AST.JLS3);
651         p.setSource(cuBuff.toString().toCharArray());
652         CompilationUnit cu= (CompilationUnit) p.createAST(null);
653         Selection selection= Selection.createFromStartLength(offset, trimmed.length());
654         SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false);
655         cu.accept(analyzer);
656         ASTNode[] selectedNodes= analyzer.getSelectedNodes();
657         if (selectedNodes.length == 0)
658             return false;
659         for (int i= 0; i < selectedNodes.length; i++) {
660             if (! (selectedNodes[i] instanceof Expression))
661                 return false;
662         }
663         return true;
664     }
665
666     public StubTypeContext getStubTypeContext() {
667         try {
668             if (fContextCuStartEnd == null)
669                 fContextCuStartEnd= TypeContextChecker.createStubTypeContext(getCu(), fBaseCuRewrite.getRoot(), fMethod.getSourceRange().getOffset());
670         } catch (CoreException e) {
671             //cannot do anything here
672
throw new RuntimeException JavaDoc(e);
673         }
674         return fContextCuStartEnd;
675     }
676
677     private ITypeHierarchy getCachedTypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
678         if (fCachedTypeHierarchy == null)
679             fCachedTypeHierarchy= fMethod.getDeclaringType().newTypeHierarchy(new SubProgressMonitor(monitor, 1));
680         return fCachedTypeHierarchy;
681     }
682
683     /*
684      * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkActivation(org.eclipse.core.runtime.IProgressMonitor)
685      */

686     public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException {
687         try {
688             monitor.beginTask("", 5); //$NON-NLS-1$
689
RefactoringStatus result= Checks.checkIfCuBroken(fMethod);
690             if (result.hasFatalError())
691                 return result;
692             if (fMethod == null || !fMethod.exists()) {
693                 String JavaDoc message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_method_deleted, getCu().getElementName());
694                 return RefactoringStatus.createFatalErrorStatus(message);
695             }
696             if (fMethod.getDeclaringType().isInterface()) {
697                 fTopMethod= MethodChecks.overridesAnotherMethod(fMethod, fMethod.getDeclaringType().newSupertypeHierarchy(new SubProgressMonitor(monitor, 1)));
698                 monitor.worked(1);
699             } else if (MethodChecks.isVirtual(fMethod)) {
700                 ITypeHierarchy hierarchy= getCachedTypeHierarchy(new SubProgressMonitor(monitor, 1));
701                 fTopMethod= MethodChecks.isDeclaredInInterface(fMethod, hierarchy, new SubProgressMonitor(monitor, 1));
702                 if (fTopMethod == null)
703                     fTopMethod= MethodChecks.overridesAnotherMethod(fMethod, hierarchy);
704             }
705             if (fTopMethod == null)
706                 fTopMethod= fMethod;
707             if (! fTopMethod.equals(fMethod)) {
708                 if (fTopMethod.getDeclaringType().isInterface()) {
709                     RefactoringStatusContext context= JavaStatusContext.create(fTopMethod);
710                     String JavaDoc message= Messages.format(RefactoringCoreMessages.MethodChecks_implements,
711                             new String JavaDoc[]{JavaElementUtil.createMethodSignature(fTopMethod), JavaModelUtil.getFullyQualifiedName(fTopMethod.getDeclaringType())});
712                     return RefactoringStatus.createStatus(RefactoringStatus.FATAL, message, context, Corext.getPluginId(), RefactoringStatusCodes.METHOD_DECLARED_IN_INTERFACE, fTopMethod);
713                 } else {
714                     RefactoringStatusContext context= JavaStatusContext.create(fTopMethod);
715                     String JavaDoc message= Messages.format(RefactoringCoreMessages.MethodChecks_overrides,
716                             new String JavaDoc[]{JavaElementUtil.createMethodSignature(fTopMethod), JavaModelUtil.getFullyQualifiedName(fTopMethod.getDeclaringType())});
717                     return RefactoringStatus.createStatus(RefactoringStatus.FATAL, message, context, Corext.getPluginId(), RefactoringStatusCodes.OVERRIDES_ANOTHER_METHOD, fTopMethod);
718                 }
719             }
720
721             if (monitor.isCanceled())
722                 throw new OperationCanceledException();
723
724             if (fBaseCuRewrite == null || !fBaseCuRewrite.getCu().equals(getCu())) {
725                 fBaseCuRewrite= new CompilationUnitRewrite(getCu());
726                 fBaseCuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());
727             }
728             monitor.worked(1);
729             result.merge(createExceptionInfoList());
730             monitor.worked(1);
731             return result;
732         } finally {
733             monitor.done();
734         }
735     }
736     
737     private RefactoringStatus createExceptionInfoList() {
738         if (fExceptionInfos == null || fExceptionInfos.isEmpty()) {
739             fExceptionInfos= new ArrayList JavaDoc(0);
740             try {
741                 ASTNode nameNode= NodeFinder.perform(fBaseCuRewrite.getRoot(), fMethod.getNameRange());
742                 if (nameNode == null || !(nameNode instanceof Name) || !(nameNode.getParent() instanceof MethodDeclaration))
743                     return null;
744                 MethodDeclaration methodDeclaration= (MethodDeclaration) nameNode.getParent();
745                 List JavaDoc exceptions= methodDeclaration.thrownExceptions();
746                 List JavaDoc result= new ArrayList JavaDoc(exceptions.size());
747                 for (int i= 0; i < exceptions.size(); i++) {
748                     Name name= (Name) exceptions.get(i);
749                     ITypeBinding typeBinding= name.resolveTypeBinding();
750                     if (typeBinding == null)
751                         return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_no_exception_binding);
752                     IType type= (IType) typeBinding.getJavaElement();
753                     result.add(ExceptionInfo.createInfoForOldException(type, typeBinding));
754                 }
755                 fExceptionInfos= result;
756             } catch (JavaModelException e) {
757                 JavaPlugin.log(e);
758             }
759         }
760         return null;
761     }
762
763     /*
764      * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkInput(org.eclipse.core.runtime.IProgressMonitor)
765      */

766     public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
767         try {
768             pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 8);
769             RefactoringStatus result= new RefactoringStatus();
770             clearManagers();
771             fBaseCuRewrite.clearASTAndImportRewrites();
772             fBaseCuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());
773
774             if (isSignatureSameAsInitial())
775                 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_unchanged);
776             result.merge(checkSignature(true, doGetProblemVerifier()));
777             if (result.hasFatalError())
778                 return result;
779             
780             if (fDelegateUpdating && isSignatureClashWithInitial())
781                 result.merge(RefactoringStatus.createErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_old_and_new_signatures_not_sufficiently_different ));
782
783             fRippleMethods= RippleMethodFinder2.getRelatedMethods(fMethod, new SubProgressMonitor(pm, 1), null);
784             result.merge(checkVarargs());
785             if (result.hasFatalError())
786                 return result;
787             
788             fOccurrences= findOccurrences(new SubProgressMonitor(pm, 1), result);
789             
790             result.merge(checkVisibilityChanges());
791             result.merge(checkTypeVariables());
792             
793             //TODO:
794
// We need a common way of dealing with possible compilation errors for all occurrences,
795
// including visibility problems, shadowing and missing throws declarations.
796

797             if (! isOrderSameAsInitial())
798                 result.merge(checkReorderings(new SubProgressMonitor(pm, 1)));
799             else
800                 pm.worked(1);
801             
802             //TODO (bug 58616): check whether changed signature already exists somewhere in the ripple,
803
// - error if exists
804
// - warn if exists with different parameter types (may cause overloading)
805

806             if (! areNamesSameAsInitial())
807                 result.merge(checkRenamings(new SubProgressMonitor(pm, 1)));
808             else
809                 pm.worked(1);
810             if (result.hasFatalError())
811                 return result;
812             
813 // resolveTypesWithoutBindings(new SubProgressMonitor(pm, 1)); // already done in checkSignature(true)
814

815             createChangeManager(new SubProgressMonitor(pm, 1), result);
816             fCachedTypeHierarchy= null;
817
818             if (mustAnalyzeAstOfDeclaringCu())
819                 result.merge(checkCompilationofDeclaringCu()); //TODO: should also check in ripple methods (move into createChangeManager)
820
if (result.hasFatalError())
821                 return result;
822
823             result.merge(validateModifiesFiles());
824             return result;
825         } finally {
826             pm.done();
827         }
828     }
829
830     protected IProblemVerifier doGetProblemVerifier() {
831         return null;
832     }
833
834     private void clearManagers() {
835         fChangeManager= null;
836         fOtherChanges= new ArrayList JavaDoc();
837     }
838     
839     private RefactoringStatus checkVisibilityChanges() throws JavaModelException {
840         if (isVisibilitySameAsInitial())
841             return null;
842         if (fRippleMethods.length == 1)
843             return null;
844         Assert.isTrue(JdtFlags.getVisibilityCode(fMethod) != Modifier.PRIVATE);
845         if (fVisibility == Modifier.PRIVATE)
846             return RefactoringStatus.createWarningStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_non_virtual);
847         return null;
848     }
849
850     public String JavaDoc getOldMethodSignature() throws JavaModelException{
851         StringBuffer JavaDoc buff= new StringBuffer JavaDoc();
852         
853         int flags= getMethod().getFlags();
854         buff.append(getVisibilityString(flags));
855         if (Flags.isStatic(flags))
856             buff.append("static "); //$NON-NLS-1$
857
if (! getMethod().isConstructor())
858             buff.append(fReturnTypeInfo.getOldTypeName())
859                 .append(' ');
860
861         buff.append(JavaElementLabels.getElementLabel(fMethod.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED));
862         buff.append('.');
863         buff.append(fMethod.getElementName())
864             .append(Signature.C_PARAM_START)
865             .append(getOldMethodParameters())
866             .append(Signature.C_PARAM_END);
867         
868         buff.append(getOldMethodThrows());
869         
870         return buff.toString();
871     }
872
873     public String JavaDoc getNewMethodSignature() throws JavaModelException{
874         StringBuffer JavaDoc buff= new StringBuffer JavaDoc();
875         
876         buff.append(getVisibilityString(fVisibility));
877         if (Flags.isStatic(getMethod().getFlags()))
878             buff.append("static "); //$NON-NLS-1$
879
if (! getMethod().isConstructor())
880             buff.append(getReturnTypeString())
881                 .append(' ');
882
883         buff.append(getMethodName())
884             .append(Signature.C_PARAM_START)
885             .append(getMethodParameters())
886             .append(Signature.C_PARAM_END);
887         
888         buff.append(getMethodThrows());
889         
890         return buff.toString();
891     }
892
893     private String JavaDoc getVisibilityString(int visibility) {
894         String JavaDoc visibilityString= JdtFlags.getVisibilityString(visibility);
895         if ("".equals(visibilityString)) //$NON-NLS-1$
896
return visibilityString;
897         return visibilityString + ' ';
898     }
899
900     private String JavaDoc getMethodThrows() {
901         final String JavaDoc throwsString= " throws "; //$NON-NLS-1$
902
StringBuffer JavaDoc buff= new StringBuffer JavaDoc(throwsString);
903         for (Iterator JavaDoc iter= fExceptionInfos.iterator(); iter.hasNext(); ) {
904             ExceptionInfo info= (ExceptionInfo) iter.next();
905             if (! info.isDeleted()) {
906                 buff.append(info.getType().getElementName());
907                 buff.append(", "); //$NON-NLS-1$
908
}
909         }
910         if (buff.length() == throwsString.length())
911             return ""; //$NON-NLS-1$
912
buff.delete(buff.length() - 2, buff.length());
913         return buff.toString();
914     }
915
916     private String JavaDoc getOldMethodThrows() {
917         final String JavaDoc throwsString= " throws "; //$NON-NLS-1$
918
StringBuffer JavaDoc buff= new StringBuffer JavaDoc(throwsString);
919         for (Iterator JavaDoc iter= fExceptionInfos.iterator(); iter.hasNext(); ) {
920             ExceptionInfo info= (ExceptionInfo) iter.next();
921             if (! info.isAdded()) {
922                 buff.append(info.getType().getElementName());
923                 buff.append(", "); //$NON-NLS-1$
924
}
925         }
926         if (buff.length() == throwsString.length())
927             return ""; //$NON-NLS-1$
928
buff.delete(buff.length() - 2, buff.length());
929         return buff.toString();
930     }
931
932     private void checkForDuplicateParameterNames(RefactoringStatus result){
933         Set JavaDoc found= new HashSet JavaDoc();
934         Set JavaDoc doubled= new HashSet JavaDoc();
935         for (Iterator JavaDoc iter = getNotDeletedInfos().iterator(); iter.hasNext();) {
936             ParameterInfo info= (ParameterInfo)iter.next();
937             String JavaDoc newName= info.getNewName();
938             if (found.contains(newName) && !doubled.contains(newName)){
939                 result.addFatalError(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_duplicate_name, newName));
940                 doubled.add(newName);
941             } else {
942                 found.add(newName);
943             }
944         }
945     }
946     
947     private ICompilationUnit getCu() {
948         return fMethod.getCompilationUnit();
949     }
950     
951     private boolean mustAnalyzeAstOfDeclaringCu() throws JavaModelException{
952         if (JdtFlags.isAbstract(getMethod()))
953             return false;
954         else if (JdtFlags.isNative(getMethod()))
955             return false;
956         else if (getMethod().getDeclaringType().isInterface())
957             return false;
958         else
959             return true;
960     }
961     
962     private RefactoringStatus checkCompilationofDeclaringCu() throws CoreException {
963         ICompilationUnit cu= getCu();
964         TextChange change= fChangeManager.get(cu);
965         String JavaDoc newCuSource= change.getPreviewContent(new NullProgressMonitor());
966         CompilationUnit newCUNode= new RefactoringASTParser(AST.JLS3).parse(newCuSource, cu, true, false, null);
967         IProblem[] problems= RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, fBaseCuRewrite.getRoot());
968         RefactoringStatus result= new RefactoringStatus();
969         for (int i= 0; i < problems.length; i++) {
970             IProblem problem= problems[i];
971             if (shouldReport(problem, newCUNode))
972                 result.addEntry(new RefactoringStatusEntry((problem.isError() ? RefactoringStatus.ERROR : RefactoringStatus.WARNING), problem.getMessage(), new JavaStringStatusContext(newCuSource, new SourceRange(problem))));
973         }
974         return result;
975     }
976         
977     private boolean shouldReport(IProblem problem, CompilationUnit cu) {
978         if (! problem.isError())
979             return false;
980         if (problem.getID() == IProblem.UndefinedType) //reported when trying to import
981
return false;
982         ASTNode node= ASTNodeSearchUtil.getAstNode(cu, problem.getSourceStart(), problem.getSourceEnd() - problem.getSourceStart());
983         IProblemVerifier verifier= doGetProblemVerifier();
984         if (verifier != null)
985             return verifier.isError(problem, node);
986         return true;
987     }
988
989     private String JavaDoc getOldMethodParameters() {
990         StringBuffer JavaDoc buff= new StringBuffer JavaDoc();
991         int i= 0;
992         for (Iterator JavaDoc iter= getNotAddedInfos().iterator(); iter.hasNext(); i++) {
993             ParameterInfo info= (ParameterInfo) iter.next();
994             if (i != 0 )
995                 buff.append(", "); //$NON-NLS-1$
996
buff.append(createDeclarationString(info));
997         }
998         return buff.toString();
999     }
1000        
1001    private String JavaDoc getMethodParameters() {
1002        StringBuffer JavaDoc buff= new StringBuffer JavaDoc();
1003        int i= 0;
1004        for (Iterator JavaDoc iter= getNotDeletedInfos().iterator(); iter.hasNext(); i++) {
1005            ParameterInfo info= (ParameterInfo) iter.next();
1006            if (i != 0 )
1007                buff.append(", "); //$NON-NLS-1$
1008
buff.append(createDeclarationString(info));
1009        }
1010        return buff.toString();
1011    }
1012
1013    private List JavaDoc getAddedInfos(){
1014        List JavaDoc result= new ArrayList JavaDoc(1);
1015        for (Iterator JavaDoc iter= fParameterInfos.iterator(); iter.hasNext();) {
1016            ParameterInfo info= (ParameterInfo) iter.next();
1017            if (info.isAdded())
1018                result.add(info);
1019        }
1020        return result;
1021    }
1022
1023    private List JavaDoc getDeletedInfos(){
1024        List JavaDoc result= new ArrayList JavaDoc(1);
1025        for (Iterator JavaDoc iter= fParameterInfos.iterator(); iter.hasNext();) {
1026            ParameterInfo info= (ParameterInfo) iter.next();
1027            if (info.isDeleted())
1028                result.add(info);
1029        }
1030        return result;
1031    }
1032
1033    private List JavaDoc getNotAddedInfos(){
1034        List JavaDoc all= new ArrayList JavaDoc(fParameterInfos);
1035        all.removeAll(getAddedInfos());
1036        return all;
1037    }
1038    
1039    private List JavaDoc getNotDeletedInfos(){
1040        List JavaDoc all= new ArrayList JavaDoc(fParameterInfos);
1041        all.removeAll(getDeletedInfos());
1042        return all;
1043    }
1044    
1045    private boolean areNamesSameAsInitial() {
1046        for (Iterator JavaDoc iter= fParameterInfos.iterator(); iter.hasNext();) {
1047            ParameterInfo info= (ParameterInfo) iter.next();
1048            if (info.isRenamed())
1049                return false;
1050        }
1051        return true;
1052    }
1053
1054    private boolean isOrderSameAsInitial(){
1055        int i= 0;
1056        for (Iterator JavaDoc iter= fParameterInfos.iterator(); iter.hasNext(); i++) {
1057            ParameterInfo info= (ParameterInfo) iter.next();
1058            if (info.getOldIndex() != i) // includes info.isAdded()
1059
return false;
1060            if (info.isDeleted())
1061                return false;
1062        }
1063        return true;
1064    }
1065
1066    private RefactoringStatus checkReorderings(IProgressMonitor pm) throws JavaModelException {
1067        try{
1068            pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 1);
1069            return checkNativeMethods();
1070        } finally{
1071            pm.done();
1072        }
1073    }
1074    
1075    private RefactoringStatus checkRenamings(IProgressMonitor pm) throws JavaModelException {
1076        try{
1077            pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 1);
1078            return checkParameterNamesInRippleMethods();
1079        } finally{
1080            pm.done();
1081        }
1082    }
1083    
1084    private RefactoringStatus checkParameterNamesInRippleMethods() throws JavaModelException {
1085        RefactoringStatus result= new RefactoringStatus();
1086        Set JavaDoc newParameterNames= getNewParameterNamesList();
1087        for (int i= 0; i < fRippleMethods.length; i++) {
1088            String JavaDoc[] paramNames= fRippleMethods[i].getParameterNames();
1089            for (int j= 0; j < paramNames.length; j++) {
1090                if (newParameterNames.contains(paramNames[j])){
1091                    String JavaDoc[] args= new String JavaDoc[]{JavaElementUtil.createMethodSignature(fRippleMethods[i]), paramNames[j]};
1092                    String JavaDoc msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_already_has, args);
1093                    RefactoringStatusContext context= JavaStatusContext.create(fRippleMethods[i].getCompilationUnit(), fRippleMethods[i].getNameRange());
1094                    result.addError(msg, context);
1095                }
1096            }
1097        }
1098        return result;
1099    }
1100    
1101    private Set JavaDoc getNewParameterNamesList() {
1102        Set JavaDoc oldNames= getOriginalParameterNames();
1103        Set JavaDoc currentNames= getNamesOfNotDeletedParameters();
1104        currentNames.removeAll(oldNames);
1105        return currentNames;
1106    }
1107    
1108    private Set JavaDoc getNamesOfNotDeletedParameters() {
1109        Set JavaDoc result= new HashSet JavaDoc();
1110        for (Iterator JavaDoc iter= getNotDeletedInfos().iterator(); iter.hasNext();) {
1111            ParameterInfo info= (ParameterInfo) iter.next();
1112            result.add(info.getNewName());
1113        }
1114        return result;
1115    }
1116    
1117    private Set JavaDoc getOriginalParameterNames() {
1118        Set JavaDoc result= new HashSet JavaDoc();
1119        for (Iterator JavaDoc iter= fParameterInfos.iterator(); iter.hasNext();) {
1120            ParameterInfo info= (ParameterInfo) iter.next();
1121            if (! info.isAdded())
1122                result.add(info.getOldName());
1123        }
1124        return result;
1125    }
1126    
1127    private RefactoringStatus checkNativeMethods() throws JavaModelException{
1128        RefactoringStatus result= new RefactoringStatus();
1129        for (int i= 0; i < fRippleMethods.length; i++) {
1130            if (JdtFlags.isNative(fRippleMethods[i])){
1131                String JavaDoc message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_native,
1132                    new String JavaDoc[]{JavaElementUtil.createMethodSignature(fRippleMethods[i]), JavaModelUtil.getFullyQualifiedName(fRippleMethods[i].getDeclaringType())});
1133                result.addError(message, JavaStatusContext.create(fRippleMethods[i]));
1134            }
1135        }
1136        return result;
1137    }
1138
1139    private IFile[] getAllFilesToModify(){
1140        return ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits());
1141    }
1142    
1143    private RefactoringStatus validateModifiesFiles(){
1144        return Checks.validateModifiesFiles(getAllFilesToModify(), getValidationContext());
1145    }
1146
1147    public Change createChange(IProgressMonitor pm) {
1148        pm.beginTask("", 1); //$NON-NLS-1$
1149
try {
1150            final TextChange[] changes= fChangeManager.getAllChanges();
1151            final List JavaDoc list= new ArrayList JavaDoc(changes.length);
1152            list.addAll(fOtherChanges);
1153            list.addAll(Arrays.asList(changes));
1154            final Map JavaDoc arguments= new HashMap JavaDoc();
1155            String JavaDoc project= null;
1156            IJavaProject javaProject= fMethod.getJavaProject();
1157            if (javaProject != null)
1158                project= javaProject.getElementName();
1159            int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE;
1160            try {
1161                if (!Flags.isPrivate(fMethod.getFlags()))
1162                    flags|= RefactoringDescriptor.MULTI_CHANGE;
1163                final IType declaring= fMethod.getDeclaringType();
1164                if (declaring.isAnonymous() || declaring.isLocal())
1165                    flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
1166            } catch (JavaModelException exception) {
1167                JavaPlugin.log(exception);
1168            }
1169            JDTRefactoringDescriptor descriptor= null;
1170            try {
1171                final String JavaDoc description= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_descriptor_description_short, fMethod.getElementName());
1172                final String JavaDoc header= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_descriptor_description, new String JavaDoc[] { getOldMethodSignature(), getNewMethodSignature()});
1173                final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
1174                if (!fMethod.getElementName().equals(fMethodName))
1175                    comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_name_pattern, fMethodName));
1176                if (!isVisibilitySameAsInitial()) {
1177                    String JavaDoc visibility= JdtFlags.getVisibilityString(fVisibility);
1178                    if ("".equals(visibility)) //$NON-NLS-1$
1179
visibility= RefactoringCoreMessages.ChangeSignatureRefactoring_default_visibility;
1180                    comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_visibility_pattern, visibility));
1181                }
1182                if (fReturnTypeInfo.isTypeNameChanged())
1183                    comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_return_type_pattern, fReturnTypeInfo.getNewTypeName()));
1184                List JavaDoc deleted= new ArrayList JavaDoc();
1185                List JavaDoc added= new ArrayList JavaDoc();
1186                List JavaDoc changed= new ArrayList JavaDoc();
1187                for (final Iterator JavaDoc iterator= fParameterInfos.iterator(); iterator.hasNext();) {
1188                    final ParameterInfo info= (ParameterInfo) iterator.next();
1189                    if (info.isDeleted())
1190                        deleted.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_deleted_parameter_pattern, new String JavaDoc[] { info.getOldTypeName(), info.getOldName()}));
1191                    else if (info.isAdded())
1192                        added.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_added_parameter_pattern, new String JavaDoc[] { info.getNewTypeName(), info.getNewName()}));
1193                    else if (info.isRenamed() || info.isTypeNameChanged() || info.isVarargChanged())
1194                        changed.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_changed_parameter_pattern, new String JavaDoc[] { info.getOldTypeName(), info.getOldName()}));
1195                }
1196                if (!added.isEmpty())
1197                    comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_added_parameters, (String JavaDoc[]) added.toArray(new String JavaDoc[added.size()])));
1198                if (!deleted.isEmpty())
1199                    comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_removed_parameters, (String JavaDoc[]) deleted.toArray(new String JavaDoc[deleted.size()])));
1200                if (!changed.isEmpty())
1201                    comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_changed_parameters, (String JavaDoc[]) changed.toArray(new String JavaDoc[changed.size()])));
1202                added.clear();
1203                deleted.clear();
1204                changed.clear();
1205                for (final Iterator JavaDoc iterator= fExceptionInfos.iterator(); iterator.hasNext();) {
1206                    final ExceptionInfo info= (ExceptionInfo) iterator.next();
1207                    if (info.isAdded())
1208                        added.add(info.getType().getElementName());
1209                    else if (info.isDeleted())
1210                        deleted.add(info.getType().getElementName());
1211                }
1212                if (!added.isEmpty())
1213                    comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_added_exceptions, (String JavaDoc[]) added.toArray(new String JavaDoc[added.size()])));
1214                if (!deleted.isEmpty())
1215                    comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_removed_exceptions, (String JavaDoc[]) deleted.toArray(new String JavaDoc[deleted.size()])));
1216                descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.CHANGE_METHOD_SIGNATURE, project, description, comment.asString(), arguments, flags);
1217                arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fMethod));
1218                arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_NAME, fMethodName);
1219                arguments.put(ATTRIBUTE_DELEGATE, Boolean.valueOf(fDelegateUpdating).toString());
1220                arguments.put(ATTRIBUTE_DEPRECATE, Boolean.valueOf(fDelegateDeprecation).toString());
1221                if (fReturnTypeInfo.isTypeNameChanged())
1222                    arguments.put(ATTRIBUTE_RETURN, fReturnTypeInfo.getNewTypeName());
1223                try {
1224                    if (!isVisibilitySameAsInitial())
1225                        arguments.put(ATTRIBUTE_VISIBILITY, new Integer JavaDoc(fVisibility).toString());
1226                } catch (JavaModelException exception) {
1227                    JavaPlugin.log(exception);
1228                }
1229                int count= 1;
1230                for (final Iterator JavaDoc iterator= fParameterInfos.iterator(); iterator.hasNext();) {
1231                    final ParameterInfo info= (ParameterInfo) iterator.next();
1232                    final StringBuffer JavaDoc buffer= new StringBuffer JavaDoc(64);
1233                    buffer.append(info.getOldTypeName());
1234                    buffer.append(" "); //$NON-NLS-1$
1235
buffer.append(info.getOldName());
1236                    buffer.append(" "); //$NON-NLS-1$
1237
buffer.append(info.getOldIndex());
1238                    buffer.append(" "); //$NON-NLS-1$
1239
buffer.append(info.getNewTypeName());
1240                    buffer.append(" "); //$NON-NLS-1$
1241
buffer.append(info.getNewName());
1242                    buffer.append(" "); //$NON-NLS-1$
1243
buffer.append(info.isDeleted());
1244                    arguments.put(ATTRIBUTE_PARAMETER + count, buffer.toString());
1245                    final String JavaDoc value= info.getDefaultValue();
1246                    if (value != null && !"".equals(value)) //$NON-NLS-1$
1247
arguments.put(ATTRIBUTE_DEFAULT + count, value);
1248                    count++;
1249                }
1250                count= 1;
1251                for (final Iterator JavaDoc iterator= fExceptionInfos.iterator(); iterator.hasNext();) {
1252                    final ExceptionInfo info= (ExceptionInfo) iterator.next();
1253                    arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count, descriptor.elementToHandle(info.getType()));
1254                    arguments.put(ATTRIBUTE_KIND + count, new Integer JavaDoc(info.getKind()).toString());
1255                    count++;
1256                }
1257            } catch (JavaModelException exception) {
1258                JavaPlugin.log(exception);
1259                return null;
1260            }
1261            return new DynamicValidationRefactoringChange(descriptor, doGetRefactoringChangeName(), (Change[]) list.toArray(new Change[list.size()]));
1262        } finally {
1263            pm.done();
1264            clearManagers();
1265        }
1266    }
1267
1268    protected String JavaDoc doGetRefactoringChangeName() {
1269        return RefactoringCoreMessages.ChangeSignatureRefactoring_restructure_parameters;
1270    }
1271
1272    private TextChangeManager createChangeManager(IProgressMonitor pm, RefactoringStatus result) throws CoreException {
1273        pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_preview, 2);
1274        fChangeManager= new TextChangeManager();
1275        boolean isNoArgConstructor= isNoArgConstructor();
1276        Map JavaDoc namedSubclassMapping= null;
1277        if (isNoArgConstructor){
1278            //create only when needed;
1279
namedSubclassMapping= createNamedSubclassMapping(new SubProgressMonitor(pm, 1));
1280        }else{
1281            pm.worked(1);
1282        }
1283        for (int i= 0; i < fOccurrences.length; i++) {
1284            if (pm.isCanceled())
1285                throw new OperationCanceledException();
1286            SearchResultGroup group= fOccurrences[i];
1287            ICompilationUnit cu= group.getCompilationUnit();
1288            if (cu == null)
1289                continue;
1290            CompilationUnitRewrite cuRewrite;
1291            if (cu.equals(getCu())) {
1292                cuRewrite= fBaseCuRewrite;
1293            } else {
1294                cuRewrite= new CompilationUnitRewrite(cu);
1295                cuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());
1296            }
1297            ASTNode[] nodes= ASTNodeSearchUtil.findNodes(group.getSearchResults(), cuRewrite.getRoot());
1298            
1299            //IntroduceParameterObjectRefactoring needs to update declarations first:
1300
List JavaDoc/*<OccurrenceUpdate>*/ deferredUpdates= new ArrayList JavaDoc();
1301            for (int j= 0; j < nodes.length; j++) {
1302                OccurrenceUpdate update= createOccurrenceUpdate(nodes[j], cuRewrite, result);
1303                if (update instanceof DeclarationUpdate) {
1304                    update.updateNode();
1305                } else {
1306                    deferredUpdates.add(update);
1307                }
1308            }
1309            for (Iterator JavaDoc iter= deferredUpdates.iterator(); iter.hasNext();) {
1310                ((OccurrenceUpdate) iter.next()).updateNode();
1311            }
1312            
1313            if (isNoArgConstructor && namedSubclassMapping.containsKey(cu)){
1314                //only non-anonymous subclasses may have noArgConstructors to modify - see bug 43444
1315
Set JavaDoc subtypes= (Set JavaDoc)namedSubclassMapping.get(cu);
1316                for (Iterator JavaDoc iter= subtypes.iterator(); iter.hasNext();) {
1317                    IType subtype= (IType) iter.next();
1318                    AbstractTypeDeclaration subtypeNode= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(subtype, cuRewrite.getRoot());
1319                    if (subtypeNode != null)
1320                        modifyImplicitCallsToNoArgConstructor(subtypeNode, cuRewrite);
1321                }
1322            }
1323            TextChange change= cuRewrite.createChange();
1324            if (change != null)
1325                fChangeManager.manage(cu, change);
1326        }
1327        
1328        pm.done();
1329        return fChangeManager;
1330    }
1331    
1332    //Map<ICompilationUnit, Set<IType>>
1333
private Map JavaDoc createNamedSubclassMapping(IProgressMonitor pm) throws JavaModelException{
1334        IType[] subclasses= getCachedTypeHierarchy(new SubProgressMonitor(pm, 1)).getSubclasses(fMethod.getDeclaringType());
1335        Map JavaDoc result= new HashMap JavaDoc();
1336        for (int i= 0; i < subclasses.length; i++) {
1337            IType subclass= subclasses[i];
1338            if (subclass.isAnonymous())
1339                continue;
1340            ICompilationUnit cu= subclass.getCompilationUnit();
1341            if (! result.containsKey(cu))
1342                result.put(cu, new HashSet JavaDoc());
1343            ((Set JavaDoc)result.get(cu)).add(subclass);
1344        }
1345        return result;
1346    }
1347    
1348    private void modifyImplicitCallsToNoArgConstructor(AbstractTypeDeclaration subclass, CompilationUnitRewrite cuRewrite) {
1349        MethodDeclaration[] constructors= getAllConstructors(subclass);
1350        if (constructors.length == 0){
1351            addNewConstructorToSubclass(subclass, cuRewrite);
1352        } else {
1353            for (int i= 0; i < constructors.length; i++) {
1354                if (! containsImplicitCallToSuperConstructor(constructors[i]))
1355                    continue;
1356                addExplicitSuperConstructorCall(constructors[i], cuRewrite);
1357            }
1358        }
1359    }
1360    
1361    private void addExplicitSuperConstructorCall(MethodDeclaration constructor, CompilationUnitRewrite cuRewrite) {
1362        SuperConstructorInvocation superCall= constructor.getAST().newSuperConstructorInvocation();
1363        addArgumentsToNewSuperConstructorCall(superCall, cuRewrite);
1364        String JavaDoc msg= RefactoringCoreMessages.ChangeSignatureRefactoring_add_super_call;
1365        TextEditGroup description= cuRewrite.createGroupDescription(msg);
1366        cuRewrite.getASTRewrite().getListRewrite(constructor.getBody(), Block.STATEMENTS_PROPERTY).insertFirst(superCall, description);
1367    }
1368    
1369    private void addArgumentsToNewSuperConstructorCall(SuperConstructorInvocation superCall, CompilationUnitRewrite cuRewrite) {
1370        int i= 0;
1371        for (Iterator JavaDoc iter= getNotDeletedInfos().iterator(); iter.hasNext(); i++) {
1372            ParameterInfo info= (ParameterInfo) iter.next();
1373            Expression newExpression= createNewExpression(info, getParameterInfos(), superCall.arguments(), cuRewrite, (MethodDeclaration) ASTNodes.getParent(superCall, MethodDeclaration.class));
1374            if (newExpression != null)
1375                superCall.arguments().add(newExpression);
1376        }
1377    }
1378    
1379    private static boolean containsImplicitCallToSuperConstructor(MethodDeclaration constructor) {
1380        Assert.isTrue(constructor.isConstructor());
1381        Block body= constructor.getBody();
1382        if (body == null)
1383            return false;
1384        if (body.statements().size() == 0)
1385            return true;
1386        if (body.statements().get(0) instanceof ConstructorInvocation)
1387            return false;
1388        if (body.statements().get(0) instanceof SuperConstructorInvocation)
1389            return false;
1390        return true;
1391    }
1392    
1393    private void addNewConstructorToSubclass(AbstractTypeDeclaration subclass, CompilationUnitRewrite cuRewrite) {
1394        AST ast= subclass.getAST();
1395        MethodDeclaration newConstructor= ast.newMethodDeclaration();
1396        newConstructor.setName(ast.newSimpleName(subclass.getName().getIdentifier()));
1397        newConstructor.setConstructor(true);
1398        newConstructor.setExtraDimensions(0);
1399        newConstructor.setJavadoc(null);
1400        newConstructor.modifiers().addAll(ASTNodeFactory.newModifiers(ast, getAccessModifier(subclass)));
1401        newConstructor.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID));
1402        Block body= ast.newBlock();
1403        newConstructor.setBody(body);
1404        SuperConstructorInvocation superCall= ast.newSuperConstructorInvocation();
1405        addArgumentsToNewSuperConstructorCall(superCall, cuRewrite);
1406        body.statements().add(superCall);
1407        
1408        String JavaDoc msg= RefactoringCoreMessages.ChangeSignatureRefactoring_add_constructor;
1409        TextEditGroup description= cuRewrite.createGroupDescription(msg);
1410        cuRewrite.getASTRewrite().getListRewrite(subclass, subclass.getBodyDeclarationsProperty()).insertFirst(newConstructor, description);
1411        
1412        // TODO use AbstractTypeDeclaration
1413
}
1414    
1415    private static int getAccessModifier(AbstractTypeDeclaration subclass) {
1416        int modifiers= subclass.getModifiers();
1417        if (Modifier.isPublic(modifiers))
1418            return Modifier.PUBLIC;
1419        else if (Modifier.isProtected(modifiers))
1420            return Modifier.PROTECTED;
1421        else if (Modifier.isPrivate(modifiers))
1422            return Modifier.PRIVATE;
1423        else
1424            return Modifier.NONE;
1425    }
1426    
1427    private MethodDeclaration[] getAllConstructors(AbstractTypeDeclaration typeDeclaration) {
1428        BodyDeclaration decl;
1429        List JavaDoc result= new ArrayList JavaDoc(1);
1430        for (Iterator JavaDoc it = typeDeclaration.bodyDeclarations().listIterator(); it.hasNext(); ) {
1431            decl= (BodyDeclaration) it.next();
1432            if (decl instanceof MethodDeclaration && ((MethodDeclaration) decl).isConstructor())
1433                result.add(decl);
1434        }
1435        return (MethodDeclaration[]) result.toArray(new MethodDeclaration[result.size()]);
1436    }
1437    
1438    private boolean isNoArgConstructor() throws JavaModelException {
1439        return fMethod.isConstructor() && fMethod.getNumberOfParameters() == 0;
1440    }
1441    
1442    private Expression createNewExpression(ParameterInfo info, List JavaDoc parameterInfos, List JavaDoc nodes, CompilationUnitRewrite cuRewrite, MethodDeclaration method) {
1443        if (info.isNewVarargs() && info.getDefaultValue().trim().length() == 0)
1444            return null;
1445        else {
1446            if (fDefaultValueAdvisor == null)
1447                return (Expression) cuRewrite.getASTRewrite().createStringPlaceholder(info.getDefaultValue(), ASTNode.METHOD_INVOCATION);
1448            else
1449                return fDefaultValueAdvisor.createDefaultExpression(nodes, info, parameterInfos, method, false, cuRewrite);
1450        }
1451    }
1452
1453    private boolean isVisibilitySameAsInitial() throws JavaModelException {
1454        return fVisibility == JdtFlags.getVisibilityCode(fMethod);
1455    }
1456    
1457    private IJavaSearchScope createRefactoringScope() throws JavaModelException{
1458        return RefactoringScopeFactory.create(fMethod);
1459    }
1460    
1461    private SearchResultGroup[] findOccurrences(IProgressMonitor pm, RefactoringStatus status) throws JavaModelException{
1462        if (fMethod.isConstructor()){
1463            // workaround for bug 27236:
1464
return ConstructorReferenceFinder.getConstructorOccurrences(fMethod, pm, status);
1465        }else{
1466            SearchPattern pattern= RefactoringSearchEngine.createOrPattern(fRippleMethods, IJavaSearchConstants.ALL_OCCURRENCES);
1467            return RefactoringSearchEngine.search(pattern, createRefactoringScope(), pm, status);
1468        }
1469    }
1470    
1471    private static String JavaDoc createDeclarationString(ParameterInfo info) {
1472        String JavaDoc newTypeName= info.getNewTypeName();
1473        int index= newTypeName.indexOf('.');
1474        if (index != -1){
1475            newTypeName= newTypeName.substring(index+1);
1476        }
1477        return newTypeName + " " + info.getNewName(); //$NON-NLS-1$
1478
}
1479    
1480    private static final boolean BUG_89686= true; //see bug 83693: Search for References to methods/constructors: do ranges include parameter lists?
1481

1482    private OccurrenceUpdate createOccurrenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
1483        if (BUG_89686 && node instanceof SimpleName && node.getParent() instanceof EnumConstantDeclaration)
1484            node= node.getParent();
1485        
1486        if (isReferenceNode(node))
1487            return new ReferenceUpdate(node, cuRewrite, result);
1488        
1489        else if (node instanceof SimpleName && node.getParent() instanceof MethodDeclaration)
1490            return new DeclarationUpdate((MethodDeclaration) node.getParent(), cuRewrite, result);
1491        
1492        else if (node instanceof MemberRef || node instanceof MethodRef)
1493            return new DocReferenceUpdate(node, cuRewrite, result);
1494        
1495        else if (ASTNodes.getParent(node, ImportDeclaration.class) != null)
1496            return new StaticImportUpdate((ImportDeclaration) ASTNodes.getParent(node, ImportDeclaration.class), cuRewrite, result);
1497        
1498        else
1499            return new NullOccurrenceUpdate(node, cuRewrite, result);
1500    }
1501
1502    private static boolean isReferenceNode(ASTNode node){
1503        switch (node.getNodeType()) {
1504            case ASTNode.METHOD_INVOCATION :
1505            case ASTNode.SUPER_METHOD_INVOCATION :
1506            case ASTNode.CLASS_INSTANCE_CREATION :
1507            case ASTNode.CONSTRUCTOR_INVOCATION :
1508            case ASTNode.SUPER_CONSTRUCTOR_INVOCATION :
1509            case ASTNode.ENUM_CONSTANT_DECLARATION :
1510                return true;
1511
1512            default :
1513                return false;
1514        }
1515    }
1516
1517    abstract class OccurrenceUpdate {
1518        protected final CompilationUnitRewrite fCuRewrite;
1519        protected final TextEditGroup fDescription;
1520        protected RefactoringStatus fResult;
1521        
1522        protected OccurrenceUpdate(CompilationUnitRewrite cuRewrite, TextEditGroup description, RefactoringStatus result) {
1523            fCuRewrite= cuRewrite;
1524            fDescription= description;
1525            fResult= result;
1526        }
1527        
1528        protected final ASTRewrite getASTRewrite() {
1529            return fCuRewrite.getASTRewrite();
1530        }
1531
1532        protected final ImportRewrite getImportRewrite() {
1533            return fCuRewrite.getImportRewrite();
1534        }
1535        
1536        protected final ImportRemover getImportRemover() {
1537            return fCuRewrite.getImportRemover();
1538        }
1539        
1540        protected final CompilationUnitRewrite getCompilationUnitRewrite() {
1541            return fCuRewrite;
1542        }
1543        
1544        public abstract void updateNode() throws CoreException;
1545        
1546        protected void registerImportRemoveNode(ASTNode node) {
1547            getImportRemover().registerRemovedNode(node);
1548        }
1549
1550        protected final void reshuffleElements() {
1551            if (isOrderSameAsInitial())
1552                return;
1553            
1554            //varargs; method(p1, p2, .., pn), call(a1, a2, .., ax) :
1555
// if (method_was_vararg) {
1556
// assert fOldVarargIndex != -1
1557
// if (vararg_retained) {
1558
// assert vararg_is_last_non_deleted (pn)
1559
// assert no_other_varargs
1560
// => reshuffle [1..n-1] then append remaining nodes [n..x], possibly none
1561
//
1562
// } else (vararg_deleted) {
1563
// assert all_are_non_vararg
1564
// => reshuffle [1..n-1], drop all remaining nodes [n..x], possibly none
1565
// }
1566
//
1567
// } else if (method_became_vararg) {
1568
// assert n == x
1569
// assert fOldVarargIndex == -1
1570
// => reshuffle [1..n]
1571
//
1572
// } else (JLS2_case) {
1573
// assert n == x
1574
// assert fOldVarargIndex == -1
1575
// => reshuffle [1..n]
1576
// }
1577

1578            ListRewrite listRewrite= getParamgumentsRewrite();
1579            Map JavaDoc newOldMap= new LinkedHashMap JavaDoc();
1580            List JavaDoc nodes= listRewrite.getRewrittenList();
1581            Iterator JavaDoc rewriteIter= nodes.iterator();
1582            List JavaDoc original= listRewrite.getOriginalList();
1583            for (Iterator JavaDoc iter= original.iterator(); iter.hasNext();) {
1584                newOldMap.put(rewriteIter.next(),iter.next());
1585            }
1586            List JavaDoc newNodes= new ArrayList JavaDoc();
1587            // register removed nodes, and collect nodes in new sequence:
1588
for (int i= 0; i < fParameterInfos.size(); i++) {
1589                ParameterInfo info= (ParameterInfo) fParameterInfos.get(i);
1590                int oldIndex= info.getOldIndex();
1591                
1592                if (info.isDeleted()) {
1593                    if (oldIndex != fOldVarargIndex) {
1594                        registerImportRemoveNode((ASTNode) nodes.get(oldIndex));
1595                    } else {
1596                        //vararg deleted -> remove all remaining nodes:
1597
for (int n= oldIndex; n < nodes.size(); n++) {
1598                            registerImportRemoveNode((ASTNode) nodes.get(n));
1599                        }
1600                    }
1601                    
1602                } else if (info.isAdded()) {
1603                    ASTNode newParamgument= createNewParamgument(info, fParameterInfos, nodes);
1604                    if (newParamgument != null)
1605                        newNodes.add(newParamgument);
1606                    
1607                } else /* parameter stays */ {
1608                    if (oldIndex != fOldVarargIndex) {
1609                        ASTNode oldNode= (ASTNode) nodes.get(oldIndex);
1610                        ASTNode movedNode= moveNode(oldNode, getASTRewrite());
1611                        newNodes.add(movedNode);
1612                    } else {
1613                        //vararg stays and is last parameter -> copy all remaining nodes:
1614
for (int n= oldIndex; n < nodes.size(); n++) {
1615                            ASTNode oldNode= (ASTNode) nodes.get(n);
1616                            ASTNode movedNode= moveNode(oldNode, getASTRewrite());
1617                            newNodes.add(movedNode);
1618                        }
1619                    }
1620                }
1621            }
1622            
1623            Iterator JavaDoc nodesIter= nodes.iterator();
1624            Iterator JavaDoc newIter= newNodes.iterator();
1625            //replace existing nodes with new ones:
1626
while (nodesIter.hasNext() && newIter.hasNext()) {
1627                ASTNode node= (ASTNode) nodesIter.next();
1628                ASTNode newNode= (ASTNode) newIter.next();
1629                if (!ASTNodes.isExistingNode(node)) //XXX:should better be addressed in ListRewriteEvent.replaceEntry(ASTNode, ASTNode)
1630
listRewrite.replace((ASTNode) newOldMap.get(node), newNode, fDescription);
1631                else
1632                    listRewrite.replace(node, newNode, fDescription);
1633            }
1634            //remove remaining existing nodes:
1635
while (nodesIter.hasNext()) {
1636                ASTNode node= (ASTNode) nodesIter.next();
1637                if (!ASTNodes.isExistingNode(node))
1638                    listRewrite.remove((ASTNode) newOldMap.get(node), fDescription);
1639                else
1640                    listRewrite.remove(node, fDescription);
1641            }
1642            //add additional new nodes:
1643
while (newIter.hasNext()) {
1644                ASTNode node= (ASTNode) newIter.next();
1645                listRewrite.insertLast(node, fDescription);
1646            }
1647        }
1648
1649        /**
1650         * @return ListRewrite of parameters or arguments
1651         */

1652        protected abstract ListRewrite getParamgumentsRewrite();
1653        
1654        protected final void changeParamguments() {
1655            for (Iterator JavaDoc iter= getParameterInfos().iterator(); iter.hasNext();) {
1656                ParameterInfo info= (ParameterInfo) iter.next();
1657                if (info.isAdded() || info.isDeleted())
1658                    continue;
1659                
1660                if (info.isRenamed())
1661                    changeParamgumentName(info);
1662        
1663                if (info.isTypeNameChanged())
1664                    changeParamgumentType(info);
1665            }
1666        }
1667
1668        protected void changeParamgumentName(ParameterInfo info) {
1669            // no-op
1670
}
1671
1672        protected void changeParamgumentType(ParameterInfo info) {
1673            // no-op
1674
}
1675
1676        protected final void replaceTypeNode(Type typeNode, String JavaDoc newTypeName, ITypeBinding newTypeBinding){
1677            Type newTypeNode= createNewTypeNode(newTypeName, newTypeBinding);
1678            getASTRewrite().replace(typeNode, newTypeNode, fDescription);
1679            registerImportRemoveNode(typeNode);
1680            getTightSourceRangeComputer().addTightSourceNode(typeNode);
1681        }
1682    
1683        /**
1684         * @param info
1685         * @param parameterInfos TODO
1686         * @param nodes TODO
1687         * @return a new method parameter or argument, or <code>null</code> for an empty vararg argument
1688         */

1689        protected abstract ASTNode createNewParamgument(ParameterInfo info, List JavaDoc parameterInfos, List JavaDoc nodes);
1690
1691        protected abstract SimpleName getMethodNameNode();
1692
1693        protected final void changeMethodName() {
1694            if (! isMethodNameSameAsInitial()) {
1695                SimpleName nameNode= getMethodNameNode();
1696                SimpleName newNameNode= nameNode.getAST().newSimpleName(fMethodName);
1697                getASTRewrite().replace(nameNode, newNameNode, fDescription);
1698                registerImportRemoveNode(nameNode);
1699                getTightSourceRangeComputer().addTightSourceNode(nameNode);
1700            }
1701        }
1702
1703        protected final Type createNewTypeNode(String JavaDoc newTypeName, ITypeBinding newTypeBinding) {
1704            Type newTypeNode;
1705            if (newTypeBinding == null) {
1706                if (fDefaultValueAdvisor != null)
1707                    newTypeNode= fDefaultValueAdvisor.createType(newTypeName, getMethodNameNode().getStartPosition(), getCompilationUnitRewrite());
1708                else
1709                    newTypeNode= (Type) getASTRewrite().createStringPlaceholder(newTypeName, ASTNode.SIMPLE_TYPE);
1710                //Don't import if not resolved.
1711
} else {
1712                newTypeNode= getImportRewrite().addImport(newTypeBinding, fCuRewrite.getAST());
1713                getImportRemover().registerAddedImports(newTypeNode);
1714            }
1715            return newTypeNode;
1716        }
1717        
1718        protected final TightSourceRangeComputer getTightSourceRangeComputer() {
1719            return (TightSourceRangeComputer) fCuRewrite.getASTRewrite().getExtendedSourceRangeComputer();
1720        }
1721    }
1722    
1723    class ReferenceUpdate extends OccurrenceUpdate {
1724        /** isReferenceNode(fNode) */
1725        private ASTNode fNode;
1726
1727        protected ReferenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
1728            super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_update_reference), result);
1729            fNode= node; //holds: Assert.isTrue(isReferenceNode(node));
1730
}
1731
1732        public void updateNode() {
1733            reshuffleElements();
1734            changeMethodName();
1735        }
1736        
1737        /** @return {@inheritDoc} (element type: Expression) */
1738        protected ListRewrite getParamgumentsRewrite() {
1739            if (fNode instanceof MethodInvocation)
1740                return getASTRewrite().getListRewrite(fNode, MethodInvocation.ARGUMENTS_PROPERTY);
1741                
1742            if (fNode instanceof SuperMethodInvocation)
1743                return getASTRewrite().getListRewrite(fNode, SuperMethodInvocation.ARGUMENTS_PROPERTY);
1744                
1745            if (fNode instanceof ClassInstanceCreation)
1746                return getASTRewrite().getListRewrite(fNode, ClassInstanceCreation.ARGUMENTS_PROPERTY);
1747                
1748            if (fNode instanceof ConstructorInvocation)
1749                return getASTRewrite().getListRewrite(fNode, ConstructorInvocation.ARGUMENTS_PROPERTY);
1750                
1751            if (fNode instanceof SuperConstructorInvocation)
1752                return getASTRewrite().getListRewrite(fNode, SuperConstructorInvocation.ARGUMENTS_PROPERTY);
1753            
1754            if (fNode instanceof EnumConstantDeclaration)
1755                return getASTRewrite().getListRewrite(fNode, EnumConstantDeclaration.ARGUMENTS_PROPERTY);
1756            
1757            return null;
1758        }
1759        
1760        protected ASTNode createNewParamgument(ParameterInfo info, List JavaDoc parameterInfos, List JavaDoc nodes) {
1761            CompilationUnitRewrite cuRewrite= getCompilationUnitRewrite();
1762            MethodDeclaration declaration= (MethodDeclaration) ASTNodes.getParent(fNode, MethodDeclaration.class);
1763            if (isRecursiveReference()) {
1764                return createNewExpressionRecursive(info, parameterInfos, nodes, cuRewrite, declaration);
1765            } else
1766                return createNewExpression(info, parameterInfos, nodes, cuRewrite, declaration);
1767        }
1768
1769        private Expression createNewExpressionRecursive(ParameterInfo info, List JavaDoc parameterInfos, List JavaDoc nodes, CompilationUnitRewrite cuRewrite, MethodDeclaration methodDeclaration) {
1770            if (fDefaultValueAdvisor != null && info.isAdded()) {
1771                return fDefaultValueAdvisor.createDefaultExpression(nodes, info, parameterInfos, methodDeclaration, true, cuRewrite);
1772            }
1773            return (Expression) getASTRewrite().createStringPlaceholder(info.getNewName(), ASTNode.METHOD_INVOCATION);
1774        }
1775
1776        protected SimpleName getMethodNameNode() {
1777            if (fNode instanceof MethodInvocation)
1778                return ((MethodInvocation)fNode).getName();
1779                
1780            if (fNode instanceof SuperMethodInvocation)
1781                return ((SuperMethodInvocation)fNode).getName();
1782                
1783            return null;
1784        }
1785        
1786        private boolean isRecursiveReference() {
1787            MethodDeclaration enclosingMethodDeclaration= (MethodDeclaration) ASTNodes.getParent(fNode, MethodDeclaration.class);
1788            if (enclosingMethodDeclaration == null)
1789                return false;
1790            
1791            IMethodBinding enclosingMethodBinding= enclosingMethodDeclaration.resolveBinding();
1792            if (enclosingMethodBinding == null)
1793                return false;
1794            
1795            if (fNode instanceof MethodInvocation)
1796                return enclosingMethodBinding == ((MethodInvocation)fNode).resolveMethodBinding();
1797                
1798            if (fNode instanceof SuperMethodInvocation) {
1799                IMethodBinding methodBinding= ((SuperMethodInvocation)fNode).resolveMethodBinding();
1800                return isSameMethod(methodBinding, enclosingMethodBinding);
1801            }
1802                
1803            if (fNode instanceof ClassInstanceCreation)
1804                return enclosingMethodBinding == ((ClassInstanceCreation)fNode).resolveConstructorBinding();
1805                
1806            if (fNode instanceof ConstructorInvocation)
1807                return enclosingMethodBinding == ((ConstructorInvocation)fNode).resolveConstructorBinding();
1808                
1809            if (fNode instanceof SuperConstructorInvocation) {
1810                return false; //Constructors don't override -> enclosing has not been changed -> no recursion
1811
}
1812            
1813            if (fNode instanceof EnumConstantDeclaration) {
1814                return false; //cannot define enum constant inside enum constructor
1815
}
1816
1817            Assert.isTrue(false);
1818            return false;
1819        }
1820        
1821        /**
1822         * @param m1 method 1
1823         * @param m2 method 2
1824         * @return true iff
1825         * <ul><li>the methods are both constructors with same argument types, or</li>
1826         * <li>the methods have the same name and the same argument types</li></ul>
1827         */

1828        private boolean isSameMethod(IMethodBinding m1, IMethodBinding m2) {
1829            if (m1.isConstructor()) {
1830                if (! m2.isConstructor())
1831                    return false;
1832            } else {
1833                if (! m1.getName().equals(m2.getName()))
1834                    return false;
1835            }
1836            
1837            ITypeBinding[] m1Parameters= m1.getParameterTypes();
1838            ITypeBinding[] m2Parameters= m2.getParameterTypes();
1839            if (m1Parameters.length != m2Parameters.length)
1840                return false;
1841            for (int i= 0; i < m1Parameters.length; i++) {
1842                if (m1Parameters[i].getErasure() != m2Parameters[i].getErasure())
1843                    return false;
1844            }
1845            return true;
1846        }
1847
1848    }
1849
1850    class DeclarationUpdate extends OccurrenceUpdate {
1851        private MethodDeclaration fMethDecl;
1852
1853        protected DeclarationUpdate(MethodDeclaration decl, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
1854            super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_change_signature), result);
1855            fMethDecl= decl;
1856        }
1857        
1858        // Prevent import removing if delegate is created.
1859
protected void registerImportRemoveNode(ASTNode node) {
1860            if (!fDelegateUpdating)
1861                super.registerImportRemoveNode(node);
1862        }
1863
1864        public void updateNode() throws CoreException {
1865            changeParamguments();
1866            
1867            if (canChangeNameAndReturnType()) {
1868                changeMethodName();
1869                changeReturnType();
1870            }
1871                    
1872            if (needsVisibilityUpdate())
1873                changeVisibility();
1874            reshuffleElements();
1875            changeExceptions();
1876            
1877            changeJavadocTags();
1878            
1879            if (fBodyUpdater == null || fBodyUpdater.needsParameterUsedCheck())
1880                checkIfDeletedParametersUsed();
1881            
1882            if (fBodyUpdater != null)
1883                fBodyUpdater.updateBody(fMethDecl, fCuRewrite, fResult);
1884            
1885            if (fDelegateUpdating)
1886                addDelegate();
1887        }
1888
1889        private void addDelegate() throws JavaModelException {
1890
1891            DelegateMethodCreator creator= new DelegateMethodCreator();
1892            creator.setDeclaration(fMethDecl);
1893            creator.setDeclareDeprecated(fDelegateDeprecation);
1894            creator.setSourceRewrite(fCuRewrite);
1895            creator.prepareDelegate();
1896            
1897            /*
1898             * The delegate now contains a call and a javadoc reference to the
1899             * old method (i.e., to itself).
1900             *
1901             * Use ReferenceUpdate() / DocReferenceUpdate() to update these
1902             * references like any other reference.
1903             */

1904            final ASTNode delegateInvocation= creator.getDelegateInvocation();
1905            if (delegateInvocation != null)
1906                // may be null if the delegate is an interface method or
1907
// abstract -> no body
1908
new ReferenceUpdate(delegateInvocation, creator.getDelegateRewrite(), fResult).updateNode();
1909            new DocReferenceUpdate(creator.getJavadocReference(), creator.getDelegateRewrite(), fResult).updateNode();
1910            
1911            creator.createEdit();
1912        }
1913        
1914        /** @return {@inheritDoc} (element type: SingleVariableDeclaration) */
1915        protected ListRewrite getParamgumentsRewrite() {
1916            return getASTRewrite().getListRewrite(fMethDecl, MethodDeclaration.PARAMETERS_PROPERTY);
1917        }
1918
1919        protected void changeParamgumentName(ParameterInfo info) {
1920            SingleVariableDeclaration param= (SingleVariableDeclaration) fMethDecl.parameters().get(info.getOldIndex());
1921            if (! info.getOldName().equals(param.getName().getIdentifier()))
1922                return; //don't change if original parameter name != name in rippleMethod
1923

1924            String JavaDoc msg= RefactoringCoreMessages.ChangeSignatureRefactoring_update_parameter_references;
1925            TextEditGroup description= fCuRewrite.createGroupDescription(msg);
1926            TempOccurrenceAnalyzer analyzer= new TempOccurrenceAnalyzer(param, false);
1927            analyzer.perform();
1928            SimpleName[] paramOccurrences= analyzer.getReferenceAndDeclarationNodes(); // @param tags are updated in changeJavaDocTags()
1929
for (int j= 0; j < paramOccurrences.length; j++) {
1930                SimpleName occurence= paramOccurrences[j];
1931                getASTRewrite().set(occurence, SimpleName.IDENTIFIER_PROPERTY, info.getNewName(), description);
1932            }
1933        }
1934        
1935        protected void changeParamgumentType(ParameterInfo info) {
1936            SingleVariableDeclaration oldParam= (SingleVariableDeclaration) fMethDecl.parameters().get(info.getOldIndex());
1937            getASTRewrite().set(oldParam, SingleVariableDeclaration.VARARGS_PROPERTY, Boolean.valueOf(info.isNewVarargs()), fDescription);
1938            replaceTypeNode(oldParam.getType(), ParameterInfo.stripEllipsis(info.getNewTypeName()), info.getNewTypeBinding());
1939            removeExtraDimensions(oldParam);
1940        }
1941
1942        private void removeExtraDimensions(SingleVariableDeclaration oldParam) {
1943            if (oldParam.getExtraDimensions() != 0) {
1944                getASTRewrite().set(oldParam, SingleVariableDeclaration.EXTRA_DIMENSIONS_PROPERTY, new Integer JavaDoc(0), fDescription);
1945            }
1946        }
1947    
1948        private void changeReturnType() throws JavaModelException {
1949            if (isReturnTypeSameAsInitial())
1950                return;
1951            replaceTypeNode(fMethDecl.getReturnType2(), fReturnTypeInfo.getNewTypeName(), fReturnTypeInfo.getNewTypeBinding());
1952            removeExtraDimensions(fMethDecl);
1953            //Remove expression from return statement when changed to void? No, would lose information!
1954
//Could add return statement with default value and add todo comment, but compile error is better.
1955
}
1956    
1957        private void removeExtraDimensions(MethodDeclaration methDecl) {
1958            if (methDecl.getExtraDimensions() != 0)
1959                getASTRewrite().set(methDecl, MethodDeclaration.EXTRA_DIMENSIONS_PROPERTY, new Integer JavaDoc(0), fDescription);
1960        }
1961
1962        private boolean needsVisibilityUpdate() throws JavaModelException {
1963            if (isVisibilitySameAsInitial())
1964                return false;
1965            if (isIncreasingVisibility())
1966                return JdtFlags.isHigherVisibility(fVisibility, JdtFlags.getVisibilityCode(fMethDecl));
1967            else
1968                return JdtFlags.isHigherVisibility(JdtFlags.getVisibilityCode(fMethDecl), fVisibility);
1969        }
1970        
1971        private boolean isIncreasingVisibility() throws JavaModelException{
1972            return JdtFlags.isHigherVisibility(fVisibility, JdtFlags.getVisibilityCode(fMethod));
1973        }
1974        
1975        private void changeVisibility() {
1976            ModifierRewrite.create(getASTRewrite(), fMethDecl).setVisibility(fVisibility, fDescription);
1977        }
1978    
1979        private void changeExceptions() {
1980            for (Iterator JavaDoc iter= fExceptionInfos.iterator(); iter.hasNext();) {
1981                ExceptionInfo info= (ExceptionInfo) iter.next();
1982                if (info.isOld())
1983                    continue;
1984                if (info.isDeleted())
1985                    removeExceptionFromNodeList(info, fMethDecl.thrownExceptions());
1986                else
1987                    addExceptionToNodeList(info, getASTRewrite().getListRewrite(fMethDecl, MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY));
1988            }
1989        }
1990        
1991        private void removeExceptionFromNodeList(ExceptionInfo toRemove, List JavaDoc exceptionsNodeList) {
1992            ITypeBinding typeToRemove= toRemove.getTypeBinding();
1993            for (Iterator JavaDoc iter= exceptionsNodeList.iterator(); iter.hasNext(); ) {
1994                Name currentName= (Name) iter.next();
1995                ITypeBinding currentType= currentName.resolveTypeBinding();
1996                /* Maybe remove all subclasses of typeToRemove too.
1997                 * Problem:
1998                 * - B extends A;
1999                 * - A.m() throws IOException, Exception;
2000                 * - B.m() throws IOException, AWTException;
2001                 * Removing Exception should remove AWTException,
2002                 * but NOT remove IOException (or a subclass of JavaModelException). */

2003                 // if (Bindings.isSuperType(typeToRemove, currentType))
2004
if (currentType == null)
2005                    continue; // newly added or unresolvable type
2006
if (Bindings.equals(currentType, typeToRemove) || toRemove.getType().getElementName().equals(currentType.getName())) {
2007                    getASTRewrite().remove(currentName, fDescription);
2008                    registerImportRemoveNode(currentName);
2009                }
2010            }
2011        }
2012    
2013        private void addExceptionToNodeList(ExceptionInfo exceptionInfo, ListRewrite exceptionListRewrite) {
2014            String JavaDoc fullyQualified= JavaModelUtil.getFullyQualifiedName(exceptionInfo.getType());
2015            for (Iterator JavaDoc iter= exceptionListRewrite.getOriginalList().iterator(); iter.hasNext(); ) {
2016                Name exName= (Name) iter.next();
2017                //XXX: existing superclasses of the added exception are redundant and could be removed
2018
ITypeBinding typeBinding= exName.resolveTypeBinding();
2019                if (typeBinding == null)
2020                    continue; // newly added or unresolvable type
2021
if (typeBinding.getQualifiedName().equals(fullyQualified))
2022                    return; // don't add it again
2023
}
2024            String JavaDoc importedType= getImportRewrite().addImport(JavaModelUtil.getFullyQualifiedName(exceptionInfo.getType()));
2025            getImportRemover().registerAddedImport(importedType);
2026            ASTNode exNode= getASTRewrite().createStringPlaceholder(importedType, ASTNode.SIMPLE_NAME);
2027            exceptionListRewrite.insertLast(exNode, fDescription);
2028        }
2029        
2030        private void changeJavadocTags() throws JavaModelException {
2031            //update tags in javadoc: @param, @return, @exception, @throws, ...
2032
Javadoc javadoc= fMethDecl.getJavadoc();
2033            if (javadoc == null)
2034                return;
2035
2036            ITypeBinding typeBinding= Bindings.getBindingOfParentType(fMethDecl);
2037            if (typeBinding == null)
2038                return;
2039            IMethodBinding methodBinding= fMethDecl.resolveBinding();
2040            if (methodBinding == null)
2041                return;
2042                
2043            boolean isTopOfRipple= (Bindings.findOverriddenMethod(methodBinding, false) == null);
2044            //add tags: only iff top of ripple; change and remove: always.
2045
//TODO: should have preference for adding tags in (overriding) methods (with template: todo, inheritDoc, ...)
2046

2047            List JavaDoc tags= javadoc.tags(); // List of TagElement
2048
ListRewrite tagsRewrite= getASTRewrite().getListRewrite(javadoc, Javadoc.TAGS_PROPERTY);
2049
2050            if (! isReturnTypeSameAsInitial()) {
2051                if (PrimitiveType.VOID.toString().equals(fReturnTypeInfo.getNewTypeName())) {
2052                    for (int i = 0; i < tags.size(); i++) {
2053                        TagElement tag= (TagElement) tags.get(i);
2054                        if (TagElement.TAG_RETURN.equals(tag.getTagName())) {
2055                            getASTRewrite().remove(tag, fDescription);
2056                            registerImportRemoveNode(tag);
2057                        }
2058                    }
2059                } else if (isTopOfRipple && Signature.SIG_VOID.equals(fMethod.getReturnType())){
2060                    TagElement returnNode= createReturnTag();
2061                    TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_RETURN);
2062                    insertTag(returnNode, previousTag, tagsRewrite);
2063                    tags= tagsRewrite.getRewrittenList();
2064                }
2065            }
2066            
2067            if (! (areNamesSameAsInitial() && isOrderSameAsInitial())) {
2068                ArrayList JavaDoc paramTags= new ArrayList JavaDoc(); // <TagElement>, only not deleted tags with simpleName
2069
// delete & rename:
2070
for (Iterator JavaDoc iter = tags.iterator(); iter.hasNext(); ) {
2071                    TagElement tag = (TagElement) iter.next();
2072                    String JavaDoc tagName= tag.getTagName();
2073                    List JavaDoc fragments= tag.fragments();
2074                    if (! (TagElement.TAG_PARAM.equals(tagName) && fragments.size() > 0 && fragments.get(0) instanceof SimpleName))
2075                        continue;
2076                    SimpleName simpleName= (SimpleName) fragments.get(0);
2077                    String JavaDoc identifier= simpleName.getIdentifier();
2078                    boolean removed= false;
2079                    for (int i= 0; i < fParameterInfos.size(); i++) {
2080                        ParameterInfo info= (ParameterInfo) fParameterInfos.get(i);
2081                        if (identifier.equals(info.getOldName())) {
2082                            if (info.isDeleted()) {
2083                                getASTRewrite().remove(tag, fDescription);
2084                                registerImportRemoveNode(tag);
2085                                removed= true;
2086                            } else if (info.isRenamed()) {
2087                                SimpleName newName= simpleName.getAST().newSimpleName(info.getNewName());
2088                                getASTRewrite().replace(simpleName, newName, fDescription);
2089                                registerImportRemoveNode(tag);
2090                            }
2091                            break;
2092                        }
2093                    }
2094                    if (! removed)
2095                        paramTags.add(tag);
2096                }
2097                tags= tagsRewrite.getRewrittenList();
2098
2099                if (! isOrderSameAsInitial()) {
2100                    // reshuffle (sort in declaration sequence) & add (only add to top of ripple):
2101
TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_PARAM);
2102                    boolean first= true; // workaround for bug 92111: preserve first tag if possible
2103
// reshuffle:
2104
for (Iterator JavaDoc infoIter= fParameterInfos.iterator(); infoIter.hasNext();) {
2105                        ParameterInfo info= (ParameterInfo) infoIter.next();
2106                        String JavaDoc oldName= info.getOldName();
2107                        String JavaDoc newName= info.getNewName();
2108                        if (info.isAdded()) {
2109                            first= false;
2110                            if (! isTopOfRipple)
2111                                continue;
2112                            TagElement paramNode= JavadocUtil.createParamTag(newName, fCuRewrite.getRoot().getAST(), fCuRewrite.getCu().getJavaProject());
2113                            insertTag(paramNode, previousTag, tagsRewrite);
2114                            previousTag= paramNode;
2115                        } else {
2116                            for (Iterator JavaDoc tagIter= paramTags.iterator(); tagIter.hasNext();) {
2117                                TagElement tag= (TagElement) tagIter.next();
2118                                SimpleName tagName= (SimpleName) tag.fragments().get(0);
2119                                if (oldName.equals(tagName.getIdentifier())) {
2120                                    tagIter.remove();
2121                                    if (first) {
2122                                        previousTag= tag;
2123                                    } else {
2124                                        TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
2125                                        getASTRewrite().remove(tag, fDescription);
2126                                        insertTag(movedTag, previousTag, tagsRewrite);
2127                                        previousTag= movedTag;
2128                                    }
2129                                }
2130                                first= false;
2131                            }
2132                        }
2133                    }
2134                    // params with bad names:
2135
for (Iterator JavaDoc iter= paramTags.iterator(); iter.hasNext();) {
2136                        TagElement tag= (TagElement) iter.next();
2137                        TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
2138                        getASTRewrite().remove(tag, fDescription);
2139                        insertTag(movedTag, previousTag, tagsRewrite);
2140                        previousTag= movedTag;
2141                    }
2142                }
2143                tags= tagsRewrite.getRewrittenList();
2144            }
2145            
2146            if (! areExceptionsSameAsInitial()) {
2147                // collect exceptionTags and remove deleted:
2148
ArrayList JavaDoc exceptionTags= new ArrayList JavaDoc(); // <TagElement>, only not deleted tags with name
2149
for (int i= 0; i < tags.size(); i++) {
2150                    TagElement tag= (TagElement) tags.get(i);
2151                    if (! TagElement.TAG_THROWS.equals(tag.getTagName()) && ! TagElement.TAG_EXCEPTION.equals(tag.getTagName()))
2152                        continue;
2153                    if (! (tag.fragments().size() > 0 && tag.fragments().get(0) instanceof Name))
2154                        continue;
2155                    boolean tagDeleted= false;
2156                    Name name= (Name) tag.fragments().get(0);
2157                    for (int j= 0; j < fExceptionInfos.size(); j++) {
2158                        ExceptionInfo info= (ExceptionInfo) fExceptionInfos.get(j);
2159                        if (info.isDeleted()) {
2160                            boolean remove= false;
2161                            final ITypeBinding nameBinding= name.resolveTypeBinding();
2162                            if (nameBinding != null) {
2163                                final ITypeBinding infoBinding= info.getTypeBinding();
2164                                if (infoBinding != null && Bindings.equals(infoBinding, nameBinding))
2165                                    remove= true;
2166                                else if (info.getType().getElementName().equals(nameBinding.getName()))
2167                                    remove= true;
2168                                if (remove) {
2169                                    getASTRewrite().remove(tag, fDescription);
2170                                    registerImportRemoveNode(tag);
2171                                    tagDeleted= true;
2172                                    break;
2173                                }
2174                            }
2175                        }
2176                    }
2177                    if (! tagDeleted)
2178                        exceptionTags.add(tag);
2179                }
2180                // reshuffle:
2181
tags= tagsRewrite.getRewrittenList();
2182                TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_THROWS);
2183                for (Iterator JavaDoc infoIter= fExceptionInfos.iterator(); infoIter.hasNext();) {
2184                    ExceptionInfo info= (ExceptionInfo) infoIter.next();
2185                    if (info.isAdded()) {
2186                        if (!isTopOfRipple)
2187                            continue;
2188                        TagElement excptNode= createExceptionTag(info.getType().getElementName());
2189                        insertTag(excptNode, previousTag, tagsRewrite);
2190                        previousTag= excptNode;
2191                    } else {
2192                        for (Iterator JavaDoc tagIter= exceptionTags.iterator(); tagIter.hasNext();) {
2193                            TagElement tag= (TagElement) tagIter.next();
2194                            Name tagName= (Name) tag.fragments().get(0);
2195                            final ITypeBinding nameBinding= tagName.resolveTypeBinding();
2196                            if (nameBinding != null) {
2197                                boolean process= false;
2198                                final ITypeBinding infoBinding= info.getTypeBinding();
2199                                if (infoBinding != null && Bindings.equals(infoBinding, nameBinding))
2200                                    process= true;
2201                                else if (info.getType().getElementName().equals(nameBinding.getName()))
2202                                    process= true;
2203                                if (process) {
2204                                    tagIter.remove();
2205                                    TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
2206                                    getASTRewrite().remove(tag, fDescription);
2207                                    insertTag(movedTag, previousTag, tagsRewrite);
2208                                    previousTag= movedTag;
2209                                }
2210                            }
2211                        }
2212                    }
2213                }
2214                // exceptions with bad names:
2215
for (Iterator JavaDoc iter= exceptionTags.iterator(); iter.hasNext();) {
2216                    TagElement tag= (TagElement) iter.next();
2217                    TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
2218                    getASTRewrite().remove(tag, fDescription);
2219                    insertTag(movedTag, previousTag, tagsRewrite);
2220                    previousTag= movedTag;
2221                }
2222            }
2223        }
2224
2225        private TagElement createReturnTag() {
2226            TagElement returnNode= getASTRewrite().getAST().newTagElement();
2227            returnNode.setTagName(TagElement.TAG_RETURN);
2228            
2229            TextElement textElement= getASTRewrite().getAST().newTextElement();
2230            String JavaDoc text= StubUtility.getTodoTaskTag(fCuRewrite.getCu().getJavaProject());
2231            if (text != null)
2232                textElement.setText(text); //TODO: use template with {@todo} ...
2233
returnNode.fragments().add(textElement);
2234            
2235            return returnNode;
2236        }
2237
2238        private TagElement createExceptionTag(String JavaDoc simpleName) {
2239            TagElement excptNode= getASTRewrite().getAST().newTagElement();
2240            excptNode.setTagName(TagElement.TAG_THROWS);
2241
2242            SimpleName nameNode= getASTRewrite().getAST().newSimpleName(simpleName);
2243            excptNode.fragments().add(nameNode);
2244
2245            TextElement textElement= getASTRewrite().getAST().newTextElement();
2246            String JavaDoc text= StubUtility.getTodoTaskTag(fCuRewrite.getCu().getJavaProject());
2247            if (text != null)
2248                textElement.setText(text); //TODO: use template with {@todo} ...
2249
excptNode.fragments().add(textElement);
2250            
2251            return excptNode;
2252        }
2253
2254        private void insertTag(TagElement tag, TagElement previousTag, ListRewrite tagsRewrite) {
2255            if (previousTag == null)
2256                tagsRewrite.insertFirst(tag, fDescription);
2257            else
2258                tagsRewrite.insertAfter(tag, previousTag, fDescription);
2259        }
2260
2261        /**
2262         * @param tags existing tags
2263         * @param tagName name of tag to add
2264         * @return the <code>TagElement<code> just before a new <code>TagElement</code> with name <code>tagName</code>,
2265         * or <code>null</code>.
2266         */

2267        private TagElement findTagElementToInsertAfter(List JavaDoc tags, String JavaDoc tagName) {
2268            List JavaDoc tagOrder= Arrays.asList(new String JavaDoc[] {
2269                    TagElement.TAG_AUTHOR,
2270                    TagElement.TAG_VERSION,
2271                    TagElement.TAG_PARAM,
2272                    TagElement.TAG_RETURN,
2273                    TagElement.TAG_THROWS,
2274                    TagElement.TAG_EXCEPTION,
2275                    TagElement.TAG_SEE,
2276                    TagElement.TAG_SINCE,
2277                    TagElement.TAG_SERIAL,
2278                    TagElement.TAG_SERIALFIELD,
2279                    TagElement.TAG_SERIALDATA,
2280                    TagElement.TAG_DEPRECATED,
2281                    TagElement.TAG_VALUE
2282            });
2283            int goalOrdinal= tagOrder.indexOf(tagName);
2284            if (goalOrdinal == -1) // unknown tag -> to end
2285
return (tags.size() == 0) ? null : (TagElement) tags.get(tags.size());
2286            for (int i= 0; i < tags.size(); i++) {
2287                int tagOrdinal= tagOrder.indexOf(((TagElement) tags.get(i)).getTagName());
2288                if (tagOrdinal >= goalOrdinal)
2289                    return (i == 0) ? null : (TagElement) tags.get(i-1);
2290            }
2291            return (tags.size() == 0) ? null : (TagElement) tags.get(tags.size()-1);
2292        }
2293
2294        //TODO: already reported as compilation error -> don't report there?
2295
private void checkIfDeletedParametersUsed() {
2296            for (Iterator JavaDoc iter= getDeletedInfos().iterator(); iter.hasNext();) {
2297                ParameterInfo info= (ParameterInfo) iter.next();
2298                SingleVariableDeclaration paramDecl= (SingleVariableDeclaration) fMethDecl.parameters().get(info.getOldIndex());
2299                TempOccurrenceAnalyzer analyzer= new TempOccurrenceAnalyzer(paramDecl, false);
2300                analyzer.perform();
2301                SimpleName[] paramRefs= analyzer.getReferenceNodes();
2302
2303                if (paramRefs.length > 0){
2304                    RefactoringStatusContext context= JavaStatusContext.create(fCuRewrite.getCu(), paramRefs[0]);
2305                    String JavaDoc typeName= getFullTypeName(fMethDecl);
2306                    Object JavaDoc[] keys= new String JavaDoc[]{paramDecl.getName().getIdentifier(),
2307                                                fMethDecl.getName().getIdentifier(),
2308                                                typeName};
2309                    String JavaDoc msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_parameter_used, keys);
2310                    fResult.addError(msg, context);
2311                }
2312            }
2313        }
2314        
2315        private String JavaDoc getFullTypeName(MethodDeclaration decl) {
2316            ASTNode node= decl;
2317            while (true) {
2318                node= node.getParent();
2319                if (node instanceof AbstractTypeDeclaration) {
2320                    return ((AbstractTypeDeclaration) node).getName().getIdentifier();
2321                } else if (node instanceof ClassInstanceCreation) {
2322                    ClassInstanceCreation cic= (ClassInstanceCreation) node;
2323                    return Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_anonymous_subclass, new String JavaDoc[]{ASTNodes.asString(cic.getType())});
2324                } else if (node instanceof EnumConstantDeclaration) {
2325                    EnumDeclaration ed= (EnumDeclaration) node.getParent();
2326                    return Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_anonymous_subclass, new String JavaDoc[]{ASTNodes.asString(ed.getName())});
2327                }
2328            }
2329        }
2330        
2331        protected ASTNode createNewParamgument(ParameterInfo info, List JavaDoc parameterInfos, List JavaDoc nodes) {
2332            return createNewSingleVariableDeclaration(info);
2333        }
2334    
2335        private SingleVariableDeclaration createNewSingleVariableDeclaration(ParameterInfo info) {
2336            SingleVariableDeclaration newP= getASTRewrite().getAST().newSingleVariableDeclaration();
2337            newP.setName(getASTRewrite().getAST().newSimpleName(info.getNewName()));
2338            newP.setType(createNewTypeNode(ParameterInfo.stripEllipsis(info.getNewTypeName()), info.getNewTypeBinding()));
2339            newP.setVarargs(info.isNewVarargs());
2340            return newP;
2341        }
2342        
2343        protected SimpleName getMethodNameNode() {
2344            return fMethDecl.getName();
2345        }
2346    
2347    }
2348
2349    class DocReferenceUpdate extends OccurrenceUpdate {
2350        /** instanceof MemberRef || MethodRef */
2351        private ASTNode fNode;
2352
2353        protected DocReferenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
2354            super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_update_javadoc_reference), result);
2355            fNode= node;
2356        }
2357
2358        public void updateNode() {
2359            if (fNode instanceof MethodRef) {
2360                changeParamguments();
2361                reshuffleElements();
2362            }
2363            if (canChangeNameAndReturnType())
2364                changeMethodName();
2365        }
2366        
2367        protected ASTNode createNewParamgument(ParameterInfo info, List JavaDoc parameterInfos, List JavaDoc nodes) {
2368            return createNewMethodRefParameter(info);
2369        }
2370        
2371        private MethodRefParameter createNewMethodRefParameter(ParameterInfo info) {
2372            MethodRefParameter newP= getASTRewrite().getAST().newMethodRefParameter();
2373            
2374            // only add name iff first parameter already has a name:
2375
List JavaDoc parameters= getParamgumentsRewrite().getOriginalList();
2376            if (parameters.size() > 0)
2377                if (((MethodRefParameter) parameters.get(0)).getName() != null)
2378                    newP.setName(getASTRewrite().getAST().newSimpleName(info.getNewName()));
2379            
2380            newP.setType(createNewDocRefType(info));
2381            newP.setVarargs(info.isNewVarargs());
2382            return newP;
2383        }
2384
2385        private Type createNewDocRefType(ParameterInfo info) {
2386            String JavaDoc newTypeName= ParameterInfo.stripEllipsis(info.getNewTypeName());
2387            ITypeBinding newTypeBinding= info.getNewTypeBinding();
2388            if (newTypeBinding != null)
2389                newTypeBinding= newTypeBinding.getErasure(); //see bug 83127: Javadoc references are raw (erasures)
2390
return createNewTypeNode(newTypeName, newTypeBinding);
2391        }
2392
2393        protected SimpleName getMethodNameNode() {
2394            if (fNode instanceof MemberRef)
2395                return ((MemberRef) fNode).getName();
2396            
2397            if (fNode instanceof MethodRef)
2398                return ((MethodRef) fNode).getName();
2399            
2400            return null;
2401        }
2402        
2403        /** @return {@inheritDoc} (element type: MethodRefParameter) */
2404        protected ListRewrite getParamgumentsRewrite() {
2405            return getASTRewrite().getListRewrite(fNode, MethodRef.PARAMETERS_PROPERTY);
2406        }
2407
2408        protected void changeParamgumentName(ParameterInfo info) {
2409            if (! (fNode instanceof MethodRef))
2410                return;
2411
2412            MethodRefParameter oldParam= (MethodRefParameter) ((MethodRef) fNode).parameters().get(info.getOldIndex());
2413            SimpleName oldParamName= oldParam.getName();
2414            if (oldParamName != null)
2415                getASTRewrite().set(oldParamName, SimpleName.IDENTIFIER_PROPERTY, info.getNewName(), fDescription);
2416        }
2417        
2418        protected void changeParamgumentType(ParameterInfo info) {
2419            if (! (fNode instanceof MethodRef))
2420                return;
2421            
2422            MethodRefParameter oldParam= (MethodRefParameter) ((MethodRef) fNode).parameters().get(info.getOldIndex());
2423            Type oldTypeNode= oldParam.getType();
2424            Type newTypeNode= createNewDocRefType(info);
2425            if (info.isNewVarargs()) {
2426                if (info.isOldVarargs() && ! oldParam.isVarargs()) {
2427                    // leave as array reference of old reference was not vararg
2428
newTypeNode= getASTRewrite().getAST().newArrayType(newTypeNode);
2429                } else {
2430                    getASTRewrite().set(oldParam, MethodRefParameter.VARARGS_PROPERTY, Boolean.TRUE, fDescription);
2431                }
2432            } else {
2433                if (oldParam.isVarargs()) {
2434                    getASTRewrite().set(oldParam, MethodRefParameter.VARARGS_PROPERTY, Boolean.FALSE, fDescription);
2435                }
2436            }
2437            
2438            getASTRewrite().replace(oldTypeNode, newTypeNode, fDescription);
2439            registerImportRemoveNode(oldTypeNode);
2440        }
2441    }
2442    
2443    class StaticImportUpdate extends OccurrenceUpdate {
2444
2445        private final ImportDeclaration fImportDecl;
2446
2447        public StaticImportUpdate(ImportDeclaration importDecl, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
2448            super(cuRewrite, null, result);
2449            fImportDecl= importDecl;
2450        }
2451
2452        public void updateNode() throws JavaModelException {
2453            ImportRewrite importRewrite= fCuRewrite.getImportRewrite();
2454            QualifiedName name= (QualifiedName) fImportDecl.getName();
2455            //will be removed by importRemover if not used elsewhere ... importRewrite.removeStaticImport(name.getFullyQualifiedName());
2456
importRewrite.addStaticImport(name.getQualifier().getFullyQualifiedName(), fMethodName, false);
2457        }
2458
2459        protected ListRewrite getParamgumentsRewrite() {
2460            return null;
2461        }
2462
2463        protected ASTNode createNewParamgument(ParameterInfo info, List JavaDoc parameterInfos, List JavaDoc nodes) {
2464            return null;
2465        }
2466
2467        protected SimpleName getMethodNameNode() {
2468            return null;
2469        }
2470    }
2471    
2472    class NullOccurrenceUpdate extends OccurrenceUpdate {
2473        private ASTNode fNode;
2474        protected NullOccurrenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
2475            super(cuRewrite, null, result);
2476            fNode= node;
2477        }
2478        public void updateNode() throws JavaModelException {
2479            int start= fNode.getStartPosition();
2480            int length= fNode.getLength();
2481            String JavaDoc msg= "Cannot update found node: nodeType=" + fNode.getNodeType() + "; " //$NON-NLS-1$//$NON-NLS-2$
2482
+ fNode.toString() + "[" + start + ", " + length + "] in " + fCuRewrite.getCu(); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
2483
JavaPlugin.log(new Exception JavaDoc(msg + ":\n" + fCuRewrite.getCu().getSource().substring(start, start + length))); //$NON-NLS-1$
2484
fResult.addError(msg, JavaStatusContext.create(fCuRewrite.getCu(), fNode));
2485        }
2486        protected ListRewrite getParamgumentsRewrite() {
2487            return null;
2488        }
2489        protected ASTNode createNewParamgument(ParameterInfo info, List JavaDoc parameterInfos, List JavaDoc nodes) {
2490            return null;
2491        }
2492        protected SimpleName getMethodNameNode() {
2493            return null;
2494        }
2495    }
2496
2497    public RefactoringStatus initialize(final RefactoringArguments arguments) {
2498        if (arguments instanceof JavaRefactoringArguments) {
2499            final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
2500            final String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
2501            if (handle != null) {
2502                final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
2503                if (element == null || !element.exists() || element.getElementType() != IJavaElement.METHOD)
2504                    return createInputFatalStatus(element, IJavaRefactorings.CHANGE_METHOD_SIGNATURE);
2505                else {
2506                    fMethod= (IMethod) element;
2507                    fMethodName= fMethod.getElementName();
2508                    try {
2509                        fVisibility= JdtFlags.getVisibilityCode(fMethod);
2510                        fReturnTypeInfo= new ReturnTypeInfo(Signature.toString(Signature.getReturnType(fMethod.getSignature())));
2511                    } catch (JavaModelException exception) {
2512                        return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, ATTRIBUTE_VISIBILITY));
2513                    }
2514                }
2515            } else
2516                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
2517            final String JavaDoc name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME);
2518            if (name != null) {
2519                fMethodName= name;
2520                final RefactoringStatus status= Checks.checkMethodName(fMethodName);
2521                if (status.hasError())
2522                    return status;
2523            } else
2524                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME));
2525            final String JavaDoc type= extended.getAttribute(ATTRIBUTE_RETURN);
2526            if (type != null && !"".equals(type)) //$NON-NLS-1$
2527
fReturnTypeInfo= new ReturnTypeInfo(type);
2528            final String JavaDoc visibility= extended.getAttribute(ATTRIBUTE_VISIBILITY);
2529            if (visibility != null && !"".equals(visibility)) {//$NON-NLS-1$
2530
int flag= 0;
2531                try {
2532                    flag= Integer.parseInt(visibility);
2533                } catch (NumberFormatException JavaDoc exception) {
2534                    return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_VISIBILITY));
2535                }
2536                fVisibility= flag;
2537            }
2538            int count= 1;
2539            String JavaDoc attribute= ATTRIBUTE_PARAMETER + count;
2540            String JavaDoc value= null;
2541            fParameterInfos= new ArrayList JavaDoc(3);
2542            while ((value= extended.getAttribute(attribute)) != null) {
2543                StringTokenizer JavaDoc tokenizer= new StringTokenizer JavaDoc(value);
2544                if (tokenizer.countTokens() < 6)
2545                    return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, ATTRIBUTE_PARAMETER));
2546                String JavaDoc oldTypeName= tokenizer.nextToken();
2547                String JavaDoc oldName= tokenizer.nextToken();
2548                String JavaDoc oldIndex= tokenizer.nextToken();
2549                String JavaDoc newTypeName= tokenizer.nextToken();
2550                String JavaDoc newName= tokenizer.nextToken();
2551                String JavaDoc deleted= tokenizer.nextToken();
2552                ParameterInfo info= null;
2553                try {
2554                    info= new ParameterInfo(oldTypeName, oldName, Integer.valueOf(oldIndex).intValue());
2555                    info.setNewTypeName(newTypeName);
2556                    info.setNewName(newName);
2557                    if (Boolean.valueOf(deleted).booleanValue())
2558                        info.markAsDeleted();
2559                    fParameterInfos.add(info);
2560                } catch (NumberFormatException JavaDoc exception) {
2561                    return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, ATTRIBUTE_PARAMETER));
2562                }
2563                final String JavaDoc result= extended.getAttribute(ATTRIBUTE_DEFAULT + count);
2564                if (result != null && !"".equals(result)) //$NON-NLS-1$
2565
info.setDefaultValue(result);
2566                count++;
2567                attribute= ATTRIBUTE_PARAMETER + count;
2568            }
2569            count= 1;
2570            fExceptionInfos= new ArrayList JavaDoc(2);
2571            attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count;
2572            while ((value= extended.getAttribute(attribute)) != null) {
2573                ExceptionInfo info= null;
2574                final String JavaDoc kind= extended.getAttribute(ATTRIBUTE_KIND + count);
2575                if (kind != null) {
2576                    final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), value, false);
2577                    if (element == null || !element.exists())
2578                        return createInputFatalStatus(element, IJavaRefactorings.CHANGE_METHOD_SIGNATURE);
2579                    else {
2580                        try {
2581                            info= new ExceptionInfo((IType) element, Integer.valueOf(kind).intValue(), null);
2582                        } catch (NumberFormatException JavaDoc exception) {
2583                            return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, ATTRIBUTE_KIND));
2584                        }
2585                    }
2586                } else
2587                    return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, ATTRIBUTE_KIND));
2588                fExceptionInfos.add(info);
2589                count++;
2590                attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count;
2591            }
2592            final String JavaDoc deprecate= extended.getAttribute(ATTRIBUTE_DEPRECATE);
2593            if (deprecate != null) {
2594                fDelegateDeprecation= Boolean.valueOf(deprecate).booleanValue();
2595            } else
2596                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DEPRECATE));
2597            final String JavaDoc delegate= extended.getAttribute(ATTRIBUTE_DELEGATE);
2598            if (delegate != null) {
2599                fDelegateUpdating= Boolean.valueOf(delegate).booleanValue();
2600            } else
2601                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELEGATE));
2602        } else
2603            return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
2604        return new RefactoringStatus();
2605    }
2606
2607    /**
2608     * If this occurrence update is called from within a declaration update
2609     * (i.e., to update the call inside the newly created delegate), the old
2610     * node does not yet exist and therefore cannot be a move target.
2611     *
2612     * Normally, always use createMoveTarget as this has the advantage of
2613     * being able to add changes inside changed nodes (for example, a method
2614     * call within a method call, see test case #4) and preserving comments
2615     * inside calls.
2616     * @param oldNode original node
2617     * @param rewrite an AST rewrite
2618     * @return the node to insert at the target location
2619     */

2620    protected ASTNode moveNode(ASTNode oldNode, ASTRewrite rewrite) {
2621        ASTNode movedNode;
2622        if (ASTNodes.isExistingNode(oldNode))
2623            movedNode= rewrite.createMoveTarget(oldNode); //node must be one of ast
2624
else
2625            movedNode= ASTNode.copySubtree(rewrite.getAST(), oldNode);
2626        return movedNode;
2627    }
2628    
2629    public String JavaDoc getDelegateUpdatingTitle(boolean plural) {
2630        if (plural)
2631            return RefactoringCoreMessages.DelegateCreator_keep_original_changed_plural;
2632        else
2633            return RefactoringCoreMessages.DelegateCreator_keep_original_changed_singular;
2634    }
2635
2636    public IDefaultValueAdvisor getDefaultValueAdvisor() {
2637        return fDefaultValueAdvisor;
2638    }
2639
2640    public void setDefaultValueAdvisor(IDefaultValueAdvisor defaultValueAdvisor) {
2641        fDefaultValueAdvisor= defaultValueAdvisor;
2642    }
2643}
2644
Popular Tags