KickJava   Java API By Example, From Geeks To Geeks.

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


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.Collection JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Iterator 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.MultiTextEdit;
25 import org.eclipse.text.edits.TextEditGroup;
26
27 import org.eclipse.core.runtime.Assert;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.NullProgressMonitor;
31 import org.eclipse.core.runtime.OperationCanceledException;
32 import org.eclipse.core.runtime.SubProgressMonitor;
33
34 import org.eclipse.ltk.core.refactoring.Change;
35 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
36 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
37 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
38
39 import org.eclipse.jdt.core.ICompilationUnit;
40 import org.eclipse.jdt.core.IField;
41 import org.eclipse.jdt.core.IJavaElement;
42 import org.eclipse.jdt.core.IJavaProject;
43 import org.eclipse.jdt.core.IMethod;
44 import org.eclipse.jdt.core.JavaModelException;
45 import org.eclipse.jdt.core.dom.AST;
46 import org.eclipse.jdt.core.dom.ASTNode;
47 import org.eclipse.jdt.core.dom.CompilationUnit;
48 import org.eclipse.jdt.core.dom.Expression;
49 import org.eclipse.jdt.core.dom.FieldDeclaration;
50 import org.eclipse.jdt.core.dom.IBinding;
51 import org.eclipse.jdt.core.dom.IMethodBinding;
52 import org.eclipse.jdt.core.dom.ITypeBinding;
53 import org.eclipse.jdt.core.dom.IVariableBinding;
54 import org.eclipse.jdt.core.dom.MethodDeclaration;
55 import org.eclipse.jdt.core.dom.ParameterizedType;
56 import org.eclipse.jdt.core.dom.QualifiedName;
57 import org.eclipse.jdt.core.dom.SimpleName;
58 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
59 import org.eclipse.jdt.core.dom.Type;
60 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
61 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
62 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
63 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
64 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
65 import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
66 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
67 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
68 import org.eclipse.jdt.core.search.IJavaSearchConstants;
69 import org.eclipse.jdt.core.search.IJavaSearchScope;
70 import org.eclipse.jdt.core.search.SearchPattern;
71
72 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
73 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
74 import org.eclipse.jdt.internal.corext.dom.Bindings;
75 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
76 import org.eclipse.jdt.internal.corext.refactoring.Checks;
77 import org.eclipse.jdt.internal.corext.refactoring.CollectingSearchRequestor;
78 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
79 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
80 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
81 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
82 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
83 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine;
84 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
85 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
86 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
87 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
88 import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks;
89 import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2;
90 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ASTCreator;
91 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompositeOrTypeConstraint;
92 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintCollector;
93 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintOperator;
94 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintVariable;
95 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintVariableFactory;
96 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ExpressionVariable;
97 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.FullConstraintCreator;
98 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ITypeConstraint;
99 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ParameterTypeVariable;
100 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ReturnTypeVariable;
101 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.SimpleTypeConstraint;
102 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.TypeConstraintFactory;
103 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.TypeVariable;
104 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
105 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
106 import org.eclipse.jdt.internal.corext.util.Messages;
107 import org.eclipse.jdt.internal.corext.util.SearchUtils;
108
109 import org.eclipse.jdt.ui.JavaElementLabels;
110
111 import org.eclipse.jdt.internal.ui.JavaPlugin;
112 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
113
114 /**
115  * @author tip
116  */

117 public class ChangeTypeRefactoring extends ScriptableRefactoring {
118
119     private static final String JavaDoc ATTRIBUTE_TYPE= "type"; //$NON-NLS-1$
120

121     private final Map JavaDoc/*<ICompilationUnit, Collection<ITypeConstraint>>*/ fConstraintCache;
122     /**
123      * Offset of the selected text area.
124      */

125     private int fSelectionStart;
126
127     /**
128      * Length of the selected text area.
129      */

130     private int fSelectionLength;
131     
132     /**
133      * Offset of the effective selection
134      */

135     private int fEffectiveSelectionStart;
136     
137     /**
138      * Length of the effective selection
139      */

140     private int fEffectiveSelectionLength;
141     
142     /**
143      * ICompilationUnit containing the selection.
144      */

145     private ICompilationUnit fCu;
146     
147     /**
148      * If the selection corresponds to a method parameter/return type, this field stores
149      * a reference to its IMethodBinding, otherwise this field remains null. Used during
150      * search for references in other CUs, and for determining the ConstraintVariable
151      * that corresponds to the selection
152      */

153     private IMethodBinding fMethodBinding;
154     
155     /**
156      * If the selection corresponds to a method parameter, this field stores the parameter
157      * index (0 = first parameter for static methods, 0 = this for nonstatic methods). The
158      * value -1 is stored in the field if the selection corresponds to a method return type.
159      */

160     private int fParamIndex;
161     
162     /**
163      * The name of the selected parameter, or <code>null</code>.
164      */

165     private String JavaDoc fParamName;
166     
167     /**
168      * If the selection corresponds to a field, this field stores a reference to its IVariableBinding,
169      * otherwise this field remains null. Used during search for references in other CUs.
170      */

171     private IVariableBinding fFieldBinding;
172
173     /**
174      * The compilation units that contain constraint variables related to the selection
175      */

176     private ICompilationUnit[] fAffectedUnits;
177
178     /**
179      * The constraint variables that are of interest to this refactoring. This includes
180      * the constraint var. corresponding to the text selection, and possibly additional
181      * elements due to method overriding, method calls, etc.
182      */

183     private Collection JavaDoc/*<ConstraintVariable>*/ fRelevantVars;
184
185     /**
186      * The set of types (other than the original type) that can be given to
187      * the selected ASTNode.
188      */

189     private final Collection JavaDoc/*<IType>*/ fValidTypes;
190     
191     /**
192      * The type constraints that are related to the selected ASTNode.
193      */

194     private Collection JavaDoc/*<ITypeConstraint>*/ fRelevantConstraints;
195
196     /**
197      * All type constraints in affected compilation units.
198      */

199     private Collection JavaDoc/*<ITypeConstraint>*/ fAllConstraints;
200
201     /**
202      * The name of the new type of the selected declaration.
203      */

204     private String JavaDoc fSelectedTypeName;
205     
206     /**
207      * The new type of the selected declaration.
208      */

209     private ITypeBinding fSelectedType;
210     
211     /**
212      * Organizes SearchResults by CompilationUnit
213      */

214     private Map JavaDoc/*<ICompilationUnit,SearchResultGroup>*/ fCuToSearchResultGroup= new HashMap JavaDoc();
215     
216     
217     /**
218      * ITypeBinding for java.lang.Object
219      */

220     private ITypeBinding fObject;
221
222     public ITypeBinding getObject(){
223         return fObject;
224     }
225     
226     /**
227      * Control debugging output.
228      */

229     private static final boolean DEBUG= false;
230
231     private ConstraintVariable fCv;
232     private IBinding fSelectionBinding;
233     private ITypeBinding fSelectionTypeBinding;
234     private ConstraintCollector fCollector;
235
236     public ChangeTypeRefactoring(ICompilationUnit cu, int selectionStart, int selectionLength) {
237         this(cu, selectionStart, selectionLength, null);
238     }
239
240     /**
241      * Constructor for ChangeTypeRefactoring (invoked from tests only)
242      */

243     public ChangeTypeRefactoring(ICompilationUnit cu, int selectionStart, int selectionLength, String JavaDoc selectedType) {
244         Assert.isTrue(selectionStart >= 0);
245         Assert.isTrue(selectionLength >= 0);
246
247         fSelectionStart= selectionStart;
248         fSelectionLength= selectionLength;
249
250         fEffectiveSelectionStart= selectionStart;
251         fEffectiveSelectionLength= selectionLength;
252         
253         fCu= cu;
254
255         if (selectedType != null)
256             fSelectedTypeName= selectedType;
257         
258         fConstraintCache= new HashMap JavaDoc();
259         fValidTypes= new HashSet JavaDoc();
260     }
261
262     // ------------------------------------------------------------------------------------------------- //
263

264     /*
265      * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkActivation(org.eclipse.core.runtime.IProgressMonitor)
266      */

267     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
268         if (fCu == null || !fCu.isStructureKnown())
269             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_invalidSelection);
270         return checkSelection(new SubProgressMonitor(pm, 1));
271     }
272
273     private void setSelectionRanges(Expression exp){
274         fEffectiveSelectionStart= exp.getStartPosition();
275         fEffectiveSelectionLength= exp.getLength();
276         fSelectionBinding= ExpressionVariable.resolveBinding(exp);
277         setOriginalType(exp.resolveTypeBinding());
278     }
279     
280     /**
281      * Check if the right type of AST Node is selected. Create the TypeHierarchy needed to
282      * bring up the wizard.
283      */

284     private RefactoringStatus checkSelection(IProgressMonitor pm) throws JavaModelException {
285         try {
286             pm.beginTask("", 5); //$NON-NLS-1$
287

288             ASTNode node= getTargetNode(fCu, fSelectionStart, fSelectionLength);
289             if (DEBUG) {
290                 System.out.println(
291                     "selection: [" //$NON-NLS-1$
292
+ fSelectionStart
293                         + "," //$NON-NLS-1$
294
+ (fSelectionStart + fSelectionLength)
295                         + "] in " //$NON-NLS-1$
296
+ fCu.getElementName());
297                 System.out.println("node= " + node + ", type= " + node.getClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
298
}
299
300             TypeConstraintFactory typeConstraintFactory = new TypeConstraintFactory(){
301                 public boolean filter(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator o){
302                     if (o.isStrictSubtypeOperator()) //TODO: explain why these can be excluded
303
return true;
304                     //Don't create constraint if fSelectionTypeBinding is not involved:
305
if (v1.getBinding() != null && v2.getBinding() != null
306                             && ! Bindings.equals(v1.getBinding(), fSelectionTypeBinding)
307                             && ! Bindings.equals(v2.getBinding(), fSelectionTypeBinding)) {
308                         if (PRINT_STATS) fNrFiltered++;
309                         return true;
310                     }
311                     return super.filter(v1, v2, o);
312                 }
313             };
314             fCollector= new ConstraintCollector(new FullConstraintCreator(new ConstraintVariableFactory(), typeConstraintFactory));
315             String JavaDoc selectionValid= determineSelection(node);
316             if (selectionValid != null){
317                 if (DEBUG){
318                     System.out.println("invalid selection: " + selectionValid); //$NON-NLS-1$
319
}
320                 return RefactoringStatus.createFatalErrorStatus(selectionValid);
321             }
322             
323             if (fMethodBinding != null) {
324                 IMethod selectedMethod= (IMethod) fMethodBinding.getJavaElement();
325                 if (selectedMethod == null){
326                     return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_insideLocalTypesNotSupported);
327                 }
328             }
329
330             pm.worked(1);
331
332             RefactoringStatus result= new RefactoringStatus();
333             
334             if (DEBUG){
335                 System.out.println("fSelectionTypeBinding: " + fSelectionTypeBinding.getName()); //$NON-NLS-1$
336
}
337             
338             // produce error message if array or primitive type is selected
339
if (fSelectionTypeBinding.isArray()){
340                 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_arraysNotSupported);
341             }
342             if (fSelectionTypeBinding.isPrimitive()){
343                 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_primitivesNotSupported);
344             }
345             if (checkOverriddenBinaryMethods())
346                 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnBinary);
347             
348             if (fSelectionTypeBinding.isLocal()){
349                 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_localTypesNotSupported);
350             }
351             
352             if (fFieldBinding != null && fFieldBinding.getDeclaringClass().isLocal()){
353                 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_insideLocalTypesNotSupported);
354             }
355             
356             if (fSelectionTypeBinding.isTypeVariable()){
357                 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_typeParametersNotSupported);
358             }
359             
360             if (fSelectionTypeBinding.isEnum()){
361                 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_enumsNotSupported);
362             }
363             
364             pm.worked(1);
365
366             if (fSelectedType != null){ // if invoked from unit test, compute valid types here
367
computeValidTypes(new NullProgressMonitor());
368             }
369             return result;
370         } finally {
371             pm.done();
372         }
373     }
374     
375     private boolean checkOverriddenBinaryMethods() throws JavaModelException {
376         if (fMethodBinding != null){
377             Set JavaDoc declaringSupertypes= getDeclaringSuperTypes(fMethodBinding);
378             for (Iterator JavaDoc iter= declaringSupertypes.iterator(); iter.hasNext();) {
379                 ITypeBinding superType= (ITypeBinding) iter.next();
380                 IMethodBinding overriddenMethod= findMethod(fMethodBinding, superType);
381                 Assert.isNotNull(overriddenMethod);//because we asked for declaring types
382
IMethod iMethod= (IMethod) overriddenMethod.getJavaElement();
383                 if (iMethod.isBinary()){
384                     return true;
385                 }
386             }
387         }
388         return false;
389     }
390     
391     // copied from FullConstraintCreator
392
private static IMethodBinding findMethod(IMethodBinding methodBinding, ITypeBinding type) {
393           if (methodBinding.getDeclaringClass().equals(type))
394               return methodBinding;
395           return Bindings.findOverriddenMethodInType(type, methodBinding);
396     }
397
398     // copied from FullConstraintCreator
399
private static Set JavaDoc getDeclaringSuperTypes(IMethodBinding methodBinding) {
400         ITypeBinding[] allSuperTypes= Bindings.getAllSuperTypes(methodBinding.getDeclaringClass());
401         Set JavaDoc result= new HashSet JavaDoc();
402         for (int i= 0; i < allSuperTypes.length; i++) {
403             ITypeBinding type= allSuperTypes[i];
404             if (findMethod(methodBinding, type) != null)
405                 result.add(type);
406         }
407         return result;
408     }
409     
410     /**
411      * Do the actual work of computing allowable types. Invoked by the wizard when
412      * "compute" button is pressed
413      */

414     public Collection JavaDoc/*<IType>*/ computeValidTypes(IProgressMonitor pm) {
415         
416         pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_checking_preconditions, 100);
417
418         try {
419             fCv= findConstraintVariableForSelectedNode(new SubProgressMonitor(pm, 3));
420             if (DEBUG) System.out.println("selected CV: " + fCv + //$NON-NLS-1$
421
" (" + fCv.getClass().getName() + //$NON-NLS-1$
422
")"); //$NON-NLS-1$
423

424             if (pm.isCanceled())
425                 throw new OperationCanceledException();
426             fRelevantVars= findRelevantConstraintVars(fCv, new SubProgressMonitor(pm, 50));
427             
428             if (DEBUG)
429                 printCollection("relevant vars:", fRelevantVars); //$NON-NLS-1$
430

431             if (pm.isCanceled())
432                 throw new OperationCanceledException();
433             fRelevantConstraints= findRelevantConstraints(fRelevantVars, new SubProgressMonitor(pm, 30));
434         
435             if (pm.isCanceled())
436                 throw new OperationCanceledException();
437             fValidTypes.addAll(computeValidTypes(fSelectionTypeBinding, fRelevantVars,
438                                                  fRelevantConstraints, new SubProgressMonitor(pm, 20)));
439     
440             if (DEBUG)
441                 printCollection("valid types:", getValidTypeNames()); //$NON-NLS-1$
442
} catch (CoreException e) {
443             JavaPlugin.logErrorMessage("Error occurred during computation of valid types: " + e.toString()); //$NON-NLS-1$
444
fValidTypes.clear(); // error occurred during computation of valid types
445
}
446         
447         pm.done();
448         
449         return fValidTypes;
450     }
451     
452     
453     /*
454      * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkInput(org.eclipse.core.runtime.IProgressMonitor)
455      */

456     public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
457         pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_checking_preconditions, 1);
458             
459         RefactoringStatus result= Checks.validateModifiesFiles(
460             ResourceUtil.getFiles(fAffectedUnits), getValidationContext());
461         
462         pm.done();
463         return result;
464     }
465 // TODO: do sanity check somewhere if the refactoring changes any files.
466
/*
467      * @see org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring#createChange(org.eclipse.core.runtime.IProgressMonitor)
468      */

469     public Change createChange(IProgressMonitor pm) throws CoreException {
470         pm.beginTask(RefactoringCoreMessages.ChangeTypeMessages_CreateChangesForChangeType, 1);
471         try {
472             Map JavaDoc/* <ICompilationUnit,Set<ConstraintVariable>> */relevantVarsByUnit= new HashMap JavaDoc/* <ICompilationUnit,HashSet<ConstraintVariable>> */();
473             groupChangesByCompilationUnit(relevantVarsByUnit);
474             final Map JavaDoc arguments= new HashMap JavaDoc();
475             String JavaDoc project= null;
476             IJavaProject javaProject= fCu.getJavaProject();
477             if (javaProject != null)
478                 project= javaProject.getElementName();
479             final String JavaDoc description= RefactoringCoreMessages.ChangeTypeRefactoring_descriptor_description_short;
480             final String JavaDoc header= Messages.format(RefactoringCoreMessages.ChangeTypeRefactoring_descriptor_description, new String JavaDoc[] { BindingLabelProvider.getBindingLabel(fSelectionBinding, JavaElementLabels.ALL_FULLY_QUALIFIED), BindingLabelProvider.getBindingLabel(fSelectedType, JavaElementLabels.ALL_FULLY_QUALIFIED)});
481             final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
482             comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeTypeRefactoring_original_element_pattern, BindingLabelProvider.getBindingLabel(fSelectionBinding, JavaElementLabels.ALL_FULLY_QUALIFIED)));
483             comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeTypeRefactoring_original_type_pattern, BindingLabelProvider.getBindingLabel(getOriginalType(), JavaElementLabels.ALL_FULLY_QUALIFIED)));
484             comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeTypeRefactoring_refactored_type_pattern, BindingLabelProvider.getBindingLabel(fSelectedType, JavaElementLabels.ALL_FULLY_QUALIFIED)));
485             final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.GENERALIZE_TYPE, project, description, comment.asString(), arguments, (RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT));
486             arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fCu));
487             arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION, new Integer JavaDoc(fSelectionStart).toString() + " " + new Integer JavaDoc(fSelectionLength).toString()); //$NON-NLS-1$
488
arguments.put(ATTRIBUTE_TYPE, fSelectedType.getQualifiedName());
489             final DynamicValidationRefactoringChange result= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.ChangeTypeRefactoring_allChanges);
490             for (Iterator JavaDoc/* <ICompilationUnit> */it= relevantVarsByUnit.keySet().iterator(); it.hasNext();) {
491                 ICompilationUnit icu= (ICompilationUnit) it.next();
492                 Set JavaDoc/* <ConstraintVariable> */cVars= (Set JavaDoc) relevantVarsByUnit.get(icu);
493                 CompilationUnitChange cuChange= new CompilationUnitChange(getName(), icu);
494                 addAllChangesFor(icu, cVars, cuChange);
495                 result.add(cuChange);
496                 pm.worked(1);
497                 if (pm.isCanceled())
498                     throw new OperationCanceledException();
499             }
500             return result;
501         } finally {
502             pm.done();
503         }
504     }
505
506     /**
507      * Apply all changes related to a single ICompilationUnit
508      */

509     private void addAllChangesFor(ICompilationUnit icu, Set JavaDoc vars, CompilationUnitChange unitChange) throws CoreException {
510         CompilationUnit unit= new RefactoringASTParser(AST.JLS3).parse(icu, false);
511         ASTRewrite unitRewriter= ASTRewrite.create(unit.getAST());
512         MultiTextEdit root= new MultiTextEdit();
513         unitChange.setEdit(root); // Adam sez don't need this, but then unitChange.addGroupDescription() fails an assertion!
514

515         String JavaDoc typeName= updateImports(unit, root);
516         updateCu(unit, vars, unitChange, unitRewriter, typeName);
517         root.addChild(unitRewriter.rewriteAST());
518     }
519
520     private class SourceRangeComputer extends TargetSourceRangeComputer {
521         public SourceRange computeSourceRange(ASTNode node) {
522             return new SourceRange(node.getStartPosition(),node.getLength());
523         }
524     }
525     
526     private void updateCu(CompilationUnit unit, Set JavaDoc vars, CompilationUnitChange unitChange,
527         ASTRewrite unitRewriter, String JavaDoc typeName) throws JavaModelException {
528         
529         // use custom SourceRangeComputer to avoid losing comments
530
unitRewriter.setTargetSourceRangeComputer(new SourceRangeComputer());
531         
532         for (Iterator JavaDoc it=vars.iterator(); it.hasNext(); ){
533             ConstraintVariable cv = (ConstraintVariable)it.next();
534             ASTNode decl= findDeclaration(unit, cv);
535             if ((decl instanceof SimpleName || decl instanceof QualifiedName) && cv instanceof ExpressionVariable) {
536                 ASTNode gp= decl.getParent().getParent();
537                 updateType(unit, getType(gp), unitChange, unitRewriter, typeName); // local variable or parameter
538
} else if (decl instanceof MethodDeclaration || decl instanceof FieldDeclaration) {
539                 updateType(unit, getType(decl), unitChange, unitRewriter, typeName); // method return or field type
540
} else if (decl instanceof ParameterizedType){
541                 updateType(unit, getType(decl), unitChange, unitRewriter, typeName);
542             }
543         }
544     }
545
546     private void updateType(CompilationUnit cu, Type oldType, CompilationUnitChange unitChange,
547                             ASTRewrite unitRewriter, String JavaDoc typeName) {
548         
549         String JavaDoc oldName= fSelectionTypeBinding.getName();
550         String JavaDoc description= Messages.format(RefactoringCoreMessages.ChangeTypeRefactoring_typeChange, new String JavaDoc[] {oldName, typeName});
551         TextEditGroup gd= new TextEditGroup(description);
552         AST ast= cu.getAST();
553         
554         ASTNode nodeToReplace= oldType;
555         if (fSelectionTypeBinding.isParameterizedType() && !fSelectionTypeBinding.isRawType()){
556             if (oldType.isSimpleType()){
557                 nodeToReplace= oldType.getParent();
558             }
559         }
560                                                                
561         //TODO handle types other than simple & parameterized (e.g., arrays)
562
Assert.isTrue(fSelectedType.isClass() || fSelectedType.isInterface());
563         
564         Type newType= null;
565         if (!fSelectedType.isParameterizedType()){
566             newType= ast.newSimpleType(ASTNodeFactory.newName(ast, typeName));
567         } else {
568             newType= createParameterizedType(ast, fSelectedType);
569         }
570         
571         unitRewriter.replace(nodeToReplace, newType, gd);
572         unitChange.addTextEditGroup(gd);
573     }
574     
575     /**
576      * Creates the appropriate ParameterizedType node. Recursion is needed to
577      * handle the nested case (e.g., Vector<Vector<String>>).
578      */

579     private Type createParameterizedType(AST ast, ITypeBinding typeBinding){
580         if (typeBinding.isParameterizedType() && !typeBinding.isRawType()){
581             Type baseType= ast.newSimpleType(ASTNodeFactory.newName(ast, typeBinding.getErasure().getName()));
582             ParameterizedType newType= ast.newParameterizedType(baseType);
583             for (int i=0; i < typeBinding.getTypeArguments().length; i++){
584                 ITypeBinding typeArg= typeBinding.getTypeArguments()[i];
585                 Type argType= createParameterizedType(ast, typeArg); // recursive call
586
newType.typeArguments().add(argType);
587             }
588             return newType;
589         } else {
590             if (!typeBinding.isTypeVariable()){
591                 return ast.newSimpleType(ASTNodeFactory.newName(ast, typeBinding.getErasure().getName()));
592             } else {
593                 return ast.newSimpleType(ast.newSimpleName(typeBinding.getName()));
594             }
595         }
596     }
597     
598     
599     
600     private void groupChangesByCompilationUnit(Map JavaDoc relevantVarsByUnit) throws JavaModelException {
601         for (Iterator JavaDoc it= fRelevantVars.iterator(); it.hasNext();) {
602             ConstraintVariable cv= (ConstraintVariable) it.next();
603             if (!(cv instanceof ExpressionVariable) && !(cv instanceof ReturnTypeVariable)){
604                 continue;
605             }
606             ICompilationUnit icu = null;
607             if (cv instanceof ExpressionVariable) {
608                 ExpressionVariable ev = (ExpressionVariable)cv;
609                 icu = ev.getCompilationUnitRange().getCompilationUnit();
610             } else if (cv instanceof ReturnTypeVariable){
611                 ReturnTypeVariable rtv = (ReturnTypeVariable)cv;
612                 IMethodBinding mb= rtv.getMethodBinding();
613                 icu= ((IMethod) mb.getJavaElement()).getCompilationUnit();
614             }
615             if (!relevantVarsByUnit.containsKey(icu)){
616                 relevantVarsByUnit.put(icu, new HashSet JavaDoc/*<ConstraintVariable>*/());
617             }
618             ((Set JavaDoc)relevantVarsByUnit.get(icu)).add(cv);
619         }
620     }
621
622     private ASTNode findDeclaration(CompilationUnit root, ConstraintVariable cv) throws JavaModelException {
623
624         if (fFieldBinding != null){
625             IField f= (IField) fFieldBinding.getJavaElement();
626             return ASTNodeSearchUtil.getFieldDeclarationNode(f, root);
627         }
628         
629         if (cv instanceof ExpressionVariable){
630             for (Iterator JavaDoc iter= fAllConstraints.iterator(); iter.hasNext();) {
631                 ITypeConstraint constraint= (ITypeConstraint) iter.next();
632                 if (constraint.isSimpleTypeConstraint()){
633                     SimpleTypeConstraint stc= (SimpleTypeConstraint)constraint;
634                     if (stc.isDefinesConstraint() && stc.getLeft().equals(cv)){
635                         ConstraintVariable right= stc.getRight();
636                         if (right instanceof TypeVariable){
637                             TypeVariable typeVariable= (TypeVariable)right;
638                             return NodeFinder.perform(root, typeVariable.getCompilationUnitRange().getSourceRange());
639                         }
640                     }
641                 }
642             }
643         } else if (cv instanceof ReturnTypeVariable) {
644             ReturnTypeVariable rtv= (ReturnTypeVariable) cv;
645             IMethodBinding mb= rtv.getMethodBinding();
646             IMethod im= (IMethod) mb.getJavaElement();
647             return ASTNodeSearchUtil.getMethodDeclarationNode(im, root);
648         }
649         return null;
650     }
651     
652     private static Type getType(ASTNode node) {
653         switch(node.getNodeType()){
654             case ASTNode.SINGLE_VARIABLE_DECLARATION:
655                 return ((SingleVariableDeclaration) node).getType();
656             case ASTNode.FIELD_DECLARATION:
657                 return ((FieldDeclaration) node).getType();
658             case ASTNode.VARIABLE_DECLARATION_STATEMENT:
659                 return ((VariableDeclarationStatement) node).getType();
660             case ASTNode.METHOD_DECLARATION:
661                 return ((MethodDeclaration)node).getReturnType2();
662             case ASTNode.PARAMETERIZED_TYPE:
663                 return ((ParameterizedType)node).getType();
664             default:
665                 Assert.isTrue(false);
666                 return null;
667         }
668     }
669
670     /*
671      * @see org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring#getName()
672      */

673     public String JavaDoc getName() {
674         return RefactoringCoreMessages.ChangeTypeRefactoring_name;
675     }
676
677     // ------------------------------------------------------------------------------------------------- //
678
// Method for examining if a suitable kind of ASTNode was selected. Information about this node and
679
// its parents in the AST are stored in fields fBinding, theMethod, and theField
680

681     /**
682      * Determines what kind of ASTNode has been selected. A non-null String containing an error message
683      * is returned if the ChangeTypeRefactoring refactoring cannot be applied to the selected ASTNode.
684      * A return value of null indicates a valid selection.
685      */

686     private String JavaDoc determineSelection(ASTNode node) {
687         if (node == null) {
688             return RefactoringCoreMessages.ChangeTypeRefactoring_invalidSelection;
689         } else {
690             
691             if (DEBUG) System.out.println("node nodeType= " + node.getClass().getName()); //$NON-NLS-1$
692
if (DEBUG) System.out.println("parent nodeType= " + node.getParent().getClass().getName()); //$NON-NLS-1$
693
if (DEBUG) System.out.println("GrandParent nodeType= " + node.getParent().getParent().getClass().getName()); //$NON-NLS-1$
694

695             ASTNode parent= node.getParent();
696             ASTNode grandParent= parent.getParent();
697             if (grandParent == null)
698                 return nodeTypeNotSupported();
699             
700             // adjustment needed if part of a parameterized type is selected
701
if (grandParent.getNodeType() == ASTNode.PARAMETERIZED_TYPE){
702                 node= grandParent;
703             }
704             
705             // adjustment needed if part of a qualified name is selected
706
ASTNode current= null;
707             if (node.getNodeType() == ASTNode.QUALIFIED_NAME){
708                 current= node;
709                 while (current.getNodeType() == ASTNode.QUALIFIED_NAME){
710                     current= current.getParent();
711                 }
712                 if (current.getNodeType() != ASTNode.SIMPLE_TYPE){
713                     return nodeTypeNotSupported();
714                 }
715                 node= current.getParent();
716             } else if (parent.getNodeType() == ASTNode.QUALIFIED_NAME){
717                 current= parent;
718                 while (current.getNodeType() == ASTNode.QUALIFIED_NAME){
719                     current= current.getParent();
720                 }
721                 if (current.getNodeType() != ASTNode.SIMPLE_TYPE){
722                     return nodeTypeNotSupported();
723                 }
724                 node= current.getParent();
725             }
726             
727             fObject= node.getAST().resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
728
switch (node.getNodeType()) {
729                 case ASTNode.SIMPLE_NAME :
730                     return simpleNameSelected((SimpleName)node);
731                 case ASTNode.VARIABLE_DECLARATION_STATEMENT :
732                     return variableDeclarationStatementSelected((VariableDeclarationStatement) node);
733                 case ASTNode.FIELD_DECLARATION :
734                     return fieldDeclarationSelected((FieldDeclaration) node);
735                 case ASTNode.SINGLE_VARIABLE_DECLARATION :
736                     return singleVariableDeclarationSelected((SingleVariableDeclaration) node);
737                 case ASTNode.PARAMETERIZED_TYPE:
738                     return parameterizedTypeSelected((ParameterizedType) node);
739                 default :
740                     return nodeTypeNotSupported();
741             }
742         }
743     }
744     /**
745      * The selection corresponds to an ASTNode on which "ChangeTypeRefactoring" is not defined.
746      */

747     private static String JavaDoc nodeTypeNotSupported() {
748         return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType;
749     }
750
751     /**
752       * The selection corresponds to a SingleVariableDeclaration
753       */

754     private String JavaDoc singleVariableDeclarationSelected(SingleVariableDeclaration svd) {
755         SimpleName name = svd.getName();
756         setSelectionRanges(name);
757         return simpleNameSelected(name);
758     }
759
760     /**
761       * The selection corresponds to a ParameterizedType (return type of method)
762       */

763     private String JavaDoc parameterizedTypeSelected(ParameterizedType pt) {
764         ASTNode parent= pt.getParent();
765         if (parent.getNodeType() == ASTNode.METHOD_DECLARATION){
766             fMethodBinding= ((MethodDeclaration)parent).resolveBinding();
767             fParamIndex= -1;
768             fEffectiveSelectionStart= pt.getStartPosition();
769             fEffectiveSelectionLength= pt.getLength();
770             setOriginalType(pt.resolveBinding());
771         } else if (parent.getNodeType() == ASTNode.SINGLE_VARIABLE_DECLARATION){
772             return singleVariableDeclarationSelected((SingleVariableDeclaration)parent);
773         } else if (parent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT){
774             return variableDeclarationStatementSelected((VariableDeclarationStatement)parent);
775         } else if (parent.getNodeType() == ASTNode.FIELD_DECLARATION){
776             return fieldDeclarationSelected((FieldDeclaration)parent);
777         } else {
778             return nodeTypeNotSupported();
779         }
780         return null;
781     }
782     
783     /**
784      * The selection corresponds to a VariableDeclarationStatement
785      */

786     private String JavaDoc variableDeclarationStatementSelected(VariableDeclarationStatement vds) {
787         if (vds.fragments().size() != 1) {
788             return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
789         } else {
790             VariableDeclarationFragment elem= (VariableDeclarationFragment) vds.fragments().iterator().next();
791             SimpleName name= elem.getName();
792             setSelectionRanges(name);
793             return simpleNameSelected(name);
794         }
795     }
796
797     /**
798      * The selection corresponds to a FieldDeclaration
799      */

800     private String JavaDoc fieldDeclarationSelected(FieldDeclaration fieldDeclaration) {
801         if (fieldDeclaration.fragments().size() != 1) {
802             return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
803         } else {
804             VariableDeclarationFragment elem= (VariableDeclarationFragment) fieldDeclaration.fragments().iterator().next();
805             fFieldBinding= elem.resolveBinding();
806             SimpleName name= elem.getName();
807             setSelectionRanges(name);
808             return simpleNameSelected(name);
809         }
810     }
811
812     /**
813      * The selection corresponds to a SimpleName
814      */

815     private String JavaDoc simpleNameSelected(SimpleName simpleName) {
816         ASTNode parent= simpleName.getParent();
817         ASTNode grandParent= parent.getParent();
818             
819         if (parent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT){
820             VariableDeclarationStatement vds= (VariableDeclarationStatement)parent;
821             if (vds.fragments().size() > 1){
822                 return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
823             }
824         } else if (parent.getNodeType() == ASTNode.VARIABLE_DECLARATION_FRAGMENT) {
825             if (grandParent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT){
826                 VariableDeclarationStatement vds= (VariableDeclarationStatement)grandParent;
827                 if (vds.fragments().size() > 1) {
828                     return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
829                 }
830                 setSelectionRanges(simpleName);
831             } else if (grandParent.getNodeType() == ASTNode.VARIABLE_DECLARATION_EXPRESSION) {
832                 VariableDeclarationExpression vde= (VariableDeclarationExpression)grandParent;
833                 if (vde.fragments().size() > 1) {
834                     return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
835                 }
836                 setSelectionRanges(simpleName);
837             } else if (grandParent.getNodeType() == ASTNode.FIELD_DECLARATION) {
838                 FieldDeclaration fd= (FieldDeclaration)grandParent;
839                 if (fd.fragments().size() > 1){
840                     return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
841                 }
842                 VariableDeclarationFragment fragment = (VariableDeclarationFragment)parent;
843                 fFieldBinding= fragment.resolveBinding();
844                 setSelectionRanges(fragment.getName());
845             } else {
846                 return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType;
847             }
848         } else if (parent.getNodeType() == ASTNode.SINGLE_VARIABLE_DECLARATION) {
849             SingleVariableDeclaration singleVariableDeclaration= (SingleVariableDeclaration) parent;
850             if ((grandParent.getNodeType() == ASTNode.METHOD_DECLARATION)) {
851                 fMethodBinding= ((MethodDeclaration)grandParent).resolveBinding();
852                 setOriginalType(simpleName.resolveTypeBinding());
853                 fParamIndex= ((MethodDeclaration)grandParent).parameters().indexOf(parent);
854                 fParamName= singleVariableDeclaration.getName().getIdentifier();
855             } else {
856                 setSelectionRanges(singleVariableDeclaration.getName());
857             }
858         } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE && (grandParent.getNodeType() == ASTNode.SINGLE_VARIABLE_DECLARATION)) {
859             ASTNode greatGrandParent= grandParent.getParent();
860             SingleVariableDeclaration singleVariableDeclaration= (SingleVariableDeclaration) grandParent;
861             if (singleVariableDeclaration.getExtraDimensions() > 0) {
862                 return RefactoringCoreMessages.ChangeTypeRefactoring_arraysNotSupported;
863             }
864             if (greatGrandParent != null && greatGrandParent.getNodeType() == ASTNode.METHOD_DECLARATION) {
865                 fMethodBinding= ((MethodDeclaration)greatGrandParent).resolveBinding();
866                 fParamIndex= ((MethodDeclaration)greatGrandParent).parameters().indexOf(grandParent);
867                 fParamName= singleVariableDeclaration.getName().getIdentifier();
868                 setSelectionRanges(simpleName);
869             } else {
870                 setSelectionRanges(singleVariableDeclaration.getName());
871             }
872         } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE && grandParent.getNodeType() == ASTNode.METHOD_DECLARATION) {
873             fMethodBinding= ((MethodDeclaration)grandParent).resolveBinding();
874             setOriginalType(fMethodBinding.getReturnType());
875             fParamIndex= -1;
876         } else if (parent.getNodeType() == ASTNode.METHOD_DECLARATION &&
877                 grandParent.getNodeType() == ASTNode.TYPE_DECLARATION) {
878             MethodDeclaration methodDeclaration= (MethodDeclaration)parent;
879             if (methodDeclaration.getName().equals(simpleName) || methodDeclaration.thrownExceptions().contains(simpleName)){
880                 return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType;
881             }
882             fMethodBinding= ((MethodDeclaration)parent).resolveBinding();
883             fParamIndex= -1;
884         } else if (
885                 parent.getNodeType() == ASTNode.SIMPLE_TYPE && (grandParent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT)) {
886             return variableDeclarationStatementSelected((VariableDeclarationStatement) grandParent);
887         } else if (parent.getNodeType() == ASTNode.CAST_EXPRESSION) {
888             ASTNode decl= findDeclaration(parent.getRoot(), fSelectionStart, fSelectionLength+1);
889             VariableDeclarationFragment fragment= (VariableDeclarationFragment)decl;
890             SimpleName name = fragment.getName();
891             setSelectionRanges(name);
892         } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE &&
893                 grandParent.getNodeType() == ASTNode.FIELD_DECLARATION) {
894             return fieldDeclarationSelected((FieldDeclaration) grandParent);
895         } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE &&
896                 grandParent.getNodeType() == ASTNode.ARRAY_TYPE){
897             return RefactoringCoreMessages.ChangeTypeRefactoring_arraysNotSupported;
898         } else if (parent.getNodeType() == ASTNode.QUALIFIED_NAME){
899             setSelectionRanges(simpleName);
900         } else {
901             return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType;
902         }
903         return null;
904     }
905
906     // ------------------------------------------------------------------------------------------------- //
907
// Methods for examining & solving type constraints. This includes:
908
// (1) locating the ConstraintVariable corresponding to the selected ASTNode
909
// (2) finding all ConstraintVariables "related" to (1) via overriding, method calls, field access
910
// (3) find all ITypeConstraints of interest that mention ConstraintVariables in (2)
911
// (4) determining all ITypes for which the ITypeConstraints in (3) are satisfied
912

913     /**
914      * Find a ConstraintVariable that corresponds to the selected ASTNode.
915      */

916     private ConstraintVariable findConstraintVariableForSelectedNode(IProgressMonitor pm) {
917         pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, 100);
918         ICompilationUnit[] cus= { fCu }; // only search in CU containing selection
919

920         if (DEBUG){
921             System.out.println("Effective selection: " + fEffectiveSelectionStart + "/" + fEffectiveSelectionLength); //$NON-NLS-1$ //$NON-NLS-2$
922
}
923         
924         Collection JavaDoc/*<ITypeConstraint>*/ allConstraints= getConstraints(cus, new SubProgressMonitor(pm, 50));
925         
926         IProgressMonitor subMonitor= new SubProgressMonitor(pm, 50);
927         subMonitor.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, allConstraints.size());
928         for (Iterator JavaDoc it= allConstraints.iterator(); it.hasNext(); ) {
929             subMonitor.worked(1);
930             ITypeConstraint tc= (ITypeConstraint)it.next();
931             if (! (tc instanceof SimpleTypeConstraint))
932                 continue;
933             SimpleTypeConstraint stc= (SimpleTypeConstraint) tc;
934             if (matchesSelection(stc.getLeft()))
935                 return stc.getLeft();
936             if (matchesSelection(stc.getRight()))
937                 return stc.getRight();
938         }
939         subMonitor.done();
940         pm.done();
941         Assert.isTrue(false, RefactoringCoreMessages.ChangeTypeRefactoring_noMatchingConstraintVariable);
942         return null;
943     }
944
945     /**
946      * Determine if a given ConstraintVariable matches the selected ASTNode.
947      */

948     private boolean matchesSelection(ConstraintVariable cv){
949         if (cv instanceof ExpressionVariable){
950             ExpressionVariable ev= (ExpressionVariable)cv;
951             return (fSelectionBinding != null && Bindings.equals(fSelectionBinding, ev.getExpressionBinding()));
952         } else if (cv instanceof ParameterTypeVariable){
953             ParameterTypeVariable ptv = (ParameterTypeVariable)cv;
954             if (fMethodBinding != null && Bindings.equals(ptv.getMethodBinding(), fMethodBinding) &&
955                 ptv.getParameterIndex() == fParamIndex){
956                 return true;
957             }
958         } else if (cv instanceof ReturnTypeVariable){
959             ReturnTypeVariable rtv = (ReturnTypeVariable)cv;
960             if (fMethodBinding != null && Bindings.equals(rtv.getMethodBinding(), fMethodBinding) &&
961                 fParamIndex == -1){
962                 return true;
963             }
964         }
965         return false;
966     }
967         
968     /**
969      * Determine the set of constraint variables related to the selected
970      * expression. In addition to the expression itself, this consists of
971      * any expression that is defines-equal to it, and any expression equal
972      * to it.
973      */

974     private Collection JavaDoc/*<ConstraintVariable>*/ findRelevantConstraintVars(ConstraintVariable cv, IProgressMonitor pm) throws CoreException {
975         pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, 150);
976         Collection JavaDoc/*<ConstraintVariable>*/ result= new HashSet JavaDoc();
977         result.add(cv);
978         ICompilationUnit[] cus= collectAffectedUnits(new SubProgressMonitor(pm, 50));
979         Collection JavaDoc/*<ITypeConstraint>*/ allConstraints= getConstraints(cus, new SubProgressMonitor(pm, 50));
980
981         List JavaDoc/*<ConstraintVariable>*/ workList= new ArrayList JavaDoc(result);
982         while(! workList.isEmpty()){
983             
984             pm.worked(10);
985             
986             ConstraintVariable first= (ConstraintVariable)workList.remove(0);
987             for (Iterator JavaDoc iter= allConstraints.iterator(); iter.hasNext();) {
988                 pm.worked(1);
989                 ITypeConstraint typeConstraint= (ITypeConstraint) iter.next();
990                 if (! typeConstraint.isSimpleTypeConstraint())
991                     continue;
992                 SimpleTypeConstraint stc= (SimpleTypeConstraint)typeConstraint;
993                 if (! stc.isDefinesConstraint() && ! stc.isEqualsConstraint())
994                     continue;
995                 ConstraintVariable match= match(first, stc.getLeft(), stc.getRight());
996                 if (match instanceof ExpressionVariable
997                 || match instanceof ParameterTypeVariable
998                 || match instanceof ReturnTypeVariable){
999                     if (! result.contains(match)){
1000                        workList.add(match);
1001                        result.add(match);
1002                    }
1003                }
1004            }
1005        }
1006        
1007        pm.done();
1008        
1009        return result;
1010    }
1011    private static ConstraintVariable match(ConstraintVariable matchee, ConstraintVariable left, ConstraintVariable right) {
1012        if (matchee.equals(left))
1013            return right;
1014        if (matchee.equals(right))
1015            return left;
1016        return null;
1017    }
1018
1019    /**
1020     * Select the type constraints that involve the selected ASTNode.
1021     */

1022    private Collection JavaDoc/*<ITypeConstraint>*/ findRelevantConstraints(Collection JavaDoc/*<ConstraintVariable>*/ relevantConstraintVars,
1023                                                                    IProgressMonitor pm) throws CoreException {
1024
1025        ICompilationUnit[] cus= collectAffectedUnits(new SubProgressMonitor(pm, 100));
1026        
1027        fAllConstraints= getConstraints(cus, new SubProgressMonitor(pm, 900));
1028        
1029        pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, 1000 + fAllConstraints.size());
1030        
1031
1032        if (DEBUG) printCollection("type constraints: ", fAllConstraints); //$NON-NLS-1$
1033
Collection JavaDoc/*<ITypeConstraint>*/ result= new ArrayList JavaDoc();
1034        for (Iterator JavaDoc it= fAllConstraints.iterator(); it.hasNext(); ) {
1035            ITypeConstraint tc= (ITypeConstraint)it.next();
1036            if (tc.isSimpleTypeConstraint()) {
1037                SimpleTypeConstraint stc= (SimpleTypeConstraint) tc;
1038                if (stc.isDefinesConstraint() || stc.isEqualsConstraint())
1039                    continue;
1040                if (stc.getLeft().equals(stc.getRight()))
1041                    continue;
1042                if (isNull(stc.getLeft()))
1043                    continue;
1044                if (relevantConstraintVars.contains(stc.getLeft()) || relevantConstraintVars.contains(stc.getRight()))
1045                    result.add(tc);
1046            } else {
1047                CompositeOrTypeConstraint cotc= (CompositeOrTypeConstraint) tc;
1048                ITypeConstraint[] components= cotc.getConstraints();
1049                for (int i= 0; i < components.length; i++) {
1050                    ITypeConstraint component= components[i];
1051                    SimpleTypeConstraint simpleComponent= (SimpleTypeConstraint) component;
1052                    if (relevantConstraintVars.contains(simpleComponent.getLeft()))
1053                        result.add(tc);
1054                }
1055            }
1056            pm.worked(1);
1057        }
1058        if (DEBUG)
1059            printCollection("selected constraints: ", result); //$NON-NLS-1$
1060
pm.done();
1061        return result;
1062    }
1063    
1064    /**
1065     * Finds the declaration of the ASTNode in a given AST at a specified offset and with a specified length
1066     */

1067    private static ASTNode findDeclaration(final ASTNode root, final int start, final int length){
1068        ASTNode node= NodeFinder.perform(root, start, length);
1069        Assert.isTrue(node instanceof SimpleName, String.valueOf(node.getNodeType()));
1070        Assert.isTrue(root instanceof CompilationUnit, String.valueOf(root.getNodeType()));
1071        return ((CompilationUnit)root).findDeclaringNode(((SimpleName)node).resolveBinding());
1072    }
1073    
1074    // For debugging
1075
static String JavaDoc print(Collection JavaDoc/*<ITypeBinding>*/ types){
1076        if (types.isEmpty())
1077            return "{ }"; //$NON-NLS-1$
1078
String JavaDoc result = "{ "; //$NON-NLS-1$
1079
for (Iterator JavaDoc it=types.iterator(); it.hasNext(); ){
1080            ITypeBinding type= (ITypeBinding)it.next();
1081            result += type.getQualifiedName();
1082            if (it.hasNext()){
1083                result += ", "; //$NON-NLS-1$
1084
} else {
1085                result += " }"; //$NON-NLS-1$
1086
}
1087        }
1088        return result;
1089    }
1090
1091    
1092    /**
1093     * Determines the set of types for which a set of type constraints is satisfied.
1094     */

1095    private Collection JavaDoc/*<ITypeBinding>*/ computeValidTypes(ITypeBinding originalType,
1096                                                    Collection JavaDoc/*<ConstraintVariable>*/ relevantVars,
1097                                                    Collection JavaDoc/*<ITypeConstraint>*/ relevantConstraints,
1098                                                    IProgressMonitor pm) throws JavaModelException {
1099        
1100        Collection JavaDoc/*<ITypeBinding>*/ result= new HashSet JavaDoc();
1101        IJavaProject project= fCu.getJavaProject();
1102
1103        Collection JavaDoc/*<ITypeBinding>*/ allTypes = new HashSet JavaDoc/*<IType>*/();
1104        allTypes.addAll(getAllSuperTypes(originalType));
1105        
1106        pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, allTypes.size());
1107
1108        for (Iterator JavaDoc/*<ITypeBinding>*/ it= allTypes.iterator(); it.hasNext(); ) {
1109            ITypeBinding type= (ITypeBinding)it.next();
1110            if (isValid(project, type, relevantVars, relevantConstraints, new SubProgressMonitor(pm, 1))) {
1111                result.add(type);
1112            }
1113        }
1114        // "changing" to the original type is a no-op
1115
result.remove(originalType);
1116
1117        // TODO: remove all types that are not visible --- need to check visibility in the CUs for
1118
// all relevant constraint variables
1119

1120        pm.done();
1121        
1122        return result;
1123    }
1124
1125    /**
1126     * Determines if a given type satisfies a set of type constraints.
1127     */

1128    private boolean isValid(IJavaProject project,
1129                            ITypeBinding type,
1130                            Collection JavaDoc/*<ConstraintVariable>*/ relevantVars,
1131                            Collection JavaDoc/*<ITypeConstraint>*/ constraints,
1132                            IProgressMonitor pm) throws JavaModelException {
1133        pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, constraints.size());
1134        for (Iterator JavaDoc it= constraints.iterator(); it.hasNext(); ) {
1135            ITypeConstraint tc= (ITypeConstraint)it.next();
1136            if (tc instanceof SimpleTypeConstraint) {
1137                if (!(isValidSimpleConstraint(project, type, relevantVars, (SimpleTypeConstraint) tc)))
1138                    return false;
1139            } else if (tc instanceof CompositeOrTypeConstraint) {
1140                if (!(isValidOrConstraint(project, type, relevantVars, (CompositeOrTypeConstraint) tc)))
1141                    return false;
1142            }
1143            pm.worked(1);
1144        }
1145        pm.done();
1146        return true;
1147    }
1148    
1149    private boolean isValidSimpleConstraint(IJavaProject project, ITypeBinding type,
1150                                            Collection JavaDoc/*<ConstraintVariable>*/ relevantVars,
1151                                            SimpleTypeConstraint stc) throws JavaModelException{
1152        if (relevantVars.contains(stc.getLeft())) { // upper bound
1153
if (!isSubTypeOf(type, findType(stc.getRight()))) {
1154                return false;
1155            }
1156        }
1157        return true;
1158    }
1159    
1160    private boolean isValidOrConstraint(IJavaProject project, ITypeBinding type,
1161                                        Collection JavaDoc/*<ConstraintVariable>*/ relevantVars,
1162                                        CompositeOrTypeConstraint cotc) throws JavaModelException{
1163        ITypeConstraint[] components= cotc.getConstraints();
1164        for (int i= 0; i < components.length; i++) {
1165            if (components[i] instanceof SimpleTypeConstraint) {
1166                SimpleTypeConstraint sc= (SimpleTypeConstraint) components[i];
1167                if (relevantVars.contains(sc.getLeft())) { // upper bound
1168
if (isSubTypeOf(type, findType(sc.getRight())))
1169                        return true;
1170                } else if (relevantVars.contains(sc.getRight())) { // lower bound
1171
if (isSubTypeOf(findType(sc.getLeft()), type))
1172                        return true;
1173                }
1174            }
1175        }
1176        return false;
1177    }
1178    
1179    
1180    private ITypeBinding findType(ConstraintVariable cv) {
1181        return cv.getBinding();
1182    }
1183
1184    /**
1185     * Gather constraints associated with a set of compilation units.
1186     */

1187    private Collection JavaDoc/*<ITypeConstraint>*/ getConstraints(ICompilationUnit[] referringCus, IProgressMonitor pm) {
1188        pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, referringCus.length);
1189        Collection JavaDoc/*<ITypeConstraint>*/ result= new ArrayList JavaDoc();
1190        for (int i= 0; i < referringCus.length; i++) {
1191            result.addAll(getConstraints(referringCus[i]));
1192            pm.worked(1);
1193            if (pm.isCanceled())
1194                throw new OperationCanceledException();
1195        }
1196        pm.done();
1197        return result;
1198    }
1199
1200    private List JavaDoc/*<ITypeConstraint>*/ getConstraints(ICompilationUnit unit) {
1201        if (fConstraintCache.containsKey(unit))
1202            return (List JavaDoc) fConstraintCache.get(unit);
1203        
1204        CompilationUnit cu= ASTCreator.createAST(unit, null);
1205        
1206        // only generate type constraints for relevant MethodDeclaration subtrees
1207
if (fMethodBinding != null && fCuToSearchResultGroup.containsKey(unit)){
1208            SearchResultGroup group= (SearchResultGroup) fCuToSearchResultGroup.get(unit);
1209            ASTNode[] nodes= ASTNodeSearchUtil.getAstNodes(group.getSearchResults(), cu);
1210            for (int i=0; i < nodes.length; i++){
1211                ASTNode node = nodes[i];
1212                if (fMethodBinding != null){
1213                    // find MethodDeclaration above it in the tree
1214
ASTNode n= node;
1215                    while (!(n instanceof MethodDeclaration)){
1216                        n = n.getParent();
1217                    }
1218                    MethodDeclaration md = (MethodDeclaration)n;
1219                    md.accept(fCollector);
1220                }
1221            }
1222        } else {
1223            cu.accept(fCollector);
1224        }
1225        List JavaDoc/*<ITypeConstraint>*/ constraints= Arrays.asList(fCollector.getConstraints());
1226        fConstraintCache.put(unit, constraints);
1227        return constraints;
1228    }
1229    
1230    /**
1231     * update a CompilationUnit's imports after changing the type of declarations
1232     */

1233    private String JavaDoc updateImports(CompilationUnit astRoot, MultiTextEdit rootEdit) throws CoreException{
1234        ImportRewrite rewrite= StubUtility.createImportRewrite(astRoot, true);
1235        String JavaDoc typeName= rewrite.addImport(fSelectedType.getQualifiedName());
1236        rootEdit.addChild(rewrite.rewriteImports(null));
1237        return typeName;
1238    }
1239
1240    // ------------------------------------------------------------------------------------------------- //
1241
// Miscellaneous helper methods
1242

1243    /**
1244     * Returns the Collection<IType> of types that can be given to the selected declaration.
1245     */

1246    public Collection JavaDoc/*<IType>*/ getValidTypes() {
1247        return fValidTypes;
1248    }
1249    
1250    public ITypeBinding getOriginalType(){
1251        return fSelectionTypeBinding;
1252    }
1253    
1254    private void setOriginalType(ITypeBinding originalType){
1255        fSelectionTypeBinding= originalType;
1256        fSelectedType= findSuperTypeByName(originalType, fSelectedTypeName);
1257    }
1258    
1259    public String JavaDoc getTarget() {
1260        String JavaDoc typeName= fSelectionTypeBinding == null ? "" : fSelectionTypeBinding.getName() + " "; //$NON-NLS-1$//$NON-NLS-2$
1261
if (fFieldBinding != null) {
1262            return typeName + fFieldBinding.getName();
1263        } else if (fMethodBinding != null) {
1264            if (fParamIndex == -1) {
1265                return typeName + fMethodBinding.getName() + "(...)"; //$NON-NLS-1$
1266
} else {
1267                return typeName + fParamName;
1268            }
1269        } else if (fSelectionBinding != null) {
1270            return typeName + fSelectionBinding.getName();
1271        } else {
1272            return typeName;
1273        }
1274    }
1275    
1276    /**
1277     * Returns the Collection<String> of names of types that can be given to the selected declaration.
1278     * (used in tests only)
1279     */

1280    public Collection JavaDoc/*<String>*/ getValidTypeNames() {
1281        Collection JavaDoc/*<String>*/ typeNames= new ArrayList JavaDoc();
1282        for (Iterator JavaDoc it= fValidTypes.iterator(); it.hasNext();) {
1283            ITypeBinding type= (ITypeBinding) it.next();
1284            typeNames.add(type.getQualifiedName());
1285        }
1286
1287        return typeNames;
1288    }
1289
1290    /**
1291     * Find the ASTNode for the given source text selection, if it is a type
1292     * declaration, or null otherwise.
1293     * @param unit The compilation unit in which the selection was made
1294     * @param offset
1295     * @param length
1296     * @return ASTNode
1297     */

1298    private ASTNode getTargetNode(ICompilationUnit unit, int offset, int length) {
1299        CompilationUnit root= ASTCreator.createAST(unit, null);
1300        ASTNode node= NodeFinder.perform(root, offset, length);
1301        return node;
1302    }
1303
1304    /**
1305     * Determines the set of compilation units that may give rise to type constraints that
1306     * we are interested in. This involves searching for overriding/overridden methods,
1307     * method calls, field accesses.
1308     */

1309    private ICompilationUnit[] collectAffectedUnits(IProgressMonitor pm) throws CoreException {
1310        // BUG: currently, no type constraints are generated for methods that are related
1311
// but that do not override each other. As a result, we may miss certain relevant
1312
// variables
1313

1314        pm.beginTask(RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage, 100);
1315        
1316        if (fAffectedUnits != null) {
1317            if (DEBUG) printCollection("affected units: ", Arrays.asList(fAffectedUnits)); //$NON-NLS-1$
1318
pm.worked(100);
1319            return fAffectedUnits;
1320        }
1321        if (fMethodBinding != null) {
1322            if (fMethodBinding != null) {
1323                
1324                
1325                IMethod selectedMethod= (IMethod) fMethodBinding.getJavaElement();
1326                if (selectedMethod == null) {
1327                    // can't happen since we checked it up front in check initial conditions
1328
Assert.isTrue(false, RefactoringCoreMessages.ChangeTypeRefactoring_no_method);
1329                }
1330                
1331                // the following code fragment appears to be the source of a memory leak, when
1332
// GT is repeatedly applied
1333

1334                IMethod root= selectedMethod;
1335                if (! root.getDeclaringType().isInterface() && MethodChecks.isVirtual(root)) {
1336                    final SubProgressMonitor subMonitor= new SubProgressMonitor(pm, 5);
1337                    IMethod inInterface= MethodChecks.isDeclaredInInterface(root, root.getDeclaringType().newTypeHierarchy(new SubProgressMonitor(subMonitor, 1)), subMonitor);
1338                    if (inInterface != null && !inInterface.equals(root))
1339                        root= inInterface;
1340                }
1341
1342                // end code fragment
1343

1344                IMethod[] rippleMethods= RippleMethodFinder2.getRelatedMethods(
1345                        root, new SubProgressMonitor(pm, 15), null);
1346                SearchPattern pattern= RefactoringSearchEngine.createOrPattern(
1347                        rippleMethods, IJavaSearchConstants.ALL_OCCURRENCES);
1348
1349                // To compute the scope we have to use the selected method. Otherwise we
1350
// might start from the wrong project.
1351
IJavaSearchScope scope= RefactoringScopeFactory.create(selectedMethod);
1352                CollectingSearchRequestor csr= new CollectingSearchRequestor();
1353                
1354                SearchResultGroup[] groups= RefactoringSearchEngine.search(
1355                    pattern,
1356                    null,
1357                    scope,
1358                    csr,
1359                    new SubProgressMonitor(pm, 80),
1360                    new RefactoringStatus()); //TODO: deal with errors from non-CU matches
1361

1362                fAffectedUnits= getCus(groups);
1363            }
1364        } else if (fFieldBinding != null) {
1365            IField iField= (IField) fFieldBinding.getJavaElement();
1366            if (iField == null) {
1367                // can't happen since we checked it up front in check initial conditions
1368
Assert.isTrue(false, RefactoringCoreMessages.ChangeTypeRefactoring_no_filed);
1369            }
1370            SearchPattern pattern= SearchPattern.createPattern(
1371                    iField, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
1372            IJavaSearchScope scope= RefactoringScopeFactory.create(iField);
1373            CollectingSearchRequestor csr= new CollectingSearchRequestor();
1374            SearchResultGroup[] groups=
1375                RefactoringSearchEngine.search(pattern, null, scope, csr, new SubProgressMonitor(pm, 100),
1376                        new RefactoringStatus()); //TODO: deal with errors from non-CU matches
1377
fAffectedUnits= getCus(groups);
1378        } else {
1379            // otherwise, selection was a local variable and we only have to search the CU
1380
// containing the selection
1381
fAffectedUnits= new ICompilationUnit[] { fCu };
1382        }
1383        if (DEBUG) {
1384            System.out.println("Determining affected CUs:"); //$NON-NLS-1$
1385
for (int i= 0; i < fAffectedUnits.length; i++) {
1386                System.out.println(" affected CU: " + fAffectedUnits[i].getElementName()); //$NON-NLS-1$
1387
}
1388        }
1389        pm.done();
1390        return fAffectedUnits;
1391    }
1392
1393    public void setSelectedType(ITypeBinding type){
1394        fSelectedType= type;
1395    }
1396    
1397    // -------------------------------------------------------------------------------------------- //
1398
// TODO The following utility methods should probably be moved to another class
1399

1400    /**
1401     * Determines if a constraint variable corresponds to the constant "null".
1402     */

1403    private static boolean isNull(ConstraintVariable cv) {
1404        return cv instanceof ExpressionVariable && ((ExpressionVariable)cv).getExpressionType() == ASTNode.NULL_LITERAL;
1405    }
1406
1407
1408    /**
1409     * For debugging.
1410     */

1411    void printCollection(String JavaDoc title, Collection JavaDoc/*<Object>*/ l) {
1412        System.out.println(l.size() + " " + title); //$NON-NLS-1$
1413
for (Iterator JavaDoc it= l.iterator(); it.hasNext();) {
1414            System.out.println(" " + it.next()); //$NON-NLS-1$
1415
}
1416    }
1417
1418    /**
1419     * Returns the compilation units that contain the search results.
1420     */

1421    private ICompilationUnit[] getCus(SearchResultGroup[] groups) {
1422        List JavaDoc result= new ArrayList JavaDoc(groups.length);
1423        for (int i= 0; i < groups.length; i++) {
1424            SearchResultGroup group= groups[i];
1425            ICompilationUnit cu= group.getCompilationUnit();
1426            if (cu != null) {
1427                result.add(cu);
1428                fCuToSearchResultGroup.put(cu, group);
1429            }
1430        }
1431        return (ICompilationUnit[]) result.toArray(new ICompilationUnit[result.size()]);
1432    }
1433    
1434    /**
1435     * This always includes the type itself. It will include type
1436     * Object for any type other than Object
1437     */

1438    public Set JavaDoc/*<ITypeBinding>*/ getAllSuperTypes(ITypeBinding type){
1439        Set JavaDoc/*<ITypeBinding>*/ result= new HashSet JavaDoc();
1440        result.add(type);
1441        if (type.getSuperclass() != null){
1442            result.addAll(getAllSuperTypes(type.getSuperclass()));
1443        }
1444        ITypeBinding[] interfaces= type.getInterfaces();
1445        for (int i=0; i < interfaces.length; i++){
1446            result.addAll(getAllSuperTypes(interfaces[i]));
1447        }
1448        if ((type != fObject) && !contains(result, fObject)){
1449            result.add(fObject);
1450        }
1451        return result;
1452    }
1453    
1454    private ITypeBinding findSuperTypeByName(ITypeBinding type, String JavaDoc superTypeName){
1455        Set JavaDoc/*<ITypeBinding>*/ superTypes= getAllSuperTypes(type);
1456        for (Iterator JavaDoc/*<ITypeBinding>*/ it= superTypes.iterator(); it.hasNext(); ){
1457            ITypeBinding sup= (ITypeBinding)it.next();
1458            if (sup.getQualifiedName().equals(superTypeName)){
1459                return sup;
1460            }
1461        }
1462        return null;
1463    }
1464    
1465    public boolean isSubTypeOf(ITypeBinding type1, ITypeBinding type2){
1466        
1467        // to ensure that, e.g., Comparable<String> is considered a subtype of raw Comparable
1468
if (type1.isParameterizedType() && type1.getTypeDeclaration().isEqualTo(type2.getTypeDeclaration())){
1469            return true;
1470        }
1471        Set JavaDoc superTypes= getAllSuperTypes(type1);
1472        return contains(superTypes, type2);
1473    }
1474    
1475    private static boolean contains(Collection JavaDoc/*<ITypeBinding>*/ c, ITypeBinding binding){
1476        for (Iterator JavaDoc/*<ITypeBinding>*/ it=c.iterator(); it.hasNext(); ){
1477            ITypeBinding b = (ITypeBinding)it.next();
1478            if (Bindings.equals(b, binding)) return true;
1479        }
1480        return false;
1481    }
1482
1483    /**
1484     * {@inheritDoc}
1485     */

1486    public RefactoringStatus initialize(RefactoringArguments arguments) {
1487        if (arguments instanceof JavaRefactoringArguments) {
1488            final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
1489            final String JavaDoc selection= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION);
1490            if (selection != null) {
1491                int offset= -1;
1492                int length= -1;
1493                final StringTokenizer JavaDoc tokenizer= new StringTokenizer JavaDoc(selection);
1494                if (tokenizer.hasMoreTokens())
1495                    offset= Integer.valueOf(tokenizer.nextToken()).intValue();
1496                if (tokenizer.hasMoreTokens())
1497                    length= Integer.valueOf(tokenizer.nextToken()).intValue();
1498                if (offset >= 0 && length >= 0) {
1499                    fSelectionStart= offset;
1500                    fSelectionLength= length;
1501                } else
1502                    return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object JavaDoc[] { selection, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION}));
1503            } else
1504                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION));
1505            final String JavaDoc handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
1506            if (handle != null) {
1507                final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
1508                if (element == null || !element.exists() || element.getElementType() != IJavaElement.COMPILATION_UNIT)
1509                    return createInputFatalStatus(element, IJavaRefactorings.GENERALIZE_TYPE);
1510                else
1511                    fCu= (ICompilationUnit) element;
1512            } else
1513                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
1514            final String JavaDoc type= extended.getAttribute(ATTRIBUTE_TYPE);
1515            if (type != null && !"".equals(type)) //$NON-NLS-1$
1516
fSelectedTypeName= type;
1517            else
1518                return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_TYPE));
1519        } else
1520            return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
1521        return new RefactoringStatus();
1522    }
1523}
1524
Popular Tags