KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > generics > InferTypeArgumentsRefactoring


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jdt.internal.corext.refactoring.generics;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Arrays JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.Set JavaDoc;
22 import java.util.Map.Entry;
23
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.core.runtime.ISafeRunnable;
27 import org.eclipse.core.runtime.IStatus;
28 import org.eclipse.core.runtime.OperationCanceledException;
29 import org.eclipse.core.runtime.SafeRunner;
30 import org.eclipse.core.runtime.Status;
31 import org.eclipse.core.runtime.SubProgressMonitor;
32
33 import org.eclipse.core.resources.IFile;
34
35 import org.eclipse.ltk.core.refactoring.Change;
36 import org.eclipse.ltk.core.refactoring.ChangeDescriptor;
37 import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
38 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
39 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
40 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
41
42 import org.eclipse.jdt.core.BindingKey;
43 import org.eclipse.jdt.core.ICompilationUnit;
44 import org.eclipse.jdt.core.IJavaElement;
45 import org.eclipse.jdt.core.IJavaProject;
46 import org.eclipse.jdt.core.compiler.IProblem;
47 import org.eclipse.jdt.core.dom.AST;
48 import org.eclipse.jdt.core.dom.ASTNode;
49 import org.eclipse.jdt.core.dom.ASTParser;
50 import org.eclipse.jdt.core.dom.ASTRequestor;
51 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
52 import org.eclipse.jdt.core.dom.CastExpression;
53 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
54 import org.eclipse.jdt.core.dom.CompilationUnit;
55 import org.eclipse.jdt.core.dom.Expression;
56 import org.eclipse.jdt.core.dom.IBinding;
57 import org.eclipse.jdt.core.dom.Name;
58 import org.eclipse.jdt.core.dom.ParameterizedType;
59 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
60 import org.eclipse.jdt.core.dom.SimpleType;
61 import org.eclipse.jdt.core.dom.Type;
62 import org.eclipse.jdt.core.dom.TypeLiteral;
63 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
64
65 import org.eclipse.jdt.internal.corext.SourceRange;
66 import org.eclipse.jdt.internal.corext.refactoring.Checks;
67 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
68 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor;
69 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
70 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
71 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
72 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
73 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange;
74 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
75 import org.eclipse.jdt.internal.corext.refactoring.generics.InferTypeArgumentsUpdate.CuUpdate;
76 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
77 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
78 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.EnumeratedTypeSet;
79 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet;
80 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CastVariable2;
81 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CollectionElementVariable2;
82 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ConstraintVariable2;
83 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeVariable2;
84 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
85 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
86 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
87 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
88 import org.eclipse.jdt.internal.corext.util.Messages;
89
90 import org.eclipse.jdt.ui.JavaElementLabels;
91
92 import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
93 import org.eclipse.jdt.internal.ui.JavaPlugin;
94
95 public class InferTypeArgumentsRefactoring extends ScriptableRefactoring {
96
97     private static final String JavaDoc ATTRIBUTE_CLONE= "clone"; //$NON-NLS-1$
98
private static final String JavaDoc ATTRIBUTE_LEAVE= "leave"; //$NON-NLS-1$
99

100     private static final String JavaDoc REWRITTEN= "InferTypeArgumentsRefactoring.rewritten"; //$NON-NLS-1$
101

102     private TextChangeManager fChangeManager;
103     private IJavaElement[] fElements;
104     private InferTypeArgumentsTCModel fTCModel;
105
106     private boolean fAssumeCloneReturnsSameType;
107     private boolean fLeaveUnconstrainedRaw;
108     
109     /**
110      * Creates a new infer type arguments refactoring.
111      * @param elements the elements to process, or <code>null</code> if invoked by scripting
112      */

113     public InferTypeArgumentsRefactoring(IJavaElement[] elements) {
114         fElements= elements;
115     }
116     
117     /*
118      * @see org.eclipse.ltk.core.refactoring.Refactoring#getName()
119      */

120     public String JavaDoc getName() {
121         return RefactoringCoreMessages.InferTypeArgumentsRefactoring_name;
122     }
123     
124     public void setAssumeCloneReturnsSameType(boolean assume) {
125         fAssumeCloneReturnsSameType= assume;
126     }
127     
128     public boolean getAssumeCloneReturnsSameType() {
129         return fAssumeCloneReturnsSameType;
130     }
131     
132     public void setLeaveUnconstrainedRaw(boolean raw) {
133         fLeaveUnconstrainedRaw= raw;
134     }
135     
136     public boolean getLeaveUnconstrainedRaw() {
137         return fLeaveUnconstrainedRaw;
138     }
139     
140     /*
141      * @see org.eclipse.ltk.core.refactoring.Refactoring#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)
142      */

143     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {
144         RefactoringStatus result= check15();
145         pm.done();
146         return result;
147     }
148
149     /*
150      * @see org.eclipse.ltk.core.refactoring.Refactoring#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor)
151      */

152     public RefactoringStatus checkFinalConditions(final IProgressMonitor pm) throws CoreException, OperationCanceledException {
153         HashMap JavaDoc/*<IJavaProject, List<JavaElement>>*/ projectsToElements= getJavaElementsPerProject(fElements);
154         pm.beginTask("", projectsToElements.size() + 2); //$NON-NLS-1$
155
final RefactoringStatus result= new RefactoringStatus();
156         try {
157             fTCModel= new InferTypeArgumentsTCModel();
158             final InferTypeArgumentsConstraintCreator unitCollector= new InferTypeArgumentsConstraintCreator(fTCModel, fAssumeCloneReturnsSameType);
159             
160             for (Iterator JavaDoc iter= projectsToElements.entrySet().iterator(); iter.hasNext(); ) {
161                 Entry entry= (Entry) iter.next();
162                 IJavaProject project= (IJavaProject) entry.getKey();
163                 List JavaDoc javaElementsList= (List JavaDoc) entry.getValue();
164                 IJavaElement[] javaElements= (IJavaElement[]) javaElementsList.toArray(new IJavaElement[javaElementsList.size()]);
165                 List JavaDoc cus= Arrays.asList(JavaModelUtil.getAllCompilationUnits(javaElements));
166                 
167                 int batchSize= 150;
168                 int batches= ((cus.size()-1) / batchSize) + 1;
169                 SubProgressMonitor projectMonitor= new SubProgressMonitor(pm, 1);
170                 projectMonitor.beginTask("", batches); //$NON-NLS-1$
171
projectMonitor.setTaskName(RefactoringCoreMessages.InferTypeArgumentsRefactoring_building);
172                 for (int i= 0; i < batches; i++) {
173                     List JavaDoc batch= cus.subList(i * batchSize, Math.min(cus.size(), (i + 1) * batchSize));
174                     ICompilationUnit[] batchCus= (ICompilationUnit[]) batch.toArray(new ICompilationUnit[batch.size()]);
175                     final SubProgressMonitor batchMonitor= new SubProgressMonitor(projectMonitor, 1);
176                     batchMonitor.subTask(RefactoringCoreMessages.InferTypeArgumentsRefactoring_calculating_dependencies);
177                     
178                     ASTParser parser= ASTParser.newParser(AST.JLS3);
179                     parser.setProject(project);
180                     parser.setCompilerOptions(RefactoringASTParser.getCompilerOptions(project));
181                     parser.setResolveBindings(true);
182                     parser.createASTs(batchCus, new String JavaDoc[0], new ASTRequestor() {
183                         public void acceptAST(final ICompilationUnit source, final CompilationUnit ast) {
184                             batchMonitor.subTask(source.getElementName());
185     
186                             SafeRunner.run(new ISafeRunnable() {
187                                 public void run() throws Exception JavaDoc {
188                                     IProblem[] problems= ast.getProblems();
189                                     for (int p= 0; p < problems.length; p++) {
190                                         if (problems[p].isError()) {
191                                             String JavaDoc cuName= JavaElementLabels.getElementLabel(source, JavaElementLabels.CU_QUALIFIED);
192                                             String JavaDoc msg= Messages.format(RefactoringCoreMessages.InferTypeArgumentsRefactoring_error_in_cu_skipped, new Object JavaDoc[] {cuName});
193                                             result.addError(msg, JavaStatusContext.create(source, new SourceRange(problems[p])));
194                                             return;
195                                         }
196                                     }
197                                     ast.accept(unitCollector);
198                                 }
199                                 public void handleException(Throwable JavaDoc exception) {
200                                     String JavaDoc cuName= JavaElementLabels.getElementLabel(source, JavaElementLabels.CU_QUALIFIED);
201                                     String JavaDoc msg= Messages.format(RefactoringCoreMessages.InferTypeArgumentsRefactoring_internal_error, new Object JavaDoc[] {cuName});
202                                     JavaPlugin.log(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, msg, null));
203                                     String JavaDoc msg2= Messages.format(RefactoringCoreMessages.InferTypeArgumentsRefactoring_error_skipped, new Object JavaDoc[] {cuName});
204                                     result.addError(msg2, JavaStatusContext.create(source));
205                                 }
206                             });
207                             
208                             fTCModel.newCu();
209                         }
210                         public void acceptBinding(String JavaDoc bindingKey, IBinding binding) {
211                             //do nothing
212
}
213                     }, batchMonitor);
214                 }
215                 
216                 projectMonitor.done();
217                 fTCModel.newCu();
218             }
219             
220 // Display.getDefault().syncExec(new Runnable() {
221
// public void run() {
222
// MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Debugging...", "after constraint gen");
223
// }
224
// });
225

226             pm.setTaskName(RefactoringCoreMessages.InferTypeArgumentsRefactoring_solving);
227             InferTypeArgumentsConstraintsSolver solver= new InferTypeArgumentsConstraintsSolver(fTCModel);
228             InferTypeArgumentsUpdate updates= solver.solveConstraints(new SubProgressMonitor(pm, 1));
229             solver= null; //free caches
230

231             fChangeManager= new TextChangeManager();
232             rewriteDeclarations(updates, new SubProgressMonitor(pm, 1));
233             
234             IFile[] filesToModify= ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits());
235             result.merge(Checks.validateModifiesFiles(filesToModify, getValidationContext()));
236             return result;
237         } finally {
238             pm.done();
239             clearGlobalState();
240         }
241     }
242     
243     private void clearGlobalState() {
244         TypeSet.resetCount();
245         EnumeratedTypeSet.resetCount();
246         fTCModel= null;
247     }
248
249     private HashMap JavaDoc getJavaElementsPerProject(IJavaElement[] elements) {
250         HashMap JavaDoc/*<IJavaProject, List<JavaElement>>*/ result= new HashMap JavaDoc/*<IJavaProject, List<JavaElement>>*/();
251         for (int i= 0; i < fElements.length; i++) {
252             IJavaElement element= fElements[i];
253             IJavaProject javaProject= element.getJavaProject();
254             ArrayList JavaDoc javaElements= (ArrayList JavaDoc) result.get(javaProject);
255             if (javaElements == null) {
256                 javaElements= new ArrayList JavaDoc();
257                 result.put(javaProject, javaElements);
258             }
259             javaElements.add(element);
260         }
261         return result;
262     }
263
264     private RefactoringStatus check15() throws CoreException {
265         RefactoringStatus result= new RefactoringStatus();
266         HashSet JavaDoc/*<IJavaProject>*/ checkedProjects= new HashSet JavaDoc/*<IJavaProject>*/();
267         
268         for (int i= 0; i < fElements.length; i++) {
269             IJavaProject javaProject= fElements[i].getJavaProject();
270             if (! checkedProjects.contains(javaProject)) {
271                 if (! JavaModelUtil.is50OrHigher(javaProject)) {
272                     String JavaDoc message= Messages.format(RefactoringCoreMessages.InferTypeArgumentsRefactoring_not50, javaProject.getElementName());
273                     result.addFatalError(message);
274                 } else if (! JavaModelUtil.is50OrHigherJRE(javaProject)) {
275                     String JavaDoc message= Messages.format(RefactoringCoreMessages.InferTypeArgumentsRefactoring_not50Library, javaProject.getElementName());
276                     result.addFatalError(message);
277                 }
278                 checkedProjects.add(javaProject);
279             }
280         }
281         return result;
282     }
283
284     private void rewriteDeclarations(InferTypeArgumentsUpdate update, IProgressMonitor pm) throws CoreException {
285         HashMap JavaDoc/*<ICompilationUnit, CuUpdate>*/ updates= update.getUpdates();
286         
287         Set JavaDoc entrySet= updates.entrySet();
288         pm.beginTask("", entrySet.size()); //$NON-NLS-1$
289
pm.setTaskName(RefactoringCoreMessages.InferTypeArgumentsRefactoring_creatingChanges);
290         for (Iterator JavaDoc iter= entrySet.iterator(); iter.hasNext();) {
291             if (pm.isCanceled())
292                 throw new OperationCanceledException();
293             
294             Map.Entry JavaDoc entry= (Map.Entry JavaDoc) iter.next();
295             ICompilationUnit cu= (ICompilationUnit) entry.getKey();
296             pm.worked(1);
297             pm.subTask(cu.getElementName());
298
299             CompilationUnitRewrite rewrite= new CompilationUnitRewrite(cu);
300             rewrite.setResolveBindings(false);
301             CuUpdate cuUpdate= (CuUpdate) entry.getValue();
302             
303             for (Iterator JavaDoc cvIter= cuUpdate.getDeclarations().iterator(); cvIter.hasNext();) {
304                 ConstraintVariable2 cv= (ConstraintVariable2) cvIter.next();
305                 rewriteConstraintVariable(cv, rewrite, fTCModel, fLeaveUnconstrainedRaw, null);
306             }
307             
308             for (Iterator JavaDoc castsIter= cuUpdate.getCastsToRemove().iterator(); castsIter.hasNext();) {
309                 CastVariable2 castCv= (CastVariable2) castsIter.next();
310                 rewriteCastVariable(castCv, rewrite, fTCModel);
311             }
312             
313             CompilationUnitChange change= rewrite.createChange();
314             if (change != null) {
315                 fChangeManager.manage(cu, change);
316             }
317         }
318         
319     }
320     
321     public static ParameterizedType[] inferArguments(SimpleType[] types, InferTypeArgumentsUpdate update, InferTypeArgumentsTCModel model, CompilationUnitRewrite rewrite) {
322         for (int i= 0; i < types.length; i++) {
323             types[i].setProperty(REWRITTEN, null);
324         }
325         List JavaDoc result= new ArrayList JavaDoc();
326         HashMap JavaDoc/*<ICompilationUnit, CuUpdate>*/ updates= update.getUpdates();
327         Set JavaDoc entrySet= updates.entrySet();
328         for (Iterator JavaDoc iter= entrySet.iterator(); iter.hasNext();) {
329             
330             Map.Entry JavaDoc entry= (Map.Entry JavaDoc) iter.next();
331             
332             rewrite.setResolveBindings(false);
333             CuUpdate cuUpdate= (CuUpdate) entry.getValue();
334             
335             for (Iterator JavaDoc cvIter= cuUpdate.getDeclarations().iterator(); cvIter.hasNext();) {
336                 ConstraintVariable2 cv= (ConstraintVariable2) cvIter.next();
337                 ParameterizedType newNode= rewriteConstraintVariable(cv, rewrite, model, false, types);
338                 if (newNode != null)
339                     result.add(newNode);
340             }
341         }
342         return (ParameterizedType[])result.toArray(new ParameterizedType[result.size()]);
343     }
344
345     private static ParameterizedType rewriteConstraintVariable(ConstraintVariable2 cv, CompilationUnitRewrite rewrite, InferTypeArgumentsTCModel tCModel, boolean leaveUnconstraindRaw, SimpleType[] types) {
346         if (cv instanceof CollectionElementVariable2) {
347             ConstraintVariable2 parentElement= ((CollectionElementVariable2) cv).getParentConstraintVariable();
348             if (parentElement instanceof TypeVariable2) {
349                 TypeVariable2 typeCv= (TypeVariable2) parentElement;
350                 return rewriteTypeVariable(typeCv, rewrite, tCModel, leaveUnconstraindRaw, types);
351             } else {
352                 //only rewrite type variables
353
}
354         }
355         return null;
356     }
357
358     private static ParameterizedType rewriteTypeVariable(TypeVariable2 typeCv, CompilationUnitRewrite rewrite, InferTypeArgumentsTCModel tCModel, boolean leaveUnconstraindRaw, SimpleType[] types) {
359         ASTNode node= typeCv.getRange().getNode(rewrite.getRoot());
360         if (node instanceof Name && node.getParent() instanceof Type) {
361             Type originalType= (Type) node.getParent();
362             
363             if (types != null && !has(types, originalType))
364                 return null;
365             
366             // Must rewrite all type arguments in one batch. Do the rewrite when the first one is encountered; skip the others.
367
Object JavaDoc rewritten= originalType.getProperty(REWRITTEN);
368             if (rewritten == REWRITTEN)
369                 return null;
370             originalType.setProperty(REWRITTEN, REWRITTEN);
371             
372             ArrayList JavaDoc typeArgumentCvs= getTypeArgumentCvs(typeCv, tCModel);
373             Type[] typeArguments= getTypeArguments(originalType, typeArgumentCvs, rewrite, tCModel, leaveUnconstraindRaw);
374             if (typeArguments == null)
375                 return null;
376             
377             Type movingType= (Type) rewrite.getASTRewrite().createMoveTarget(originalType);
378             ParameterizedType newType= rewrite.getAST().newParameterizedType(movingType);
379             
380             for (int i= 0; i < typeArguments.length; i++) {
381                 newType.typeArguments().add(typeArguments[i]);
382             }
383
384             rewrite.getASTRewrite().replace(originalType, newType, rewrite.createGroupDescription(RefactoringCoreMessages.InferTypeArgumentsRefactoring_addTypeArguments));
385             return newType;
386         } else {//TODO: other node types?
387
return null;
388         }
389     }
390
391     private static boolean has(SimpleType[] types, Type originalType) {
392         for (int i= 0; i < types.length; i++) {
393             if (types[i] == originalType)
394                 return true;
395         }
396         return false;
397     }
398
399     /**
400      * @return the new type arguments, or <code>null</code> iff an argument could not be infered
401      */

402     private static Type[] getTypeArguments(Type baseType, ArrayList JavaDoc typeArgumentCvs, CompilationUnitRewrite rewrite, InferTypeArgumentsTCModel tCModel, boolean leaveUnconstraindRaw) {
403         if (typeArgumentCvs.size() == 0)
404             return null;
405         
406         Type[] typeArguments= new Type[typeArgumentCvs.size()];
407         for (int i= 0; i < typeArgumentCvs.size(); i++) {
408             CollectionElementVariable2 elementCv= (CollectionElementVariable2) typeArgumentCvs.get(i);
409             Type typeArgument;
410             TType chosenType= InferTypeArgumentsConstraintsSolver.getChosenType(elementCv);
411             if (chosenType != null) {
412                 if (chosenType.isWildcardType() && ! unboundedWildcardAllowed(baseType))
413                     return null; // can't e.g. write "new ArrayList<?>()".
414
if (chosenType.isParameterizedType()) // workaround for bug 99124
415
chosenType= chosenType.getTypeDeclaration();
416                 BindingKey bindingKey= new BindingKey(chosenType.getBindingKey());
417                 typeArgument= rewrite.getImportRewrite().addImportFromSignature(bindingKey.toSignature(), rewrite.getAST());
418                 ArrayList JavaDoc nestedTypeArgumentCvs= getTypeArgumentCvs(elementCv, tCModel);
419                 Type[] nestedTypeArguments= getTypeArguments(typeArgument, nestedTypeArgumentCvs, rewrite, tCModel, leaveUnconstraindRaw); //recursion
420
if (nestedTypeArguments != null) {
421                     ParameterizedType parameterizedType= rewrite.getAST().newParameterizedType(typeArgument);
422                     for (int j= 0; j < nestedTypeArguments.length; j++)
423                         parameterizedType.typeArguments().add(nestedTypeArguments[j]);
424                     typeArgument= parameterizedType;
425                 }
426
427             } else { // couldn't infer an element type (no constraints)
428
if (leaveUnconstraindRaw) {
429                     // every guess could be wrong => leave the whole thing raw
430
return null;
431                 } else {
432                     if (unboundedWildcardAllowed(baseType)) {
433                         typeArgument= rewrite.getAST().newWildcardType();
434                     } else {
435                         String JavaDoc object= rewrite.getImportRewrite().addImport("java.lang.Object"); //$NON-NLS-1$
436
typeArgument= (Type) rewrite.getASTRewrite().createStringPlaceholder(object, ASTNode.SIMPLE_TYPE);
437                     }
438                 }
439 // ASTNode baseTypeParent= baseType.getParent();
440
// if (baseTypeParent instanceof ClassInstanceCreation) {
441
// //No ? allowed. Take java.lang.Object.
442
// typeArgument= rewrite.getAST().newSimpleType(rewrite.getAST().newName(rewrite.getImportRewrite().addImport("java.lang.Object"))); //$NON-NLS-1$
443
// } else if (baseTypeParent instanceof ArrayCreation || baseTypeParent instanceof InstanceofExpression) {
444
// //Only ? allowed.
445
// typeArgument= rewrite.getAST().newWildcardType();
446
// } else {
447
// //E.g. field type: can put anything. Choosing ? in order to be most constraining.
448
// typeArgument= rewrite.getAST().newWildcardType();
449
// }
450
}
451             typeArguments[i]= typeArgument;
452         }
453         return typeArguments;
454     }
455
456     private static ArrayList JavaDoc/*<CollectionElementVariable2>*/ getTypeArgumentCvs(ConstraintVariable2 baseCv, InferTypeArgumentsTCModel tCModel) {
457         Map JavaDoc elementCvs= tCModel.getElementVariables(baseCv);
458         ArrayList JavaDoc typeArgumentCvs= new ArrayList JavaDoc();
459         for (Iterator JavaDoc iter= elementCvs.values().iterator(); iter.hasNext();) {
460             CollectionElementVariable2 elementCv= (CollectionElementVariable2) iter.next();
461             int index= elementCv.getDeclarationTypeVariableIndex();
462             if (index != CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX) {
463                 while (index >= typeArgumentCvs.size())
464                     typeArgumentCvs.add(null); // fill with null until set(index, ..) is possible
465
typeArgumentCvs.set(index, elementCv);
466             }
467         }
468         return typeArgumentCvs;
469     }
470
471     private static boolean unboundedWildcardAllowed(Type originalType) {
472         ASTNode parent= originalType.getParent();
473         while (parent instanceof Type)
474             parent= parent.getParent();
475         
476         if (parent instanceof ClassInstanceCreation) {
477             return false;
478         } else if (parent instanceof AbstractTypeDeclaration) {
479             return false;
480         } else if (parent instanceof TypeLiteral) {
481             return false;
482         }
483         return true;
484     }
485
486     private static ASTNode rewriteCastVariable(CastVariable2 castCv, CompilationUnitRewrite rewrite, InferTypeArgumentsTCModel tCModel) {//, List positionGroups) {
487
ASTNode node= castCv.getRange().getNode(rewrite.getRoot());
488         
489         ConstraintVariable2 expressionVariable= castCv.getExpressionVariable();
490         ConstraintVariable2 methodReceiverCv= tCModel.getMethodReceiverCv(expressionVariable);
491         if (methodReceiverCv != null) {
492             TType chosenReceiverType= InferTypeArgumentsConstraintsSolver.getChosenType(methodReceiverCv);
493             if (chosenReceiverType == null)
494                 return null;
495             else if (! InferTypeArgumentsTCModel.isAGenericType(chosenReceiverType))
496                 return null;
497             else if (hasUnboundElement(methodReceiverCv, tCModel))
498                 return null;
499         }
500         
501         CastExpression castExpression= (CastExpression) node;
502         Expression expression= castExpression.getExpression();
503         ASTNode nodeToReplace;
504         if (castExpression.getParent() instanceof ParenthesizedExpression)
505             nodeToReplace= castExpression.getParent();
506         else
507             nodeToReplace= castExpression;
508         
509         Expression newExpression= (Expression) rewrite.getASTRewrite().createMoveTarget(expression);
510         rewrite.getASTRewrite().replace(nodeToReplace, newExpression, rewrite.createGroupDescription(RefactoringCoreMessages.InferTypeArgumentsRefactoring_removeCast));
511         rewrite.getImportRemover().registerRemovedNode(nodeToReplace);
512         return newExpression;
513     }
514
515     private static boolean hasUnboundElement(ConstraintVariable2 methodReceiverCv, InferTypeArgumentsTCModel tCModel) {
516         ArrayList JavaDoc/*<CollectionElementVariable2>*/ typeArgumentCvs= getTypeArgumentCvs(methodReceiverCv, tCModel);
517         for (Iterator JavaDoc iter= typeArgumentCvs.iterator(); iter.hasNext();) {
518             CollectionElementVariable2 elementCv= (CollectionElementVariable2) iter.next();
519             TType chosenElementType= InferTypeArgumentsConstraintsSolver.getChosenType(elementCv);
520             if (chosenElementType == null)
521                 return true;
522         }
523         return false;
524     }
525
526     /*
527      * @see org.eclipse.ltk.core.refactoring.Refactoring#createChange(org.eclipse.core.runtime.IProgressMonitor)
528      */

529     public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
530         pm.beginTask("", 1); //$NON-NLS-1$
531
try {
532             DynamicValidationStateChange result= new DynamicValidationStateChange(RefactoringCoreMessages.InferTypeArgumentsRefactoring_name, fChangeManager.getAllChanges()) {
533             
534                 public final ChangeDescriptor getDescriptor() {
535                     final Map JavaDoc arguments= new HashMap JavaDoc();
536                     final IJavaProject project= getSingleProject();
537                     final String JavaDoc description= RefactoringCoreMessages.InferTypeArgumentsRefactoring_descriptor_description;
538                     final String JavaDoc header= project != null ? Messages.format(RefactoringCoreMessages.InferTypeArgumentsRefactoring_descriptor_description_project, project.getElementName()) : RefactoringCoreMessages.InferTypeArgumentsRefactoring_descriptor_description;
539                     final String JavaDoc name= project != null ? project.getElementName() : null;
540                     final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(name, this, header);
541                     final String JavaDoc[] settings= new String JavaDoc[fElements.length];
542                     for (int index= 0; index < settings.length; index++)
543                         settings[index]= JavaElementLabels.getTextLabel(fElements[index], JavaElementLabels.ALL_FULLY_QUALIFIED);
544                     comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.InferTypeArgumentsRefactoring_original_elements, settings));
545                     if (fAssumeCloneReturnsSameType)
546                         comment.addSetting(RefactoringCoreMessages.InferTypeArgumentsRefactoring_assume_clone);
547                     if (fLeaveUnconstrainedRaw)
548                         comment.addSetting(RefactoringCoreMessages.InferTypeArgumentsRefactoring_leave_unconstrained);
549                     final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaRefactorings.INFER_TYPE_ARGUMENTS, name, description, comment.asString(), arguments, RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE);
550                     for (int index= 0; index < fElements.length; index++)
551                         arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + (index + 1), descriptor.elementToHandle(fElements[index]));
552                     arguments.put(ATTRIBUTE_CLONE, Boolean.valueOf(fAssumeCloneReturnsSameType).toString());
553                     arguments.put(ATTRIBUTE_LEAVE, Boolean.valueOf(fLeaveUnconstrainedRaw).toString());
554                     return new RefactoringChangeDescriptor(descriptor);
555                 }
556             };
557             return result;
558         } finally {
559             pm.done();
560         }
561     }
562
563     private IJavaProject getSingleProject() {
564         IJavaProject first= null;
565         for (int index= 0; index < fElements.length; index++) {
566             final IJavaProject project= fElements[index].getJavaProject();
567             if (project != null) {
568                 if (first == null)
569                     first= project;
570                 else if (!project.equals(first))
571                     return null;
572             }
573         }
574         return first;
575     }
576
577     public RefactoringStatus initialize(final RefactoringArguments arguments) {
578         if (arguments instanceof JavaRefactoringArguments) {
579             final JavaRefactoringArguments generic= (JavaRefactoringArguments) arguments;
580             final String JavaDoc clone= generic.getAttribute(ATTRIBUTE_CLONE);
581             if (clone != null) {
582                 fAssumeCloneReturnsSameType= Boolean.valueOf(clone).booleanValue();
583             } else
584                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_CLONE));
585             final String JavaDoc leave= generic.getAttribute(ATTRIBUTE_LEAVE);
586             if (leave != null) {
587                 fLeaveUnconstrainedRaw= Boolean.valueOf(leave).booleanValue();
588             } else
589                 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_LEAVE));
590             int count= 1;
591             final List JavaDoc elements= new ArrayList JavaDoc();
592             String JavaDoc handle= null;
593             String JavaDoc attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count;
594             final RefactoringStatus status= new RefactoringStatus();
595             while ((handle= generic.getAttribute(attribute)) != null) {
596                 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(generic.getProject(), handle, false);
597                 if (element == null || !element.exists())
598                     return createInputFatalStatus(element, IJavaRefactorings.INFER_TYPE_ARGUMENTS);
599                 else
600                     elements.add(element);
601                 count++;
602                 attribute= JDTRefactoringDescriptor.ATTRIBUTE_ELEMENT + count;
603             }
604             fElements= (IJavaElement[]) elements.toArray(new IJavaElement[elements.size()]);
605             if (elements.isEmpty())
606                 return createInputFatalStatus(null, IJavaRefactorings.INFER_TYPE_ARGUMENTS);
607             if (!status.isOK())
608                 return status;
609         } else
610             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
611         return new RefactoringStatus();
612     }
613 }
614
Popular Tags