Source Code Cross Referenced for ChangeTypeRefactoring.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » corext » refactoring » structure » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » jdt » org.eclipse.jdt.internal.corext.refactoring.structure 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *******************************************************************************/package org.eclipse.jdt.internal.corext.refactoring.structure;
0011:
0012:        import java.util.ArrayList;
0013:        import java.util.Arrays;
0014:        import java.util.Collection;
0015:        import java.util.HashMap;
0016:        import java.util.HashSet;
0017:        import java.util.Iterator;
0018:        import java.util.List;
0019:        import java.util.Map;
0020:        import java.util.Set;
0021:        import java.util.StringTokenizer;
0022:
0023:        import org.eclipse.text.edits.MultiTextEdit;
0024:        import org.eclipse.text.edits.TextEditGroup;
0025:
0026:        import org.eclipse.core.runtime.Assert;
0027:        import org.eclipse.core.runtime.CoreException;
0028:        import org.eclipse.core.runtime.IProgressMonitor;
0029:        import org.eclipse.core.runtime.NullProgressMonitor;
0030:        import org.eclipse.core.runtime.OperationCanceledException;
0031:        import org.eclipse.core.runtime.SubProgressMonitor;
0032:
0033:        import org.eclipse.ltk.core.refactoring.Change;
0034:        import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
0035:        import org.eclipse.ltk.core.refactoring.RefactoringStatus;
0036:        import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
0037:
0038:        import org.eclipse.jdt.core.ICompilationUnit;
0039:        import org.eclipse.jdt.core.IField;
0040:        import org.eclipse.jdt.core.IJavaElement;
0041:        import org.eclipse.jdt.core.IJavaProject;
0042:        import org.eclipse.jdt.core.IMethod;
0043:        import org.eclipse.jdt.core.JavaModelException;
0044:        import org.eclipse.jdt.core.dom.AST;
0045:        import org.eclipse.jdt.core.dom.ASTNode;
0046:        import org.eclipse.jdt.core.dom.CompilationUnit;
0047:        import org.eclipse.jdt.core.dom.Expression;
0048:        import org.eclipse.jdt.core.dom.FieldDeclaration;
0049:        import org.eclipse.jdt.core.dom.IBinding;
0050:        import org.eclipse.jdt.core.dom.IMethodBinding;
0051:        import org.eclipse.jdt.core.dom.ITypeBinding;
0052:        import org.eclipse.jdt.core.dom.IVariableBinding;
0053:        import org.eclipse.jdt.core.dom.MethodDeclaration;
0054:        import org.eclipse.jdt.core.dom.ParameterizedType;
0055:        import org.eclipse.jdt.core.dom.QualifiedName;
0056:        import org.eclipse.jdt.core.dom.SimpleName;
0057:        import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
0058:        import org.eclipse.jdt.core.dom.Type;
0059:        import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
0060:        import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
0061:        import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
0062:        import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
0063:        import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
0064:        import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
0065:        import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
0066:        import org.eclipse.jdt.core.refactoring.descriptors.GeneralizeTypeDescriptor;
0067:        import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
0068:        import org.eclipse.jdt.core.search.IJavaSearchConstants;
0069:        import org.eclipse.jdt.core.search.IJavaSearchScope;
0070:        import org.eclipse.jdt.core.search.SearchPattern;
0071:
0072:        import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
0073:        import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
0074:        import org.eclipse.jdt.internal.corext.dom.Bindings;
0075:        import org.eclipse.jdt.internal.corext.dom.NodeFinder;
0076:        import org.eclipse.jdt.internal.corext.refactoring.Checks;
0077:        import org.eclipse.jdt.internal.corext.refactoring.CollectingSearchRequestor;
0078:        import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
0079:        import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
0080:        import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
0081:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
0082:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
0083:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine;
0084:        import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
0085:        import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
0086:        import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
0087:        import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
0088:        import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks;
0089:        import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2;
0090:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ASTCreator;
0091:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompositeOrTypeConstraint;
0092:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintCollector;
0093:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintOperator;
0094:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintVariable;
0095:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintVariableFactory;
0096:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ExpressionVariable;
0097:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.FullConstraintCreator;
0098:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ITypeConstraint;
0099:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ParameterTypeVariable;
0100:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ReturnTypeVariable;
0101:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.SimpleTypeConstraint;
0102:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.TypeConstraintFactory;
0103:        import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.TypeVariable;
0104:        import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
0105:        import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
0106:        import org.eclipse.jdt.internal.corext.util.Messages;
0107:        import org.eclipse.jdt.internal.corext.util.SearchUtils;
0108:
0109:        import org.eclipse.jdt.ui.JavaElementLabels;
0110:
0111:        import org.eclipse.jdt.internal.ui.JavaPlugin;
0112:        import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
0113:
0114:        /**
0115:         * @author tip
0116:         */
0117:        public class ChangeTypeRefactoring extends ScriptableRefactoring {
0118:
0119:            private static final String ATTRIBUTE_TYPE = "type"; //$NON-NLS-1$
0120:
0121:            private final Map/*<ICompilationUnit, Collection<ITypeConstraint>>*/fConstraintCache;
0122:            /**
0123:             * Offset of the selected text area.
0124:             */
0125:            private int fSelectionStart;
0126:
0127:            /**
0128:             * Length of the selected text area.
0129:             */
0130:            private int fSelectionLength;
0131:
0132:            /**
0133:             * Offset of the effective selection
0134:             */
0135:            private int fEffectiveSelectionStart;
0136:
0137:            /**
0138:             * Length of the effective selection
0139:             */
0140:            private int fEffectiveSelectionLength;
0141:
0142:            /**
0143:             * ICompilationUnit containing the selection.
0144:             */
0145:            private ICompilationUnit fCu;
0146:
0147:            /**
0148:             * If the selection corresponds to a method parameter/return type, this field stores
0149:             * a reference to its IMethodBinding, otherwise this field remains null. Used during 
0150:             * search for references in other CUs, and for determining the ConstraintVariable
0151:             * that corresponds to the selection
0152:             */
0153:            private IMethodBinding fMethodBinding;
0154:
0155:            /**
0156:             * If the selection corresponds to a method parameter, this field stores the parameter
0157:             * index (0 = first parameter for static methods, 0 = this for nonstatic methods). The
0158:             * value -1 is stored in the field if the selection corresponds to a method return type.
0159:             */
0160:            private int fParamIndex;
0161:
0162:            /**
0163:             * The name of the selected parameter, or <code>null</code>.
0164:             */
0165:            private String fParamName;
0166:
0167:            /**
0168:             * If the selection corresponds to a field, this field stores a reference to its IVariableBinding,
0169:             * otherwise this field remains null. Used during search for references in other CUs.
0170:             */
0171:            private IVariableBinding fFieldBinding;
0172:
0173:            /**
0174:             * The compilation units that contain constraint variables related to the selection
0175:             */
0176:            private ICompilationUnit[] fAffectedUnits;
0177:
0178:            /**
0179:             * The constraint variables that are of interest to this refactoring. This includes
0180:             * the constraint var. corresponding to the text selection, and possibly additional
0181:             * elements due to method overriding, method calls, etc.
0182:             */
0183:            private Collection/*<ConstraintVariable>*/fRelevantVars;
0184:
0185:            /**
0186:             * The set of types (other than the original type) that can be given to
0187:             * the selected ASTNode.
0188:             */
0189:            private final Collection/*<IType>*/fValidTypes;
0190:
0191:            /**
0192:             * The type constraints that are related to the selected ASTNode.
0193:             */
0194:            private Collection/*<ITypeConstraint>*/fRelevantConstraints;
0195:
0196:            /**
0197:             * All type constraints in affected compilation units.
0198:             */
0199:            private Collection/*<ITypeConstraint>*/fAllConstraints;
0200:
0201:            /**
0202:             * The name of the new type of the selected declaration.
0203:             */
0204:            private String fSelectedTypeName;
0205:
0206:            /**
0207:             * The new type of the selected declaration.
0208:             */
0209:            private ITypeBinding fSelectedType;
0210:
0211:            /**
0212:             * Organizes SearchResults by CompilationUnit
0213:             */
0214:            private Map/*<ICompilationUnit,SearchResultGroup>*/fCuToSearchResultGroup = new HashMap();
0215:
0216:            /**
0217:             * ITypeBinding for java.lang.Object
0218:             */
0219:            private ITypeBinding fObject;
0220:
0221:            public ITypeBinding getObject() {
0222:                return fObject;
0223:            }
0224:
0225:            /**
0226:             * Control debugging output.
0227:             */
0228:            private static final boolean DEBUG = false;
0229:
0230:            private ConstraintVariable fCv;
0231:            private IBinding fSelectionBinding;
0232:            private ITypeBinding fSelectionTypeBinding;
0233:            private ConstraintCollector fCollector;
0234:
0235:            public ChangeTypeRefactoring(ICompilationUnit cu,
0236:                    int selectionStart, int selectionLength) {
0237:                this (cu, selectionStart, selectionLength, null);
0238:            }
0239:
0240:            /**
0241:             * Constructor for ChangeTypeRefactoring (invoked from tests only)
0242:             */
0243:            public ChangeTypeRefactoring(ICompilationUnit cu,
0244:                    int selectionStart, int selectionLength, String selectedType) {
0245:                Assert.isTrue(selectionStart >= 0);
0246:                Assert.isTrue(selectionLength >= 0);
0247:
0248:                fSelectionStart = selectionStart;
0249:                fSelectionLength = selectionLength;
0250:
0251:                fEffectiveSelectionStart = selectionStart;
0252:                fEffectiveSelectionLength = selectionLength;
0253:
0254:                fCu = cu;
0255:
0256:                if (selectedType != null)
0257:                    fSelectedTypeName = selectedType;
0258:
0259:                fConstraintCache = new HashMap();
0260:                fValidTypes = new HashSet();
0261:            }
0262:
0263:            // ------------------------------------------------------------------------------------------------- //
0264:
0265:            /*
0266:             * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkActivation(org.eclipse.core.runtime.IProgressMonitor)
0267:             */
0268:            public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
0269:                    throws CoreException {
0270:                if (fCu == null || !fCu.isStructureKnown())
0271:                    return RefactoringStatus
0272:                            .createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_invalidSelection);
0273:                return checkSelection(new SubProgressMonitor(pm, 1));
0274:            }
0275:
0276:            private void setSelectionRanges(Expression exp) {
0277:                fEffectiveSelectionStart = exp.getStartPosition();
0278:                fEffectiveSelectionLength = exp.getLength();
0279:                fSelectionBinding = ExpressionVariable.resolveBinding(exp);
0280:                setOriginalType(exp.resolveTypeBinding());
0281:            }
0282:
0283:            /**
0284:             * Check if the right type of AST Node is selected. Create the TypeHierarchy needed to
0285:             * bring up the wizard.
0286:             */
0287:            private RefactoringStatus checkSelection(IProgressMonitor pm)
0288:                    throws JavaModelException {
0289:                try {
0290:                    pm.beginTask("", 5); //$NON-NLS-1$
0291:
0292:                    ASTNode node = getTargetNode(fCu, fSelectionStart,
0293:                            fSelectionLength);
0294:                    if (DEBUG) {
0295:                        System.out.println("selection: [" //$NON-NLS-1$
0296:                                + fSelectionStart
0297:                                + "," //$NON-NLS-1$
0298:                                + (fSelectionStart + fSelectionLength)
0299:                                + "] in " //$NON-NLS-1$
0300:                                + fCu.getElementName());
0301:                        System.out
0302:                                .println("node= " + node + ", type= " + node.getClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
0303:                    }
0304:
0305:                    TypeConstraintFactory typeConstraintFactory = new TypeConstraintFactory() {
0306:                        public boolean filter(ConstraintVariable v1,
0307:                                ConstraintVariable v2, ConstraintOperator o) {
0308:                            if (o.isStrictSubtypeOperator()) //TODO: explain why these can be excluded
0309:                                return true;
0310:                            //Don't create constraint if fSelectionTypeBinding is not involved:
0311:                            if (v1.getBinding() != null
0312:                                    && v2.getBinding() != null
0313:                                    && !Bindings.equals(v1.getBinding(),
0314:                                            fSelectionTypeBinding)
0315:                                    && !Bindings.equals(v2.getBinding(),
0316:                                            fSelectionTypeBinding)) {
0317:                                if (PRINT_STATS)
0318:                                    fNrFiltered++;
0319:                                return true;
0320:                            }
0321:                            return super .filter(v1, v2, o);
0322:                        }
0323:                    };
0324:                    fCollector = new ConstraintCollector(
0325:                            new FullConstraintCreator(
0326:                                    new ConstraintVariableFactory(),
0327:                                    typeConstraintFactory));
0328:                    String selectionValid = determineSelection(node);
0329:                    if (selectionValid != null) {
0330:                        if (DEBUG) {
0331:                            System.out
0332:                                    .println("invalid selection: " + selectionValid); //$NON-NLS-1$
0333:                        }
0334:                        return RefactoringStatus
0335:                                .createFatalErrorStatus(selectionValid);
0336:                    }
0337:
0338:                    if (fMethodBinding != null) {
0339:                        IMethod selectedMethod = (IMethod) fMethodBinding
0340:                                .getJavaElement();
0341:                        if (selectedMethod == null) {
0342:                            return RefactoringStatus
0343:                                    .createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_insideLocalTypesNotSupported);
0344:                        }
0345:                    }
0346:
0347:                    pm.worked(1);
0348:
0349:                    RefactoringStatus result = new RefactoringStatus();
0350:
0351:                    if (DEBUG) {
0352:                        System.out
0353:                                .println("fSelectionTypeBinding: " + fSelectionTypeBinding.getName()); //$NON-NLS-1$
0354:                    }
0355:
0356:                    // produce error message if array or primitive type is selected
0357:                    if (fSelectionTypeBinding.isArray()) {
0358:                        return RefactoringStatus
0359:                                .createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_arraysNotSupported);
0360:                    }
0361:                    if (fSelectionTypeBinding.isPrimitive()) {
0362:                        return RefactoringStatus
0363:                                .createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_primitivesNotSupported);
0364:                    }
0365:                    if (checkOverriddenBinaryMethods())
0366:                        return RefactoringStatus
0367:                                .createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnBinary);
0368:
0369:                    if (fSelectionTypeBinding.isLocal()) {
0370:                        return RefactoringStatus
0371:                                .createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_localTypesNotSupported);
0372:                    }
0373:
0374:                    if (fFieldBinding != null
0375:                            && fFieldBinding.getDeclaringClass().isLocal()) {
0376:                        return RefactoringStatus
0377:                                .createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_insideLocalTypesNotSupported);
0378:                    }
0379:
0380:                    if (fSelectionTypeBinding.isTypeVariable()) {
0381:                        return RefactoringStatus
0382:                                .createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_typeParametersNotSupported);
0383:                    }
0384:
0385:                    if (fSelectionTypeBinding.isEnum()) {
0386:                        return RefactoringStatus
0387:                                .createFatalErrorStatus(RefactoringCoreMessages.ChangeTypeRefactoring_enumsNotSupported);
0388:                    }
0389:
0390:                    pm.worked(1);
0391:
0392:                    if (fSelectedType != null) { // if invoked from unit test, compute valid types here
0393:                        computeValidTypes(new NullProgressMonitor());
0394:                    }
0395:                    return result;
0396:                } finally {
0397:                    pm.done();
0398:                }
0399:            }
0400:
0401:            private boolean checkOverriddenBinaryMethods()
0402:                    throws JavaModelException {
0403:                if (fMethodBinding != null) {
0404:                    Set declaringSupertypes = getDeclaringSuperTypes(fMethodBinding);
0405:                    for (Iterator iter = declaringSupertypes.iterator(); iter
0406:                            .hasNext();) {
0407:                        ITypeBinding super Type = (ITypeBinding) iter.next();
0408:                        IMethodBinding overriddenMethod = findMethod(
0409:                                fMethodBinding, super Type);
0410:                        Assert.isNotNull(overriddenMethod);//because we asked for declaring types
0411:                        IMethod iMethod = (IMethod) overriddenMethod
0412:                                .getJavaElement();
0413:                        if (iMethod.isBinary()) {
0414:                            return true;
0415:                        }
0416:                    }
0417:                }
0418:                return false;
0419:            }
0420:
0421:            // copied from FullConstraintCreator
0422:            private static IMethodBinding findMethod(
0423:                    IMethodBinding methodBinding, ITypeBinding type) {
0424:                if (methodBinding.getDeclaringClass().equals(type))
0425:                    return methodBinding;
0426:                return Bindings.findOverriddenMethodInType(type, methodBinding);
0427:            }
0428:
0429:            // copied from FullConstraintCreator
0430:            private static Set getDeclaringSuperTypes(
0431:                    IMethodBinding methodBinding) {
0432:                ITypeBinding[] allSuperTypes = Bindings
0433:                        .getAllSuperTypes(methodBinding.getDeclaringClass());
0434:                Set result = new HashSet();
0435:                for (int i = 0; i < allSuperTypes.length; i++) {
0436:                    ITypeBinding type = allSuperTypes[i];
0437:                    if (findMethod(methodBinding, type) != null)
0438:                        result.add(type);
0439:                }
0440:                return result;
0441:            }
0442:
0443:            /**
0444:             * Do the actual work of computing allowable types. Invoked by the wizard when
0445:             * "compute" button is pressed
0446:             */
0447:            public Collection/*<IType>*/computeValidTypes(IProgressMonitor pm) {
0448:
0449:                pm
0450:                        .beginTask(
0451:                                RefactoringCoreMessages.ChangeTypeRefactoring_checking_preconditions,
0452:                                100);
0453:
0454:                try {
0455:                    fCv = findConstraintVariableForSelectedNode(new SubProgressMonitor(
0456:                            pm, 3));
0457:                    if (DEBUG)
0458:                        System.out.println("selected CV: " + fCv + //$NON-NLS-1$
0459:                                " (" + fCv.getClass().getName() + //$NON-NLS-1$
0460:                                ")"); //$NON-NLS-1$
0461:
0462:                    if (pm.isCanceled())
0463:                        throw new OperationCanceledException();
0464:                    fRelevantVars = findRelevantConstraintVars(fCv,
0465:                            new SubProgressMonitor(pm, 50));
0466:
0467:                    if (DEBUG)
0468:                        printCollection("relevant vars:", fRelevantVars); //$NON-NLS-1$
0469:
0470:                    if (pm.isCanceled())
0471:                        throw new OperationCanceledException();
0472:                    fRelevantConstraints = findRelevantConstraints(
0473:                            fRelevantVars, new SubProgressMonitor(pm, 30));
0474:
0475:                    if (pm.isCanceled())
0476:                        throw new OperationCanceledException();
0477:                    fValidTypes.addAll(computeValidTypes(fSelectionTypeBinding,
0478:                            fRelevantVars, fRelevantConstraints,
0479:                            new SubProgressMonitor(pm, 20)));
0480:
0481:                    if (DEBUG)
0482:                        printCollection("valid types:", getValidTypeNames()); //$NON-NLS-1$
0483:                } catch (CoreException e) {
0484:                    JavaPlugin
0485:                            .logErrorMessage("Error occurred during computation of valid types: " + e.toString()); //$NON-NLS-1$ 
0486:                    fValidTypes.clear(); // error occurred during computation of valid types
0487:                }
0488:
0489:                pm.done();
0490:
0491:                return fValidTypes;
0492:            }
0493:
0494:            /*
0495:             * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkInput(org.eclipse.core.runtime.IProgressMonitor)
0496:             */
0497:            public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
0498:                    throws CoreException {
0499:                pm
0500:                        .beginTask(
0501:                                RefactoringCoreMessages.ChangeTypeRefactoring_checking_preconditions,
0502:                                1);
0503:
0504:                RefactoringStatus result = Checks.validateModifiesFiles(
0505:                        ResourceUtil.getFiles(fAffectedUnits),
0506:                        getValidationContext());
0507:
0508:                pm.done();
0509:                return result;
0510:            }
0511:
0512:            // TODO: do sanity check somewhere if the refactoring changes any files.
0513:            /*
0514:             * @see org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring#createChange(org.eclipse.core.runtime.IProgressMonitor)
0515:             */
0516:            public Change createChange(IProgressMonitor pm)
0517:                    throws CoreException {
0518:                pm
0519:                        .beginTask(
0520:                                RefactoringCoreMessages.ChangeTypeMessages_CreateChangesForChangeType,
0521:                                1);
0522:                try {
0523:                    Map/* <ICompilationUnit,Set<ConstraintVariable>> */relevantVarsByUnit = new HashMap/* <ICompilationUnit,HashSet<ConstraintVariable>> */();
0524:                    groupChangesByCompilationUnit(relevantVarsByUnit);
0525:                    final Map arguments = new HashMap();
0526:                    String project = null;
0527:                    IJavaProject javaProject = fCu.getJavaProject();
0528:                    if (javaProject != null)
0529:                        project = javaProject.getElementName();
0530:                    final String description = RefactoringCoreMessages.ChangeTypeRefactoring_descriptor_description_short;
0531:                    final String header = Messages
0532:                            .format(
0533:                                    RefactoringCoreMessages.ChangeTypeRefactoring_descriptor_description,
0534:                                    new String[] {
0535:                                            BindingLabelProvider
0536:                                                    .getBindingLabel(
0537:                                                            fSelectionBinding,
0538:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED),
0539:                                            BindingLabelProvider
0540:                                                    .getBindingLabel(
0541:                                                            fSelectedType,
0542:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED) });
0543:                    final JDTRefactoringDescriptorComment comment = new JDTRefactoringDescriptorComment(
0544:                            project, this , header);
0545:                    comment
0546:                            .addSetting(Messages
0547:                                    .format(
0548:                                            RefactoringCoreMessages.ChangeTypeRefactoring_original_element_pattern,
0549:                                            BindingLabelProvider
0550:                                                    .getBindingLabel(
0551:                                                            fSelectionBinding,
0552:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED)));
0553:                    comment
0554:                            .addSetting(Messages
0555:                                    .format(
0556:                                            RefactoringCoreMessages.ChangeTypeRefactoring_original_type_pattern,
0557:                                            BindingLabelProvider
0558:                                                    .getBindingLabel(
0559:                                                            getOriginalType(),
0560:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED)));
0561:                    comment
0562:                            .addSetting(Messages
0563:                                    .format(
0564:                                            RefactoringCoreMessages.ChangeTypeRefactoring_refactored_type_pattern,
0565:                                            BindingLabelProvider
0566:                                                    .getBindingLabel(
0567:                                                            fSelectedType,
0568:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED)));
0569:                    final GeneralizeTypeDescriptor descriptor = new GeneralizeTypeDescriptor(
0570:                            project,
0571:                            description,
0572:                            comment.asString(),
0573:                            arguments,
0574:                            (RefactoringDescriptor.STRUCTURAL_CHANGE
0575:                                    | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT));
0576:                    arguments.put(
0577:                            JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT,
0578:                            JavaRefactoringDescriptorUtil.elementToHandle(
0579:                                    project, fCu));
0580:                    arguments
0581:                            .put(
0582:                                    JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION,
0583:                                    new Integer(fSelectionStart).toString()
0584:                                            + " " + new Integer(fSelectionLength).toString()); //$NON-NLS-1$
0585:                    arguments.put(ATTRIBUTE_TYPE, fSelectedType
0586:                            .getQualifiedName());
0587:                    final DynamicValidationRefactoringChange result = new DynamicValidationRefactoringChange(
0588:                            descriptor,
0589:                            RefactoringCoreMessages.ChangeTypeRefactoring_allChanges);
0590:                    for (Iterator/* <ICompilationUnit> */it = relevantVarsByUnit
0591:                            .keySet().iterator(); it.hasNext();) {
0592:                        ICompilationUnit icu = (ICompilationUnit) it.next();
0593:                        Set/* <ConstraintVariable> */cVars = (Set) relevantVarsByUnit
0594:                                .get(icu);
0595:                        CompilationUnitChange cuChange = new CompilationUnitChange(
0596:                                getName(), icu);
0597:                        addAllChangesFor(icu, cVars, cuChange);
0598:                        result.add(cuChange);
0599:                        pm.worked(1);
0600:                        if (pm.isCanceled())
0601:                            throw new OperationCanceledException();
0602:                    }
0603:                    return result;
0604:                } finally {
0605:                    pm.done();
0606:                }
0607:            }
0608:
0609:            /**
0610:             * Apply all changes related to a single ICompilationUnit
0611:             */
0612:            private void addAllChangesFor(ICompilationUnit icu, Set vars,
0613:                    CompilationUnitChange unitChange) throws CoreException {
0614:                CompilationUnit unit = new RefactoringASTParser(AST.JLS3)
0615:                        .parse(icu, false);
0616:                ASTRewrite unitRewriter = ASTRewrite.create(unit.getAST());
0617:                MultiTextEdit root = new MultiTextEdit();
0618:                unitChange.setEdit(root); // Adam sez don't need this, but then unitChange.addGroupDescription() fails an assertion!
0619:
0620:                String typeName = updateImports(unit, root);
0621:                updateCu(unit, vars, unitChange, unitRewriter, typeName);
0622:                root.addChild(unitRewriter.rewriteAST());
0623:            }
0624:
0625:            private class SourceRangeComputer extends TargetSourceRangeComputer {
0626:                public SourceRange computeSourceRange(ASTNode node) {
0627:                    return new SourceRange(node.getStartPosition(), node
0628:                            .getLength());
0629:                }
0630:            }
0631:
0632:            private void updateCu(CompilationUnit unit, Set vars,
0633:                    CompilationUnitChange unitChange, ASTRewrite unitRewriter,
0634:                    String typeName) throws JavaModelException {
0635:
0636:                // use custom SourceRangeComputer to avoid losing comments
0637:                unitRewriter
0638:                        .setTargetSourceRangeComputer(new SourceRangeComputer());
0639:
0640:                for (Iterator it = vars.iterator(); it.hasNext();) {
0641:                    ConstraintVariable cv = (ConstraintVariable) it.next();
0642:                    ASTNode decl = findDeclaration(unit, cv);
0643:                    if ((decl instanceof  SimpleName || decl instanceof  QualifiedName)
0644:                            && cv instanceof  ExpressionVariable) {
0645:                        ASTNode gp = decl.getParent().getParent();
0646:                        updateType(unit, getType(gp), unitChange, unitRewriter,
0647:                                typeName); // local variable or parameter
0648:                    } else if (decl instanceof  MethodDeclaration
0649:                            || decl instanceof  FieldDeclaration) {
0650:                        updateType(unit, getType(decl), unitChange,
0651:                                unitRewriter, typeName); // method return or field type
0652:                    } else if (decl instanceof  ParameterizedType) {
0653:                        updateType(unit, getType(decl), unitChange,
0654:                                unitRewriter, typeName);
0655:                    }
0656:                }
0657:            }
0658:
0659:            private void updateType(CompilationUnit cu, Type oldType,
0660:                    CompilationUnitChange unitChange, ASTRewrite unitRewriter,
0661:                    String typeName) {
0662:
0663:                String oldName = fSelectionTypeBinding.getName();
0664:                String description = Messages
0665:                        .format(
0666:                                RefactoringCoreMessages.ChangeTypeRefactoring_typeChange,
0667:                                new String[] { oldName, typeName });
0668:                TextEditGroup gd = new TextEditGroup(description);
0669:                AST ast = cu.getAST();
0670:
0671:                ASTNode nodeToReplace = oldType;
0672:                if (fSelectionTypeBinding.isParameterizedType()
0673:                        && !fSelectionTypeBinding.isRawType()) {
0674:                    if (oldType.isSimpleType()) {
0675:                        nodeToReplace = oldType.getParent();
0676:                    }
0677:                }
0678:
0679:                //TODO handle types other than simple & parameterized (e.g., arrays)
0680:                Assert.isTrue(fSelectedType.isClass()
0681:                        || fSelectedType.isInterface());
0682:
0683:                Type newType = null;
0684:                if (!fSelectedType.isParameterizedType()) {
0685:                    newType = ast.newSimpleType(ASTNodeFactory.newName(ast,
0686:                            typeName));
0687:                } else {
0688:                    newType = createParameterizedType(ast, fSelectedType);
0689:                }
0690:
0691:                unitRewriter.replace(nodeToReplace, newType, gd);
0692:                unitChange.addTextEditGroup(gd);
0693:            }
0694:
0695:            /**
0696:             * Creates the appropriate ParameterizedType node. Recursion is needed to
0697:             * handle the nested case (e.g., Vector<Vector<String>>).
0698:             */
0699:            private Type createParameterizedType(AST ast,
0700:                    ITypeBinding typeBinding) {
0701:                if (typeBinding.isParameterizedType()
0702:                        && !typeBinding.isRawType()) {
0703:                    Type baseType = ast.newSimpleType(ASTNodeFactory.newName(
0704:                            ast, typeBinding.getErasure().getName()));
0705:                    ParameterizedType newType = ast
0706:                            .newParameterizedType(baseType);
0707:                    for (int i = 0; i < typeBinding.getTypeArguments().length; i++) {
0708:                        ITypeBinding typeArg = typeBinding.getTypeArguments()[i];
0709:                        Type argType = createParameterizedType(ast, typeArg); // recursive call
0710:                        newType.typeArguments().add(argType);
0711:                    }
0712:                    return newType;
0713:                } else {
0714:                    if (!typeBinding.isTypeVariable()) {
0715:                        return ast.newSimpleType(ASTNodeFactory.newName(ast,
0716:                                typeBinding.getErasure().getName()));
0717:                    } else {
0718:                        return ast.newSimpleType(ast.newSimpleName(typeBinding
0719:                                .getName()));
0720:                    }
0721:                }
0722:            }
0723:
0724:            private void groupChangesByCompilationUnit(Map relevantVarsByUnit)
0725:                    throws JavaModelException {
0726:                for (Iterator it = fRelevantVars.iterator(); it.hasNext();) {
0727:                    ConstraintVariable cv = (ConstraintVariable) it.next();
0728:                    if (!(cv instanceof  ExpressionVariable)
0729:                            && !(cv instanceof  ReturnTypeVariable)) {
0730:                        continue;
0731:                    }
0732:                    ICompilationUnit icu = null;
0733:                    if (cv instanceof  ExpressionVariable) {
0734:                        ExpressionVariable ev = (ExpressionVariable) cv;
0735:                        icu = ev.getCompilationUnitRange().getCompilationUnit();
0736:                    } else if (cv instanceof  ReturnTypeVariable) {
0737:                        ReturnTypeVariable rtv = (ReturnTypeVariable) cv;
0738:                        IMethodBinding mb = rtv.getMethodBinding();
0739:                        icu = ((IMethod) mb.getJavaElement())
0740:                                .getCompilationUnit();
0741:                    }
0742:                    if (!relevantVarsByUnit.containsKey(icu)) {
0743:                        relevantVarsByUnit.put(icu,
0744:                                new HashSet/*<ConstraintVariable>*/());
0745:                    }
0746:                    ((Set) relevantVarsByUnit.get(icu)).add(cv);
0747:                }
0748:            }
0749:
0750:            private ASTNode findDeclaration(CompilationUnit root,
0751:                    ConstraintVariable cv) throws JavaModelException {
0752:
0753:                if (fFieldBinding != null) {
0754:                    IField f = (IField) fFieldBinding.getJavaElement();
0755:                    return ASTNodeSearchUtil.getFieldDeclarationNode(f, root);
0756:                }
0757:
0758:                if (cv instanceof  ExpressionVariable) {
0759:                    for (Iterator iter = fAllConstraints.iterator(); iter
0760:                            .hasNext();) {
0761:                        ITypeConstraint constraint = (ITypeConstraint) iter
0762:                                .next();
0763:                        if (constraint.isSimpleTypeConstraint()) {
0764:                            SimpleTypeConstraint stc = (SimpleTypeConstraint) constraint;
0765:                            if (stc.isDefinesConstraint()
0766:                                    && stc.getLeft().equals(cv)) {
0767:                                ConstraintVariable right = stc.getRight();
0768:                                if (right instanceof  TypeVariable) {
0769:                                    TypeVariable typeVariable = (TypeVariable) right;
0770:                                    return NodeFinder.perform(root,
0771:                                            typeVariable
0772:                                                    .getCompilationUnitRange()
0773:                                                    .getSourceRange());
0774:                                }
0775:                            }
0776:                        }
0777:                    }
0778:                } else if (cv instanceof  ReturnTypeVariable) {
0779:                    ReturnTypeVariable rtv = (ReturnTypeVariable) cv;
0780:                    IMethodBinding mb = rtv.getMethodBinding();
0781:                    IMethod im = (IMethod) mb.getJavaElement();
0782:                    return ASTNodeSearchUtil.getMethodDeclarationNode(im, root);
0783:                }
0784:                return null;
0785:            }
0786:
0787:            private static Type getType(ASTNode node) {
0788:                switch (node.getNodeType()) {
0789:                case ASTNode.SINGLE_VARIABLE_DECLARATION:
0790:                    return ((SingleVariableDeclaration) node).getType();
0791:                case ASTNode.FIELD_DECLARATION:
0792:                    return ((FieldDeclaration) node).getType();
0793:                case ASTNode.VARIABLE_DECLARATION_STATEMENT:
0794:                    return ((VariableDeclarationStatement) node).getType();
0795:                case ASTNode.METHOD_DECLARATION:
0796:                    return ((MethodDeclaration) node).getReturnType2();
0797:                case ASTNode.PARAMETERIZED_TYPE:
0798:                    return ((ParameterizedType) node).getType();
0799:                default:
0800:                    Assert.isTrue(false);
0801:                    return null;
0802:                }
0803:            }
0804:
0805:            /*
0806:             * @see org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring#getName()
0807:             */
0808:            public String getName() {
0809:                return RefactoringCoreMessages.ChangeTypeRefactoring_name;
0810:            }
0811:
0812:            // ------------------------------------------------------------------------------------------------- //
0813:            // Method for examining if a suitable kind of ASTNode was selected. Information about this node and
0814:            // its parents in the AST are stored in fields fBinding, theMethod, and theField
0815:
0816:            /**
0817:             * Determines what kind of ASTNode has been selected. A non-null String containing an error message
0818:             * is returned if the ChangeTypeRefactoring refactoring cannot be applied to the selected ASTNode.
0819:             * A return value of null indicates a valid selection.  
0820:             */
0821:            private String determineSelection(ASTNode node) {
0822:                if (node == null) {
0823:                    return RefactoringCoreMessages.ChangeTypeRefactoring_invalidSelection;
0824:                } else {
0825:
0826:                    if (DEBUG)
0827:                        System.out
0828:                                .println("node nodeType= " + node.getClass().getName()); //$NON-NLS-1$
0829:                    if (DEBUG)
0830:                        System.out
0831:                                .println("parent nodeType= " + node.getParent().getClass().getName()); //$NON-NLS-1$
0832:                    if (DEBUG)
0833:                        System.out
0834:                                .println("GrandParent nodeType= " + node.getParent().getParent().getClass().getName()); //$NON-NLS-1$
0835:
0836:                    ASTNode parent = node.getParent();
0837:                    ASTNode grandParent = parent.getParent();
0838:                    if (grandParent == null)
0839:                        return nodeTypeNotSupported();
0840:
0841:                    // adjustment needed if part of a parameterized type is selected
0842:                    if (grandParent.getNodeType() == ASTNode.PARAMETERIZED_TYPE) {
0843:                        node = grandParent;
0844:                    }
0845:
0846:                    // adjustment needed if part of a qualified name is selected
0847:                    ASTNode current = null;
0848:                    if (node.getNodeType() == ASTNode.QUALIFIED_NAME) {
0849:                        current = node;
0850:                        while (current.getNodeType() == ASTNode.QUALIFIED_NAME) {
0851:                            current = current.getParent();
0852:                        }
0853:                        if (current.getNodeType() != ASTNode.SIMPLE_TYPE) {
0854:                            return nodeTypeNotSupported();
0855:                        }
0856:                        node = current.getParent();
0857:                    } else if (parent.getNodeType() == ASTNode.QUALIFIED_NAME) {
0858:                        current = parent;
0859:                        while (current.getNodeType() == ASTNode.QUALIFIED_NAME) {
0860:                            current = current.getParent();
0861:                        }
0862:                        if (current.getNodeType() != ASTNode.SIMPLE_TYPE) {
0863:                            return nodeTypeNotSupported();
0864:                        }
0865:                        node = current.getParent();
0866:                    }
0867:
0868:                    fObject = node.getAST().resolveWellKnownType(
0869:                            "java.lang.Object"); //$NON-NLS-1$
0870:                    switch (node.getNodeType()) {
0871:                    case ASTNode.SIMPLE_NAME:
0872:                        return simpleNameSelected((SimpleName) node);
0873:                    case ASTNode.VARIABLE_DECLARATION_STATEMENT:
0874:                        return variableDeclarationStatementSelected((VariableDeclarationStatement) node);
0875:                    case ASTNode.FIELD_DECLARATION:
0876:                        return fieldDeclarationSelected((FieldDeclaration) node);
0877:                    case ASTNode.SINGLE_VARIABLE_DECLARATION:
0878:                        return singleVariableDeclarationSelected((SingleVariableDeclaration) node);
0879:                    case ASTNode.PARAMETERIZED_TYPE:
0880:                        return parameterizedTypeSelected((ParameterizedType) node);
0881:                    default:
0882:                        return nodeTypeNotSupported();
0883:                    }
0884:                }
0885:            }
0886:
0887:            /**
0888:             * The selection corresponds to an ASTNode on which "ChangeTypeRefactoring" is not defined.
0889:             */
0890:            private static String nodeTypeNotSupported() {
0891:                return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType;
0892:            }
0893:
0894:            /**
0895:             * The selection corresponds to a SingleVariableDeclaration
0896:             */
0897:            private String singleVariableDeclarationSelected(
0898:                    SingleVariableDeclaration svd) {
0899:                SimpleName name = svd.getName();
0900:                setSelectionRanges(name);
0901:                return simpleNameSelected(name);
0902:            }
0903:
0904:            /**
0905:             * The selection corresponds to a ParameterizedType (return type of method)
0906:             */
0907:            private String parameterizedTypeSelected(ParameterizedType pt) {
0908:                ASTNode parent = pt.getParent();
0909:                if (parent.getNodeType() == ASTNode.METHOD_DECLARATION) {
0910:                    fMethodBinding = ((MethodDeclaration) parent)
0911:                            .resolveBinding();
0912:                    fParamIndex = -1;
0913:                    fEffectiveSelectionStart = pt.getStartPosition();
0914:                    fEffectiveSelectionLength = pt.getLength();
0915:                    setOriginalType(pt.resolveBinding());
0916:                } else if (parent.getNodeType() == ASTNode.SINGLE_VARIABLE_DECLARATION) {
0917:                    return singleVariableDeclarationSelected((SingleVariableDeclaration) parent);
0918:                } else if (parent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT) {
0919:                    return variableDeclarationStatementSelected((VariableDeclarationStatement) parent);
0920:                } else if (parent.getNodeType() == ASTNode.FIELD_DECLARATION) {
0921:                    return fieldDeclarationSelected((FieldDeclaration) parent);
0922:                } else {
0923:                    return nodeTypeNotSupported();
0924:                }
0925:                return null;
0926:            }
0927:
0928:            /**
0929:             * The selection corresponds to a VariableDeclarationStatement
0930:             */
0931:            private String variableDeclarationStatementSelected(
0932:                    VariableDeclarationStatement vds) {
0933:                if (vds.fragments().size() != 1) {
0934:                    return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
0935:                } else {
0936:                    VariableDeclarationFragment elem = (VariableDeclarationFragment) vds
0937:                            .fragments().iterator().next();
0938:                    SimpleName name = elem.getName();
0939:                    setSelectionRanges(name);
0940:                    return simpleNameSelected(name);
0941:                }
0942:            }
0943:
0944:            /**
0945:             * The selection corresponds to a FieldDeclaration
0946:             */
0947:            private String fieldDeclarationSelected(
0948:                    FieldDeclaration fieldDeclaration) {
0949:                if (fieldDeclaration.fragments().size() != 1) {
0950:                    return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
0951:                } else {
0952:                    VariableDeclarationFragment elem = (VariableDeclarationFragment) fieldDeclaration
0953:                            .fragments().iterator().next();
0954:                    fFieldBinding = elem.resolveBinding();
0955:                    SimpleName name = elem.getName();
0956:                    setSelectionRanges(name);
0957:                    return simpleNameSelected(name);
0958:                }
0959:            }
0960:
0961:            /**
0962:             * The selection corresponds to a SimpleName
0963:             */
0964:            private String simpleNameSelected(SimpleName simpleName) {
0965:                ASTNode parent = simpleName.getParent();
0966:                ASTNode grandParent = parent.getParent();
0967:
0968:                if (parent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT) {
0969:                    VariableDeclarationStatement vds = (VariableDeclarationStatement) parent;
0970:                    if (vds.fragments().size() > 1) {
0971:                        return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
0972:                    }
0973:                } else if (parent.getNodeType() == ASTNode.VARIABLE_DECLARATION_FRAGMENT) {
0974:                    if (grandParent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT) {
0975:                        VariableDeclarationStatement vds = (VariableDeclarationStatement) grandParent;
0976:                        if (vds.fragments().size() > 1) {
0977:                            return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
0978:                        }
0979:                        setSelectionRanges(simpleName);
0980:                    } else if (grandParent.getNodeType() == ASTNode.VARIABLE_DECLARATION_EXPRESSION) {
0981:                        VariableDeclarationExpression vde = (VariableDeclarationExpression) grandParent;
0982:                        if (vde.fragments().size() > 1) {
0983:                            return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
0984:                        }
0985:                        setSelectionRanges(simpleName);
0986:                    } else if (grandParent.getNodeType() == ASTNode.FIELD_DECLARATION) {
0987:                        FieldDeclaration fd = (FieldDeclaration) grandParent;
0988:                        if (fd.fragments().size() > 1) {
0989:                            return RefactoringCoreMessages.ChangeTypeRefactoring_multiDeclarationsNotSupported;
0990:                        }
0991:                        VariableDeclarationFragment fragment = (VariableDeclarationFragment) parent;
0992:                        fFieldBinding = fragment.resolveBinding();
0993:                        setSelectionRanges(fragment.getName());
0994:                    } else {
0995:                        return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType;
0996:                    }
0997:                } else if (parent.getNodeType() == ASTNode.SINGLE_VARIABLE_DECLARATION) {
0998:                    SingleVariableDeclaration singleVariableDeclaration = (SingleVariableDeclaration) parent;
0999:                    if ((grandParent.getNodeType() == ASTNode.METHOD_DECLARATION)) {
1000:                        fMethodBinding = ((MethodDeclaration) grandParent)
1001:                                .resolveBinding();
1002:                        setOriginalType(simpleName.resolveTypeBinding());
1003:                        fParamIndex = ((MethodDeclaration) grandParent)
1004:                                .parameters().indexOf(parent);
1005:                        fParamName = singleVariableDeclaration.getName()
1006:                                .getIdentifier();
1007:                    } else {
1008:                        setSelectionRanges(singleVariableDeclaration.getName());
1009:                    }
1010:                } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE
1011:                        && (grandParent.getNodeType() == ASTNode.SINGLE_VARIABLE_DECLARATION)) {
1012:                    ASTNode greatGrandParent = grandParent.getParent();
1013:                    SingleVariableDeclaration singleVariableDeclaration = (SingleVariableDeclaration) grandParent;
1014:                    if (singleVariableDeclaration.getExtraDimensions() > 0) {
1015:                        return RefactoringCoreMessages.ChangeTypeRefactoring_arraysNotSupported;
1016:                    }
1017:                    if (greatGrandParent != null
1018:                            && greatGrandParent.getNodeType() == ASTNode.METHOD_DECLARATION) {
1019:                        fMethodBinding = ((MethodDeclaration) greatGrandParent)
1020:                                .resolveBinding();
1021:                        fParamIndex = ((MethodDeclaration) greatGrandParent)
1022:                                .parameters().indexOf(grandParent);
1023:                        fParamName = singleVariableDeclaration.getName()
1024:                                .getIdentifier();
1025:                        setSelectionRanges(simpleName);
1026:                    } else {
1027:                        setSelectionRanges(singleVariableDeclaration.getName());
1028:                    }
1029:                } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE
1030:                        && grandParent.getNodeType() == ASTNode.METHOD_DECLARATION) {
1031:                    fMethodBinding = ((MethodDeclaration) grandParent)
1032:                            .resolveBinding();
1033:                    setOriginalType(fMethodBinding.getReturnType());
1034:                    fParamIndex = -1;
1035:                } else if (parent.getNodeType() == ASTNode.METHOD_DECLARATION
1036:                        && grandParent.getNodeType() == ASTNode.TYPE_DECLARATION) {
1037:                    MethodDeclaration methodDeclaration = (MethodDeclaration) parent;
1038:                    if (methodDeclaration.getName().equals(simpleName)
1039:                            || methodDeclaration.thrownExceptions().contains(
1040:                                    simpleName)) {
1041:                        return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType;
1042:                    }
1043:                    fMethodBinding = ((MethodDeclaration) parent)
1044:                            .resolveBinding();
1045:                    fParamIndex = -1;
1046:                } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE
1047:                        && (grandParent.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT)) {
1048:                    return variableDeclarationStatementSelected((VariableDeclarationStatement) grandParent);
1049:                } else if (parent.getNodeType() == ASTNode.CAST_EXPRESSION) {
1050:                    ASTNode decl = findDeclaration(parent.getRoot(),
1051:                            fSelectionStart, fSelectionLength + 1);
1052:                    VariableDeclarationFragment fragment = (VariableDeclarationFragment) decl;
1053:                    SimpleName name = fragment.getName();
1054:                    setSelectionRanges(name);
1055:                } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE
1056:                        && grandParent.getNodeType() == ASTNode.FIELD_DECLARATION) {
1057:                    return fieldDeclarationSelected((FieldDeclaration) grandParent);
1058:                } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE
1059:                        && grandParent.getNodeType() == ASTNode.ARRAY_TYPE) {
1060:                    return RefactoringCoreMessages.ChangeTypeRefactoring_arraysNotSupported;
1061:                } else if (parent.getNodeType() == ASTNode.QUALIFIED_NAME) {
1062:                    setSelectionRanges(simpleName);
1063:                } else {
1064:                    return RefactoringCoreMessages.ChangeTypeRefactoring_notSupportedOnNodeType;
1065:                }
1066:                return null;
1067:            }
1068:
1069:            // ------------------------------------------------------------------------------------------------- //
1070:            // Methods for examining & solving type constraints. This includes:
1071:            //  (1) locating the ConstraintVariable corresponding to the selected ASTNode
1072:            //  (2) finding all ConstraintVariables "related" to (1) via overriding, method calls, field access
1073:            //  (3) find all ITypeConstraints of interest that mention ConstraintVariables in (2)
1074:            //  (4) determining all ITypes for which the ITypeConstraints in (3) are satisfied
1075:
1076:            /**
1077:             * Find a ConstraintVariable that corresponds to the selected ASTNode.
1078:             */
1079:            private ConstraintVariable findConstraintVariableForSelectedNode(
1080:                    IProgressMonitor pm) {
1081:                pm
1082:                        .beginTask(
1083:                                RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage,
1084:                                100);
1085:                ICompilationUnit[] cus = { fCu }; // only search in CU containing selection
1086:
1087:                if (DEBUG) {
1088:                    System.out
1089:                            .println("Effective selection: " + fEffectiveSelectionStart + "/" + fEffectiveSelectionLength); //$NON-NLS-1$ //$NON-NLS-2$
1090:                }
1091:
1092:                Collection/*<ITypeConstraint>*/allConstraints = getConstraints(
1093:                        cus, new SubProgressMonitor(pm, 50));
1094:
1095:                IProgressMonitor subMonitor = new SubProgressMonitor(pm, 50);
1096:                subMonitor
1097:                        .beginTask(
1098:                                RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage,
1099:                                allConstraints.size());
1100:                for (Iterator it = allConstraints.iterator(); it.hasNext();) {
1101:                    subMonitor.worked(1);
1102:                    ITypeConstraint tc = (ITypeConstraint) it.next();
1103:                    if (!(tc instanceof  SimpleTypeConstraint))
1104:                        continue;
1105:                    SimpleTypeConstraint stc = (SimpleTypeConstraint) tc;
1106:                    if (matchesSelection(stc.getLeft()))
1107:                        return stc.getLeft();
1108:                    if (matchesSelection(stc.getRight()))
1109:                        return stc.getRight();
1110:                }
1111:                subMonitor.done();
1112:                pm.done();
1113:                Assert
1114:                        .isTrue(
1115:                                false,
1116:                                RefactoringCoreMessages.ChangeTypeRefactoring_noMatchingConstraintVariable);
1117:                return null;
1118:            }
1119:
1120:            /**
1121:             * Determine if a given ConstraintVariable matches the selected ASTNode.
1122:             */
1123:            private boolean matchesSelection(ConstraintVariable cv) {
1124:                if (cv instanceof  ExpressionVariable) {
1125:                    ExpressionVariable ev = (ExpressionVariable) cv;
1126:                    return (fSelectionBinding != null && Bindings.equals(
1127:                            fSelectionBinding, ev.getExpressionBinding()));
1128:                } else if (cv instanceof  ParameterTypeVariable) {
1129:                    ParameterTypeVariable ptv = (ParameterTypeVariable) cv;
1130:                    if (fMethodBinding != null
1131:                            && Bindings.equals(ptv.getMethodBinding(),
1132:                                    fMethodBinding)
1133:                            && ptv.getParameterIndex() == fParamIndex) {
1134:                        return true;
1135:                    }
1136:                } else if (cv instanceof  ReturnTypeVariable) {
1137:                    ReturnTypeVariable rtv = (ReturnTypeVariable) cv;
1138:                    if (fMethodBinding != null
1139:                            && Bindings.equals(rtv.getMethodBinding(),
1140:                                    fMethodBinding) && fParamIndex == -1) {
1141:                        return true;
1142:                    }
1143:                }
1144:                return false;
1145:            }
1146:
1147:            /**
1148:             * Determine the set of constraint variables related to the selected
1149:             * expression. In addition to the expression itself, this consists of
1150:             * any expression that is defines-equal to it, and any expression equal
1151:             * to it. 
1152:             */
1153:            private Collection/*<ConstraintVariable>*/findRelevantConstraintVars(
1154:                    ConstraintVariable cv, IProgressMonitor pm)
1155:                    throws CoreException {
1156:                pm
1157:                        .beginTask(
1158:                                RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage,
1159:                                150);
1160:                Collection/*<ConstraintVariable>*/result = new HashSet();
1161:                result.add(cv);
1162:                ICompilationUnit[] cus = collectAffectedUnits(new SubProgressMonitor(
1163:                        pm, 50));
1164:                Collection/*<ITypeConstraint>*/allConstraints = getConstraints(
1165:                        cus, new SubProgressMonitor(pm, 50));
1166:
1167:                List/*<ConstraintVariable>*/workList = new ArrayList(result);
1168:                while (!workList.isEmpty()) {
1169:
1170:                    pm.worked(10);
1171:
1172:                    ConstraintVariable first = (ConstraintVariable) workList
1173:                            .remove(0);
1174:                    for (Iterator iter = allConstraints.iterator(); iter
1175:                            .hasNext();) {
1176:                        pm.worked(1);
1177:                        ITypeConstraint typeConstraint = (ITypeConstraint) iter
1178:                                .next();
1179:                        if (!typeConstraint.isSimpleTypeConstraint())
1180:                            continue;
1181:                        SimpleTypeConstraint stc = (SimpleTypeConstraint) typeConstraint;
1182:                        if (!stc.isDefinesConstraint()
1183:                                && !stc.isEqualsConstraint())
1184:                            continue;
1185:                        ConstraintVariable match = match(first, stc.getLeft(),
1186:                                stc.getRight());
1187:                        if (match instanceof  ExpressionVariable
1188:                                || match instanceof  ParameterTypeVariable
1189:                                || match instanceof  ReturnTypeVariable) {
1190:                            if (!result.contains(match)) {
1191:                                workList.add(match);
1192:                                result.add(match);
1193:                            }
1194:                        }
1195:                    }
1196:                }
1197:
1198:                pm.done();
1199:
1200:                return result;
1201:            }
1202:
1203:            private static ConstraintVariable match(ConstraintVariable matchee,
1204:                    ConstraintVariable left, ConstraintVariable right) {
1205:                if (matchee.equals(left))
1206:                    return right;
1207:                if (matchee.equals(right))
1208:                    return left;
1209:                return null;
1210:            }
1211:
1212:            /**
1213:             * Select the type constraints that involve the selected ASTNode.
1214:             */
1215:            private Collection/*<ITypeConstraint>*/findRelevantConstraints(
1216:                    Collection/*<ConstraintVariable>*/relevantConstraintVars,
1217:                    IProgressMonitor pm) throws CoreException {
1218:
1219:                ICompilationUnit[] cus = collectAffectedUnits(new SubProgressMonitor(
1220:                        pm, 100));
1221:
1222:                fAllConstraints = getConstraints(cus, new SubProgressMonitor(
1223:                        pm, 900));
1224:
1225:                pm
1226:                        .beginTask(
1227:                                RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage,
1228:                                1000 + fAllConstraints.size());
1229:
1230:                if (DEBUG)
1231:                    printCollection("type constraints: ", fAllConstraints); //$NON-NLS-1$
1232:                Collection/*<ITypeConstraint>*/result = new ArrayList();
1233:                for (Iterator it = fAllConstraints.iterator(); it.hasNext();) {
1234:                    ITypeConstraint tc = (ITypeConstraint) it.next();
1235:                    if (tc.isSimpleTypeConstraint()) {
1236:                        SimpleTypeConstraint stc = (SimpleTypeConstraint) tc;
1237:                        if (stc.isDefinesConstraint()
1238:                                || stc.isEqualsConstraint())
1239:                            continue;
1240:                        if (stc.getLeft().equals(stc.getRight()))
1241:                            continue;
1242:                        if (isNull(stc.getLeft()))
1243:                            continue;
1244:                        if (relevantConstraintVars.contains(stc.getLeft())
1245:                                || relevantConstraintVars.contains(stc
1246:                                        .getRight()))
1247:                            result.add(tc);
1248:                    } else {
1249:                        CompositeOrTypeConstraint cotc = (CompositeOrTypeConstraint) tc;
1250:                        ITypeConstraint[] components = cotc.getConstraints();
1251:                        for (int i = 0; i < components.length; i++) {
1252:                            ITypeConstraint component = components[i];
1253:                            SimpleTypeConstraint simpleComponent = (SimpleTypeConstraint) component;
1254:                            if (relevantConstraintVars.contains(simpleComponent
1255:                                    .getLeft()))
1256:                                result.add(tc);
1257:                        }
1258:                    }
1259:                    pm.worked(1);
1260:                }
1261:                if (DEBUG)
1262:                    printCollection("selected constraints: ", result); //$NON-NLS-1$
1263:                pm.done();
1264:                return result;
1265:            }
1266:
1267:            /**
1268:             * Finds the declaration of the ASTNode in a given AST at a specified offset and with a specified length
1269:             */
1270:            private static ASTNode findDeclaration(final ASTNode root,
1271:                    final int start, final int length) {
1272:                ASTNode node = NodeFinder.perform(root, start, length);
1273:                Assert.isTrue(node instanceof  SimpleName, String.valueOf(node
1274:                        .getNodeType()));
1275:                Assert.isTrue(root instanceof  CompilationUnit, String
1276:                        .valueOf(root.getNodeType()));
1277:                return ((CompilationUnit) root)
1278:                        .findDeclaringNode(((SimpleName) node).resolveBinding());
1279:            }
1280:
1281:            // For debugging
1282:            static String print(Collection/*<ITypeBinding>*/types) {
1283:                if (types.isEmpty())
1284:                    return "{ }"; //$NON-NLS-1$
1285:                String result = "{ "; //$NON-NLS-1$
1286:                for (Iterator it = types.iterator(); it.hasNext();) {
1287:                    ITypeBinding type = (ITypeBinding) it.next();
1288:                    result += type.getQualifiedName();
1289:                    if (it.hasNext()) {
1290:                        result += ", "; //$NON-NLS-1$
1291:                    } else {
1292:                        result += " }"; //$NON-NLS-1$
1293:                    }
1294:                }
1295:                return result;
1296:            }
1297:
1298:            /**
1299:             * Determines the set of types for which a set of type constraints is satisfied.
1300:             */
1301:            private Collection/*<ITypeBinding>*/computeValidTypes(
1302:                    ITypeBinding originalType,
1303:                    Collection/*<ConstraintVariable>*/relevantVars,
1304:                    Collection/*<ITypeConstraint>*/relevantConstraints,
1305:                    IProgressMonitor pm) throws JavaModelException {
1306:
1307:                Collection/*<ITypeBinding>*/result = new HashSet();
1308:                IJavaProject project = fCu.getJavaProject();
1309:
1310:                Collection/*<ITypeBinding>*/allTypes = new HashSet/*<IType>*/();
1311:                allTypes.addAll(getAllSuperTypes(originalType));
1312:
1313:                pm
1314:                        .beginTask(
1315:                                RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage,
1316:                                allTypes.size());
1317:
1318:                for (Iterator/*<ITypeBinding>*/it = allTypes.iterator(); it
1319:                        .hasNext();) {
1320:                    ITypeBinding type = (ITypeBinding) it.next();
1321:                    if (isValid(project, type, relevantVars,
1322:                            relevantConstraints, new SubProgressMonitor(pm, 1))) {
1323:                        result.add(type);
1324:                    }
1325:                }
1326:                // "changing" to the original type is a no-op
1327:                result.remove(originalType);
1328:
1329:                // TODO: remove all types that are not visible --- need to check visibility in the CUs for
1330:                //       all relevant constraint variables
1331:
1332:                pm.done();
1333:
1334:                return result;
1335:            }
1336:
1337:            /**
1338:             * Determines if a given type satisfies a set of type constraints.
1339:             */
1340:            private boolean isValid(IJavaProject project, ITypeBinding type,
1341:                    Collection/*<ConstraintVariable>*/relevantVars,
1342:                    Collection/*<ITypeConstraint>*/constraints,
1343:                    IProgressMonitor pm) throws JavaModelException {
1344:                pm
1345:                        .beginTask(
1346:                                RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage,
1347:                                constraints.size());
1348:                for (Iterator it = constraints.iterator(); it.hasNext();) {
1349:                    ITypeConstraint tc = (ITypeConstraint) it.next();
1350:                    if (tc instanceof  SimpleTypeConstraint) {
1351:                        if (!(isValidSimpleConstraint(project, type,
1352:                                relevantVars, (SimpleTypeConstraint) tc)))
1353:                            return false;
1354:                    } else if (tc instanceof  CompositeOrTypeConstraint) {
1355:                        if (!(isValidOrConstraint(project, type, relevantVars,
1356:                                (CompositeOrTypeConstraint) tc)))
1357:                            return false;
1358:                    }
1359:                    pm.worked(1);
1360:                }
1361:                pm.done();
1362:                return true;
1363:            }
1364:
1365:            private boolean isValidSimpleConstraint(IJavaProject project,
1366:                    ITypeBinding type,
1367:                    Collection/*<ConstraintVariable>*/relevantVars,
1368:                    SimpleTypeConstraint stc) throws JavaModelException {
1369:                if (relevantVars.contains(stc.getLeft())) { // upper bound
1370:                    if (!isSubTypeOf(type, findType(stc.getRight()))) {
1371:                        return false;
1372:                    }
1373:                }
1374:                return true;
1375:            }
1376:
1377:            private boolean isValidOrConstraint(IJavaProject project,
1378:                    ITypeBinding type,
1379:                    Collection/*<ConstraintVariable>*/relevantVars,
1380:                    CompositeOrTypeConstraint cotc) throws JavaModelException {
1381:                ITypeConstraint[] components = cotc.getConstraints();
1382:                for (int i = 0; i < components.length; i++) {
1383:                    if (components[i] instanceof  SimpleTypeConstraint) {
1384:                        SimpleTypeConstraint sc = (SimpleTypeConstraint) components[i];
1385:                        if (relevantVars.contains(sc.getLeft())) { // upper bound
1386:                            if (isSubTypeOf(type, findType(sc.getRight())))
1387:                                return true;
1388:                        } else if (relevantVars.contains(sc.getRight())) { // lower bound
1389:                            if (isSubTypeOf(findType(sc.getLeft()), type))
1390:                                return true;
1391:                        }
1392:                    }
1393:                }
1394:                return false;
1395:            }
1396:
1397:            private ITypeBinding findType(ConstraintVariable cv) {
1398:                return cv.getBinding();
1399:            }
1400:
1401:            /**
1402:             * Gather constraints associated with a set of compilation units.
1403:             */
1404:            private Collection/*<ITypeConstraint>*/getConstraints(
1405:                    ICompilationUnit[] referringCus, IProgressMonitor pm) {
1406:                pm
1407:                        .beginTask(
1408:                                RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage,
1409:                                referringCus.length);
1410:                Collection/*<ITypeConstraint>*/result = new ArrayList();
1411:                for (int i = 0; i < referringCus.length; i++) {
1412:                    result.addAll(getConstraints(referringCus[i]));
1413:                    pm.worked(1);
1414:                    if (pm.isCanceled())
1415:                        throw new OperationCanceledException();
1416:                }
1417:                pm.done();
1418:                return result;
1419:            }
1420:
1421:            private List/*<ITypeConstraint>*/getConstraints(
1422:                    ICompilationUnit unit) {
1423:                if (fConstraintCache.containsKey(unit))
1424:                    return (List) fConstraintCache.get(unit);
1425:
1426:                CompilationUnit cu = ASTCreator.createAST(unit, null);
1427:
1428:                // only generate type constraints for relevant MethodDeclaration subtrees 
1429:                if (fMethodBinding != null
1430:                        && fCuToSearchResultGroup.containsKey(unit)) {
1431:                    SearchResultGroup group = (SearchResultGroup) fCuToSearchResultGroup
1432:                            .get(unit);
1433:                    ASTNode[] nodes = ASTNodeSearchUtil.getAstNodes(group
1434:                            .getSearchResults(), cu);
1435:                    for (int i = 0; i < nodes.length; i++) {
1436:                        ASTNode node = nodes[i];
1437:                        if (fMethodBinding != null) {
1438:                            // find MethodDeclaration above it in the tree
1439:                            ASTNode n = node;
1440:                            while (!(n instanceof  MethodDeclaration)) {
1441:                                n = n.getParent();
1442:                            }
1443:                            MethodDeclaration md = (MethodDeclaration) n;
1444:                            md.accept(fCollector);
1445:                        }
1446:                    }
1447:                } else {
1448:                    cu.accept(fCollector);
1449:                }
1450:                List/*<ITypeConstraint>*/constraints = Arrays
1451:                        .asList(fCollector.getConstraints());
1452:                fConstraintCache.put(unit, constraints);
1453:                return constraints;
1454:            }
1455:
1456:            /**
1457:             * update a CompilationUnit's imports after changing the type of declarations
1458:             */
1459:            private String updateImports(CompilationUnit astRoot,
1460:                    MultiTextEdit rootEdit) throws CoreException {
1461:                ImportRewrite rewrite = StubUtility.createImportRewrite(
1462:                        astRoot, true);
1463:                String typeName = rewrite.addImport(fSelectedType
1464:                        .getQualifiedName());
1465:                rootEdit.addChild(rewrite.rewriteImports(null));
1466:                return typeName;
1467:            }
1468:
1469:            //	------------------------------------------------------------------------------------------------- //
1470:            // Miscellaneous helper methods
1471:
1472:            /**
1473:             * Returns the Collection<IType> of types that can be given to the selected declaration.
1474:             * @return return the valid types
1475:             */
1476:            public Collection/*<IType>*/getValidTypes() {
1477:                return fValidTypes;
1478:            }
1479:
1480:            public ITypeBinding getOriginalType() {
1481:                return fSelectionTypeBinding;
1482:            }
1483:
1484:            private void setOriginalType(ITypeBinding originalType) {
1485:                fSelectionTypeBinding = originalType;
1486:                fSelectedType = findSuperTypeByName(originalType,
1487:                        fSelectedTypeName);
1488:            }
1489:
1490:            public String getTarget() {
1491:                String typeName = fSelectionTypeBinding == null ? "" : fSelectionTypeBinding.getName() + " "; //$NON-NLS-1$//$NON-NLS-2$
1492:                if (fFieldBinding != null) {
1493:                    return typeName + fFieldBinding.getName();
1494:                } else if (fMethodBinding != null) {
1495:                    if (fParamIndex == -1) {
1496:                        return typeName + fMethodBinding.getName() + "(...)"; //$NON-NLS-1$
1497:                    } else {
1498:                        return typeName + fParamName;
1499:                    }
1500:                } else if (fSelectionBinding != null) {
1501:                    return typeName + fSelectionBinding.getName();
1502:                } else {
1503:                    return typeName;
1504:                }
1505:            }
1506:
1507:            /**
1508:             * Returns the Collection<String> of names of types that can be given to the selected declaration.
1509:             * (used in tests only)
1510:             */
1511:            public Collection/*<String>*/getValidTypeNames() {
1512:                Collection/*<String>*/typeNames = new ArrayList();
1513:                for (Iterator it = fValidTypes.iterator(); it.hasNext();) {
1514:                    ITypeBinding type = (ITypeBinding) it.next();
1515:                    typeNames.add(type.getQualifiedName());
1516:                }
1517:
1518:                return typeNames;
1519:            }
1520:
1521:            /**
1522:             * Find the ASTNode for the given source text selection, if it is a type
1523:             * declaration, or null otherwise.
1524:             * @param unit The compilation unit in which the selection was made 
1525:             * @param offset
1526:             * @param length
1527:             * @return ASTNode
1528:             */
1529:            private ASTNode getTargetNode(ICompilationUnit unit, int offset,
1530:                    int length) {
1531:                CompilationUnit root = ASTCreator.createAST(unit, null);
1532:                ASTNode node = NodeFinder.perform(root, offset, length);
1533:                return node;
1534:            }
1535:
1536:            /**
1537:             * Determines the set of compilation units that may give rise to type constraints that
1538:             * we are interested in. This involves searching for overriding/overridden methods,
1539:             * method calls, field accesses.
1540:             */
1541:            private ICompilationUnit[] collectAffectedUnits(IProgressMonitor pm)
1542:                    throws CoreException {
1543:                // BUG: currently, no type constraints are generated for methods that are related
1544:                // but that do not override each other. As a result, we may miss certain relevant
1545:                // variables
1546:
1547:                pm
1548:                        .beginTask(
1549:                                RefactoringCoreMessages.ChangeTypeRefactoring_analyzingMessage,
1550:                                100);
1551:
1552:                if (fAffectedUnits != null) {
1553:                    if (DEBUG)
1554:                        printCollection(
1555:                                "affected units: ", Arrays.asList(fAffectedUnits)); //$NON-NLS-1$
1556:                    pm.worked(100);
1557:                    return fAffectedUnits;
1558:                }
1559:                if (fMethodBinding != null) {
1560:                    if (fMethodBinding != null) {
1561:
1562:                        IMethod selectedMethod = (IMethod) fMethodBinding
1563:                                .getJavaElement();
1564:                        if (selectedMethod == null) {
1565:                            // can't happen since we checked it up front in check initial conditions
1566:                            Assert
1567:                                    .isTrue(
1568:                                            false,
1569:                                            RefactoringCoreMessages.ChangeTypeRefactoring_no_method);
1570:                        }
1571:
1572:                        // the following code fragment appears to be the source of a memory leak, when
1573:                        // GT is repeatedly applied
1574:
1575:                        IMethod root = selectedMethod;
1576:                        if (!root.getDeclaringType().isInterface()
1577:                                && MethodChecks.isVirtual(root)) {
1578:                            final SubProgressMonitor subMonitor = new SubProgressMonitor(
1579:                                    pm, 5);
1580:                            IMethod inInterface = MethodChecks
1581:                                    .isDeclaredInInterface(root, root
1582:                                            .getDeclaringType()
1583:                                            .newTypeHierarchy(
1584:                                                    new SubProgressMonitor(
1585:                                                            subMonitor, 1)),
1586:                                            subMonitor);
1587:                            if (inInterface != null
1588:                                    && !inInterface.equals(root))
1589:                                root = inInterface;
1590:                        }
1591:
1592:                        // end code fragment
1593:
1594:                        IMethod[] rippleMethods = RippleMethodFinder2
1595:                                .getRelatedMethods(root,
1596:                                        new SubProgressMonitor(pm, 15), null);
1597:                        SearchPattern pattern = RefactoringSearchEngine
1598:                                .createOrPattern(rippleMethods,
1599:                                        IJavaSearchConstants.ALL_OCCURRENCES);
1600:
1601:                        // To compute the scope we have to use the selected method. Otherwise we
1602:                        // might start from the wrong project.
1603:                        IJavaSearchScope scope = RefactoringScopeFactory
1604:                                .create(selectedMethod);
1605:                        CollectingSearchRequestor csr = new CollectingSearchRequestor();
1606:
1607:                        SearchResultGroup[] groups = RefactoringSearchEngine
1608:                                .search(pattern, null, scope, csr,
1609:                                        new SubProgressMonitor(pm, 80),
1610:                                        new RefactoringStatus()); //TODO: deal with errors from non-CU matches
1611:
1612:                        fAffectedUnits = getCus(groups);
1613:                    }
1614:                } else if (fFieldBinding != null) {
1615:                    IField iField = (IField) fFieldBinding.getJavaElement();
1616:                    if (iField == null) {
1617:                        // can't happen since we checked it up front in check initial conditions
1618:                        Assert
1619:                                .isTrue(
1620:                                        false,
1621:                                        RefactoringCoreMessages.ChangeTypeRefactoring_no_filed);
1622:                    }
1623:                    SearchPattern pattern = SearchPattern.createPattern(iField,
1624:                            IJavaSearchConstants.ALL_OCCURRENCES,
1625:                            SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
1626:                    IJavaSearchScope scope = RefactoringScopeFactory
1627:                            .create(iField);
1628:                    CollectingSearchRequestor csr = new CollectingSearchRequestor();
1629:                    SearchResultGroup[] groups = RefactoringSearchEngine
1630:                            .search(pattern, null, scope, csr,
1631:                                    new SubProgressMonitor(pm, 100),
1632:                                    new RefactoringStatus()); //TODO: deal with errors from non-CU matches
1633:                    fAffectedUnits = getCus(groups);
1634:                } else {
1635:                    // otherwise, selection was a local variable and we only have to search the CU
1636:                    // containing the selection
1637:                    fAffectedUnits = new ICompilationUnit[] { fCu };
1638:                }
1639:                if (DEBUG) {
1640:                    System.out.println("Determining affected CUs:"); //$NON-NLS-1$
1641:                    for (int i = 0; i < fAffectedUnits.length; i++) {
1642:                        System.out
1643:                                .println("  affected CU: " + fAffectedUnits[i].getElementName()); //$NON-NLS-1$
1644:                    }
1645:                }
1646:                pm.done();
1647:                return fAffectedUnits;
1648:            }
1649:
1650:            public void setSelectedType(ITypeBinding type) {
1651:                fSelectedType = type;
1652:            }
1653:
1654:            //	-------------------------------------------------------------------------------------------- //
1655:            // TODO The following utility methods should probably be moved to another class
1656:
1657:            /**
1658:             * Determines if a constraint variable corresponds to the constant "null".
1659:             */
1660:            private static boolean isNull(ConstraintVariable cv) {
1661:                return cv instanceof  ExpressionVariable
1662:                        && ((ExpressionVariable) cv).getExpressionType() == ASTNode.NULL_LITERAL;
1663:            }
1664:
1665:            /**
1666:             * For debugging.
1667:             */
1668:            void printCollection(String title, Collection/*<Object>*/l) {
1669:                System.out.println(l.size() + " " + title); //$NON-NLS-1$
1670:                for (Iterator it = l.iterator(); it.hasNext();) {
1671:                    System.out.println("  " + it.next()); //$NON-NLS-1$
1672:                }
1673:            }
1674:
1675:            /**
1676:             * Returns the compilation units that contain the search results.
1677:             */
1678:            private ICompilationUnit[] getCus(SearchResultGroup[] groups) {
1679:                List result = new ArrayList(groups.length);
1680:                for (int i = 0; i < groups.length; i++) {
1681:                    SearchResultGroup group = groups[i];
1682:                    ICompilationUnit cu = group.getCompilationUnit();
1683:                    if (cu != null) {
1684:                        result.add(cu);
1685:                        fCuToSearchResultGroup.put(cu, group);
1686:                    }
1687:                }
1688:                return (ICompilationUnit[]) result
1689:                        .toArray(new ICompilationUnit[result.size()]);
1690:            }
1691:
1692:            /**
1693:             * This always includes the type itself. It will include type
1694:             * Object for any type other than Object
1695:             */
1696:            public Set/*<ITypeBinding>*/getAllSuperTypes(ITypeBinding type) {
1697:                Set/*<ITypeBinding>*/result = new HashSet();
1698:                result.add(type);
1699:                if (type.getSuperclass() != null) {
1700:                    result.addAll(getAllSuperTypes(type.getSuperclass()));
1701:                }
1702:                ITypeBinding[] interfaces = type.getInterfaces();
1703:                for (int i = 0; i < interfaces.length; i++) {
1704:                    result.addAll(getAllSuperTypes(interfaces[i]));
1705:                }
1706:                if ((type != fObject) && !contains(result, fObject)) {
1707:                    result.add(fObject);
1708:                }
1709:                return result;
1710:            }
1711:
1712:            private ITypeBinding findSuperTypeByName(ITypeBinding type,
1713:                    String super TypeName) {
1714:                Set/*<ITypeBinding>*/super Types = getAllSuperTypes(type);
1715:                for (Iterator/*<ITypeBinding>*/it = super Types.iterator(); it
1716:                        .hasNext();) {
1717:                    ITypeBinding sup = (ITypeBinding) it.next();
1718:                    if (sup.getQualifiedName().equals(super TypeName)) {
1719:                        return sup;
1720:                    }
1721:                }
1722:                return null;
1723:            }
1724:
1725:            public boolean isSubTypeOf(ITypeBinding type1, ITypeBinding type2) {
1726:
1727:                // to ensure that, e.g., Comparable<String> is considered a subtype of raw Comparable
1728:                if (type1.isParameterizedType()
1729:                        && type1.getTypeDeclaration().isEqualTo(
1730:                                type2.getTypeDeclaration())) {
1731:                    return true;
1732:                }
1733:                Set super Types = getAllSuperTypes(type1);
1734:                return contains(super Types, type2);
1735:            }
1736:
1737:            private static boolean contains(Collection/*<ITypeBinding>*/c,
1738:                    ITypeBinding binding) {
1739:                for (Iterator/*<ITypeBinding>*/it = c.iterator(); it.hasNext();) {
1740:                    ITypeBinding b = (ITypeBinding) it.next();
1741:                    if (Bindings.equals(b, binding))
1742:                        return true;
1743:                }
1744:                return false;
1745:            }
1746:
1747:            /**
1748:             * {@inheritDoc}
1749:             */
1750:            public RefactoringStatus initialize(RefactoringArguments arguments) {
1751:                if (arguments instanceof  JavaRefactoringArguments) {
1752:                    final JavaRefactoringArguments extended = (JavaRefactoringArguments) arguments;
1753:                    final String selection = extended
1754:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION);
1755:                    if (selection != null) {
1756:                        int offset = -1;
1757:                        int length = -1;
1758:                        final StringTokenizer tokenizer = new StringTokenizer(
1759:                                selection);
1760:                        if (tokenizer.hasMoreTokens())
1761:                            offset = Integer.valueOf(tokenizer.nextToken())
1762:                                    .intValue();
1763:                        if (tokenizer.hasMoreTokens())
1764:                            length = Integer.valueOf(tokenizer.nextToken())
1765:                                    .intValue();
1766:                        if (offset >= 0 && length >= 0) {
1767:                            fSelectionStart = offset;
1768:                            fSelectionLength = length;
1769:                        } else
1770:                            return RefactoringStatus
1771:                                    .createFatalErrorStatus(Messages
1772:                                            .format(
1773:                                                    RefactoringCoreMessages.InitializableRefactoring_illegal_argument,
1774:                                                    new Object[] {
1775:                                                            selection,
1776:                                                            JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION }));
1777:                    } else
1778:                        return RefactoringStatus
1779:                                .createFatalErrorStatus(Messages
1780:                                        .format(
1781:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1782:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION));
1783:                    final String handle = extended
1784:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
1785:                    if (handle != null) {
1786:                        final IJavaElement element = JavaRefactoringDescriptorUtil
1787:                                .handleToElement(extended.getProject(), handle,
1788:                                        false);
1789:                        if (element == null
1790:                                || !element.exists()
1791:                                || element.getElementType() != IJavaElement.COMPILATION_UNIT)
1792:                            return createInputFatalStatus(element,
1793:                                    IJavaRefactorings.GENERALIZE_TYPE);
1794:                        else
1795:                            fCu = (ICompilationUnit) element;
1796:                    } else
1797:                        return RefactoringStatus
1798:                                .createFatalErrorStatus(Messages
1799:                                        .format(
1800:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1801:                                                JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
1802:                    final String type = extended.getAttribute(ATTRIBUTE_TYPE);
1803:                    if (type != null && !"".equals(type)) //$NON-NLS-1$
1804:                        fSelectedTypeName = type;
1805:                    else
1806:                        return RefactoringStatus
1807:                                .createFatalErrorStatus(Messages
1808:                                        .format(
1809:                                                RefactoringCoreMessages.InitializableRefactoring_argument_not_exist,
1810:                                                ATTRIBUTE_TYPE));
1811:                } else
1812:                    return RefactoringStatus
1813:                            .createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
1814:                return new RefactoringStatus();
1815:            }
1816:        }
ww__w___.___j___a_va2__s.__c_o___m | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.