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