KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > text > correction > UnresolvedElementsSubProcessor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Renaud Waldura <renaud+eclipse@waldura.com> - New class/interface with wizard
11  *******************************************************************************/

12 package org.eclipse.jdt.internal.ui.text.correction;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.List JavaDoc;
18
19 import org.eclipse.core.runtime.CoreException;
20
21 import org.eclipse.swt.graphics.Image;
22
23 import org.eclipse.ui.ISharedImages;
24
25 import org.eclipse.jdt.core.ICompilationUnit;
26 import org.eclipse.jdt.core.IJavaElement;
27 import org.eclipse.jdt.core.IJavaProject;
28 import org.eclipse.jdt.core.IPackageFragment;
29 import org.eclipse.jdt.core.IType;
30 import org.eclipse.jdt.core.JavaModelException;
31 import org.eclipse.jdt.core.Signature;
32 import org.eclipse.jdt.core.dom.AST;
33 import org.eclipse.jdt.core.dom.ASTMatcher;
34 import org.eclipse.jdt.core.dom.ASTNode;
35 import org.eclipse.jdt.core.dom.Annotation;
36 import org.eclipse.jdt.core.dom.ArrayType;
37 import org.eclipse.jdt.core.dom.Assignment;
38 import org.eclipse.jdt.core.dom.BodyDeclaration;
39 import org.eclipse.jdt.core.dom.CastExpression;
40 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
41 import org.eclipse.jdt.core.dom.CompilationUnit;
42 import org.eclipse.jdt.core.dom.ConstructorInvocation;
43 import org.eclipse.jdt.core.dom.Expression;
44 import org.eclipse.jdt.core.dom.FieldAccess;
45 import org.eclipse.jdt.core.dom.IBinding;
46 import org.eclipse.jdt.core.dom.IMethodBinding;
47 import org.eclipse.jdt.core.dom.IPackageBinding;
48 import org.eclipse.jdt.core.dom.ITypeBinding;
49 import org.eclipse.jdt.core.dom.IVariableBinding;
50 import org.eclipse.jdt.core.dom.MemberValuePair;
51 import org.eclipse.jdt.core.dom.MethodDeclaration;
52 import org.eclipse.jdt.core.dom.MethodInvocation;
53 import org.eclipse.jdt.core.dom.Modifier;
54 import org.eclipse.jdt.core.dom.Name;
55 import org.eclipse.jdt.core.dom.NormalAnnotation;
56 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
57 import org.eclipse.jdt.core.dom.QualifiedName;
58 import org.eclipse.jdt.core.dom.SimpleName;
59 import org.eclipse.jdt.core.dom.SimpleType;
60 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
61 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
62 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
63 import org.eclipse.jdt.core.dom.SuperFieldAccess;
64 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
65 import org.eclipse.jdt.core.dom.SwitchCase;
66 import org.eclipse.jdt.core.dom.SwitchStatement;
67 import org.eclipse.jdt.core.dom.ThisExpression;
68 import org.eclipse.jdt.core.dom.ThrowStatement;
69 import org.eclipse.jdt.core.dom.Type;
70 import org.eclipse.jdt.core.dom.TypeDeclaration;
71 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
72 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
73 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
74
75 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
76 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
77 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
78 import org.eclipse.jdt.internal.corext.dom.Bindings;
79 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
80 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
81 import org.eclipse.jdt.internal.corext.util.Messages;
82 import org.eclipse.jdt.internal.corext.util.QualifiedTypeNameHistory;
83 import org.eclipse.jdt.internal.corext.util.TypeFilter;
84
85 import org.eclipse.jdt.ui.JavaElementImageDescriptor;
86 import org.eclipse.jdt.ui.JavaElementLabels;
87 import org.eclipse.jdt.ui.text.java.IInvocationContext;
88 import org.eclipse.jdt.ui.text.java.IProblemLocation;
89
90 import org.eclipse.jdt.internal.ui.JavaPlugin;
91 import org.eclipse.jdt.internal.ui.JavaPluginImages;
92 import org.eclipse.jdt.internal.ui.text.correction.ChangeMethodSignatureProposal.ChangeDescription;
93 import org.eclipse.jdt.internal.ui.text.correction.ChangeMethodSignatureProposal.EditDescription;
94 import org.eclipse.jdt.internal.ui.text.correction.ChangeMethodSignatureProposal.InsertDescription;
95 import org.eclipse.jdt.internal.ui.text.correction.ChangeMethodSignatureProposal.RemoveDescription;
96 import org.eclipse.jdt.internal.ui.text.correction.ChangeMethodSignatureProposal.SwapDescription;
97 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
98 import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;
99
100 public class UnresolvedElementsSubProcessor {
101     
102     private static final String JavaDoc ADD_IMPORT_ID= "org.eclipse.jdt.ui.correction.addImport"; //$NON-NLS-1$
103

104     public static void getVariableProposals(IInvocationContext context, IProblemLocation problem, IVariableBinding resolvedField, Collection JavaDoc proposals) throws CoreException {
105
106         ICompilationUnit cu= context.getCompilationUnit();
107
108         CompilationUnit astRoot= context.getASTRoot();
109         ASTNode selectedNode= problem.getCoveredNode(astRoot);
110         if (selectedNode == null) {
111             return;
112         }
113
114         // type that defines the variable
115
ITypeBinding binding= null;
116         ITypeBinding declaringTypeBinding= Bindings.getBindingOfParentTypeContext(selectedNode);
117         if (declaringTypeBinding == null) {
118             return;
119         }
120
121         // possible type kind of the node
122
boolean suggestVariableProposals= true;
123         int typeKind= 0;
124
125         while (selectedNode instanceof ParenthesizedExpression) {
126             selectedNode= ((ParenthesizedExpression) selectedNode).getExpression();
127         }
128
129
130         Name node= null;
131
132         switch (selectedNode.getNodeType()) {
133             case ASTNode.SIMPLE_NAME:
134                 node= (SimpleName) selectedNode;
135                 ASTNode parent= node.getParent();
136                 StructuralPropertyDescriptor locationInParent= node.getLocationInParent();
137                 if (locationInParent == MethodInvocation.EXPRESSION_PROPERTY) {
138                     typeKind= SimilarElementsRequestor.CLASSES;
139                 } else if (locationInParent == FieldAccess.NAME_PROPERTY) {
140                     Expression expression= ((FieldAccess) parent).getExpression();
141                     if (expression != null) {
142                         binding= expression.resolveTypeBinding();
143                         if (binding == null) {
144                             node= null;
145                         }
146                     }
147                 } else if (parent instanceof SimpleType) {
148                     suggestVariableProposals= false;
149                     typeKind= SimilarElementsRequestor.REF_TYPES_AND_VAR;
150                 } else if (parent instanceof QualifiedName) {
151                     Name qualifier= ((QualifiedName) parent).getQualifier();
152                     if (qualifier != node) {
153                         binding= qualifier.resolveTypeBinding();
154                     } else {
155                         typeKind= SimilarElementsRequestor.REF_TYPES;
156                     }
157                     ASTNode outerParent= parent.getParent();
158                     while (outerParent instanceof QualifiedName) {
159                         outerParent= outerParent.getParent();
160                     }
161                     if (outerParent instanceof SimpleType) {
162                         typeKind= SimilarElementsRequestor.REF_TYPES;
163                         suggestVariableProposals= false;
164                     }
165                 } else if (locationInParent == SwitchCase.EXPRESSION_PROPERTY) {
166                     ITypeBinding switchExp= ((SwitchStatement) node.getParent().getParent()).getExpression().resolveTypeBinding();
167                     if (switchExp != null && switchExp.isEnum()) {
168                         binding= switchExp;
169                     }
170                 } else if (locationInParent == SuperFieldAccess.NAME_PROPERTY) {
171                     binding= declaringTypeBinding.getSuperclass();
172                 }
173                 break;
174             case ASTNode.QUALIFIED_NAME:
175                 QualifiedName qualifierName= (QualifiedName) selectedNode;
176                 ITypeBinding qualifierBinding= qualifierName.getQualifier().resolveTypeBinding();
177                 if (qualifierBinding != null) {
178                     node= qualifierName.getName();
179                     binding= qualifierBinding;
180                 } else {
181                     node= qualifierName.getQualifier();
182                     typeKind= SimilarElementsRequestor.REF_TYPES;
183                     suggestVariableProposals= node.isSimpleName();
184                 }
185                 if (selectedNode.getParent() instanceof SimpleType) {
186                     typeKind= SimilarElementsRequestor.REF_TYPES;
187                     suggestVariableProposals= false;
188                 }
189                 break;
190             case ASTNode.FIELD_ACCESS:
191                 FieldAccess access= (FieldAccess) selectedNode;
192                 Expression expression= access.getExpression();
193                 if (expression != null) {
194                     binding= expression.resolveTypeBinding();
195                     if (binding != null) {
196                         node= access.getName();
197                     }
198                 }
199                 break;
200             case ASTNode.SUPER_FIELD_ACCESS:
201                 binding= declaringTypeBinding.getSuperclass();
202                 node= ((SuperFieldAccess) selectedNode).getName();
203                 break;
204             default:
205         }
206
207         if (node == null) {
208             return;
209         }
210
211         // add type proposals
212
if (typeKind != 0) {
213             if (!JavaModelUtil.is50OrHigher(cu.getJavaProject())) {
214                 typeKind &= ~(SimilarElementsRequestor.ANNOTATIONS | SimilarElementsRequestor.ENUMS | SimilarElementsRequestor.VARIABLES);
215             }
216
217             int relevance= Character.isUpperCase(ASTNodes.getSimpleNameIdentifier(node).charAt(0)) ? 5 : -2;
218             addSimilarTypeProposals(typeKind, cu, node, relevance + 1, proposals);
219             
220             typeKind &= ~SimilarElementsRequestor.ANNOTATIONS;
221             addNewTypeProposals(cu, node, typeKind, relevance, proposals);
222         }
223
224         if (!suggestVariableProposals) {
225             return;
226         }
227
228         SimpleName simpleName= node.isSimpleName() ? (SimpleName) node : ((QualifiedName) node).getName();
229         boolean isWriteAccess= ASTResolving.isWriteAccess(node);
230
231         // similar variables
232
addSimilarVariableProposals(cu, astRoot, binding, simpleName, isWriteAccess, proposals);
233
234         if (resolvedField == null || binding == null || resolvedField.getDeclaringClass() != binding.getTypeDeclaration() && Modifier.isPrivate(resolvedField.getModifiers())) {
235             
236             // new fields
237
addNewFieldProposals(cu, astRoot, binding, declaringTypeBinding, simpleName, isWriteAccess, proposals);
238             
239             // new parameters and local variables
240
if (binding == null) {
241                 addNewVariableProposals(cu, node, simpleName, proposals);
242             }
243         }
244     }
245
246     private static void addNewVariableProposals(ICompilationUnit cu, Name node, SimpleName simpleName, Collection JavaDoc proposals) {
247         String JavaDoc name= simpleName.getIdentifier();
248         BodyDeclaration bodyDeclaration= ASTResolving.findParentBodyDeclaration(node, true);
249         int type= bodyDeclaration.getNodeType();
250         if (type == ASTNode.METHOD_DECLARATION) {
251             int relevance= StubUtility.hasParameterName(cu.getJavaProject(), name) ? 8 : 5;
252             String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createparameter_description, simpleName.getIdentifier());
253             Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
254             proposals.add(new NewVariableCompletionProposal(label, cu, NewVariableCompletionProposal.PARAM, simpleName, null, relevance, image));
255         }
256         if (type == ASTNode.INITIALIZER || (type == ASTNode.METHOD_DECLARATION && !ASTResolving.isInsideConstructorInvocation((MethodDeclaration) bodyDeclaration, node))) {
257             int relevance= StubUtility.hasLocalVariableName(cu.getJavaProject(), name) ? 10 : 7;
258             String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createlocal_description, simpleName.getIdentifier());
259             Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
260             proposals.add(new NewVariableCompletionProposal(label, cu, NewVariableCompletionProposal.LOCAL, simpleName, null, relevance, image));
261         }
262
263         if (node.getParent().getNodeType() == ASTNode.ASSIGNMENT) {
264             Assignment assignment= (Assignment) node.getParent();
265             if (assignment.getLeftHandSide() == node && assignment.getParent().getNodeType() == ASTNode.EXPRESSION_STATEMENT) {
266                 ASTNode statement= assignment.getParent();
267                 ASTRewrite rewrite= ASTRewrite.create(statement.getAST());
268                 if (ASTNodes.isControlStatementBody(assignment.getParent().getLocationInParent())) {
269                     rewrite.replace(statement, rewrite.getAST().newBlock(), null);
270                 } else {
271                     rewrite.remove(statement, null);
272                 }
273                 String JavaDoc label= CorrectionMessages.UnresolvedElementsSubProcessor_removestatement_description;
274                 Image image= JavaPlugin.getDefault().getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE);
275                 ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 4, image);
276                 proposals.add(proposal);
277             }
278         }
279     }
280
281     private static void addNewFieldProposals(ICompilationUnit cu, CompilationUnit astRoot, ITypeBinding binding, ITypeBinding declaringTypeBinding, SimpleName simpleName, boolean isWriteAccess, Collection JavaDoc proposals) throws JavaModelException {
282         // new variables
283
ICompilationUnit targetCU;
284         ITypeBinding senderDeclBinding;
285         if (binding != null) {
286             senderDeclBinding= binding.getTypeDeclaration();
287             targetCU= ASTResolving.findCompilationUnitForBinding(cu, astRoot, senderDeclBinding);
288         } else { // binding is null for accesses without qualifier
289
senderDeclBinding= declaringTypeBinding;
290             targetCU= cu;
291         }
292
293         if (!senderDeclBinding.isFromSource() || targetCU == null) {
294             return;
295         }
296         
297         boolean mustBeConst= ASTResolving.isInsideModifiers(simpleName);
298
299         addNewFieldForType(targetCU, binding, senderDeclBinding, simpleName, isWriteAccess, mustBeConst, proposals);
300
301         if (binding == null && senderDeclBinding.isNested()) {
302             ASTNode anonymDecl= astRoot.findDeclaringNode(senderDeclBinding);
303             if (anonymDecl != null) {
304                 ITypeBinding bind= Bindings.getBindingOfParentType(anonymDecl.getParent());
305                 if (!bind.isAnonymous()) {
306                     addNewFieldForType(targetCU, bind, bind, simpleName, isWriteAccess, mustBeConst, proposals);
307                 }
308             }
309         }
310     }
311
312     private static void addNewFieldForType(ICompilationUnit targetCU, ITypeBinding binding, ITypeBinding senderDeclBinding, SimpleName simpleName, boolean isWriteAccess, boolean mustBeConst, Collection JavaDoc proposals) {
313         String JavaDoc name= simpleName.getIdentifier();
314         String JavaDoc label;
315         Image image;
316         if (senderDeclBinding.isEnum() && !isWriteAccess) {
317             label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createenum_description, new Object JavaDoc[] { name, ASTResolving.getTypeSignature(senderDeclBinding) });
318             image= JavaPluginImages.get(JavaPluginImages.IMG_FIELD_PUBLIC);
319             proposals.add(new NewVariableCompletionProposal(label, targetCU, NewVariableCompletionProposal.ENUM_CONST, simpleName, senderDeclBinding, 10, image));
320         } else {
321             if (!mustBeConst) {
322                 if (binding == null) {
323                     label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createfield_description, name);
324                     image= JavaPluginImages.get(JavaPluginImages.IMG_FIELD_PRIVATE);
325                 } else {
326                     label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createfield_other_description, new Object JavaDoc[] { name, ASTResolving.getTypeSignature(senderDeclBinding) } );
327                     image= JavaPluginImages.get(JavaPluginImages.IMG_FIELD_PUBLIC);
328                 }
329                 int fieldRelevance= StubUtility.hasFieldName(targetCU.getJavaProject(), name) ? 9 : 6;
330                 proposals.add(new NewVariableCompletionProposal(label, targetCU, NewVariableCompletionProposal.FIELD, simpleName, senderDeclBinding, fieldRelevance, image));
331             }
332
333             if (!isWriteAccess && !senderDeclBinding.isAnonymous()) {
334                 if (binding == null) {
335                     label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createconst_description, name);
336                     image= JavaPluginImages.get(JavaPluginImages.IMG_FIELD_PRIVATE);
337                 } else {
338                     label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createconst_other_description, new Object JavaDoc[] { name, ASTResolving.getTypeSignature(senderDeclBinding) } );
339                     image= JavaPluginImages.get(JavaPluginImages.IMG_FIELD_PUBLIC);
340                 }
341                 int constRelevance= StubUtility.hasConstantName(name) ? 9 : 4;
342                 proposals.add(new NewVariableCompletionProposal(label, targetCU, NewVariableCompletionProposal.CONST_FIELD, simpleName, senderDeclBinding, constRelevance, image));
343             }
344         }
345     }
346
347     private static void addSimilarVariableProposals(ICompilationUnit cu, CompilationUnit astRoot, ITypeBinding binding, SimpleName node, boolean isWriteAccess, Collection JavaDoc proposals) {
348         int kind= ScopeAnalyzer.VARIABLES | ScopeAnalyzer.CHECK_VISIBILITY;
349         if (!isWriteAccess) {
350             kind |= ScopeAnalyzer.METHODS; // also try to find similar methods
351
}
352
353         IBinding[] varsAndMethodsInScope= (new ScopeAnalyzer(astRoot)).getDeclarationsInScope(node, kind);
354         if (varsAndMethodsInScope.length > 0) {
355             // avoid corrections like int i= i;
356
String JavaDoc otherNameInAssign= null;
357
358             // help with x.getString() -> y.getString()
359
String JavaDoc methodSenderName= null;
360             String JavaDoc fieldSenderName= null;
361
362             ASTNode parent= node.getParent();
363             switch (parent.getNodeType()) {
364             case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
365                 // node must be initializer
366
otherNameInAssign= ((VariableDeclarationFragment) parent).getName().getIdentifier();
367                 break;
368             case ASTNode.ASSIGNMENT:
369                 Assignment assignment= (Assignment) parent;
370                 if (isWriteAccess && assignment.getRightHandSide() instanceof SimpleName) {
371                     otherNameInAssign= ((SimpleName) assignment.getRightHandSide()).getIdentifier();
372                 } else if (!isWriteAccess && assignment.getLeftHandSide() instanceof SimpleName) {
373                     otherNameInAssign= ((SimpleName) assignment.getLeftHandSide()).getIdentifier();
374                 }
375                 break;
376             case ASTNode.METHOD_INVOCATION:
377                 MethodInvocation inv= (MethodInvocation) parent;
378                 if (inv.getExpression() == node) {
379                     methodSenderName= inv.getName().getIdentifier();
380                 }
381                 break;
382             case ASTNode.QUALIFIED_NAME:
383                 QualifiedName qualName= (QualifiedName) parent;
384                 if (qualName.getQualifier() == node) {
385                     fieldSenderName= qualName.getName().getIdentifier();
386                 }
387                 break;
388             }
389
390
391             ITypeBinding guessedType= ASTResolving.guessBindingForReference(node);
392
393             ITypeBinding objectBinding= astRoot.getAST().resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
394
String JavaDoc identifier= node.getIdentifier();
395             boolean isInStaticContext= ASTResolving.isInStaticContext(node);
396
397             loop: for (int i= 0; i < varsAndMethodsInScope.length; i++) {
398                 IBinding varOrMeth= varsAndMethodsInScope[i];
399                 if (varOrMeth instanceof IVariableBinding) {
400                     IVariableBinding curr= (IVariableBinding) varOrMeth;
401                     String JavaDoc currName= curr.getName();
402                     if (currName.equals(otherNameInAssign)) {
403                         continue loop;
404                     }
405                     boolean isFinal= Modifier.isFinal(curr.getModifiers());
406                     if (isFinal && curr.isField() && isWriteAccess) {
407                         continue loop;
408                     }
409                     if (isInStaticContext && !Modifier.isStatic(curr.getModifiers()) && curr.isField()) {
410                         continue loop;
411                     }
412
413                     int relevance= 0;
414                     if (NameMatcher.isSimilarName(currName, identifier)) {
415                         relevance += 3; // variable with a similar name than the unresolved variable
416
}
417                     if (currName.equalsIgnoreCase(identifier)) {
418                         relevance+= 5;
419                     }
420                     ITypeBinding varType= curr.getType();
421                     if (varType != null) {
422                         if (guessedType != null && guessedType != objectBinding) { // too many result with object
423
// variable type is compatible with the guessed type
424
if (!isWriteAccess && canAssign(varType, guessedType)
425                                     || isWriteAccess && canAssign(guessedType, varType)) {
426                                 relevance += 2; // unresolved variable can be assign to this variable
427
}
428                         }
429                         if (methodSenderName != null && hasMethodWithName(varType, methodSenderName)) {
430                             relevance += 2;
431                         }
432                         if (fieldSenderName != null && hasFieldWithName(varType, fieldSenderName)) {
433                             relevance += 2;
434                         }
435                     }
436
437                     if (relevance > 0) {
438                         String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changevariable_description, currName);
439                         proposals.add(new RenameNodeCompletionProposal(label, cu, node.getStartPosition(), node.getLength(), currName, relevance));
440                     }
441                 } else if (varOrMeth instanceof IMethodBinding) {
442                     IMethodBinding curr= (IMethodBinding) varOrMeth;
443                     if (!curr.isConstructor() && guessedType != null && canAssign(curr.getReturnType(), guessedType)) {
444                         if (NameMatcher.isSimilarName(curr.getName(), identifier)) {
445                             AST ast= astRoot.getAST();
446                             ASTRewrite rewrite= ASTRewrite.create(ast);
447                             String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changetomethod_description, ASTResolving.getMethodSignature(curr, false));
448                             Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
449                             LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, 8, image);
450                             proposals.add(proposal);
451
452                             MethodInvocation newInv= ast.newMethodInvocation();
453                             newInv.setName(ast.newSimpleName(curr.getName()));
454                             ITypeBinding[] parameterTypes= curr.getParameterTypes();
455                             for (int k= 0; k < parameterTypes.length; k++) {
456                                 ASTNode arg= ASTNodeFactory.newDefaultExpression(ast, parameterTypes[k]);
457                                 newInv.arguments().add(arg);
458                                 proposal.addLinkedPosition(rewrite.track(arg), false, null);
459                             }
460                             rewrite.replace(node, newInv, null);
461                         }
462                     }
463                 }
464             }
465         }
466         if (binding != null && binding.isArray()) {
467             String JavaDoc idLength= "length"; //$NON-NLS-1$
468
String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changevariable_description, idLength);
469             proposals.add(new RenameNodeCompletionProposal(label, cu, node.getStartPosition(), node.getLength(), idLength, 8));
470         }
471     }
472
473     private static boolean canAssign(ITypeBinding returnType, ITypeBinding guessedType) {
474         return returnType.isAssignmentCompatible(guessedType);
475     }
476
477     private static boolean hasMethodWithName(ITypeBinding typeBinding, String JavaDoc name) {
478         IVariableBinding[] fields= typeBinding.getDeclaredFields();
479         for (int i= 0; i < fields.length; i++) {
480             if (fields[i].getName().equals(name)) {
481                 return true;
482             }
483         }
484         ITypeBinding superclass= typeBinding.getSuperclass();
485         if (superclass != null) {
486             return hasMethodWithName(superclass, name);
487         }
488         return false;
489     }
490
491     private static boolean hasFieldWithName(ITypeBinding typeBinding, String JavaDoc name) {
492         IMethodBinding[] methods= typeBinding.getDeclaredMethods();
493         for (int i= 0; i < methods.length; i++) {
494             if (methods[i].getName().equals(name)) {
495                 return true;
496             }
497         }
498         ITypeBinding superclass= typeBinding.getSuperclass();
499         if (superclass != null) {
500             return hasMethodWithName(superclass, name);
501         }
502         return false;
503     }
504
505     private static int evauateTypeKind(ASTNode node, IJavaProject project) {
506         int kind= ASTResolving.getPossibleTypeKinds(node, JavaModelUtil.is50OrHigher(project));
507         return kind;
508     }
509
510
511     public static void getTypeProposals(IInvocationContext context, IProblemLocation problem, Collection JavaDoc proposals) throws CoreException {
512         ICompilationUnit cu= context.getCompilationUnit();
513
514         ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
515         if (selectedNode == null) {
516             return;
517         }
518
519         int kind= evauateTypeKind(selectedNode, cu.getJavaProject());
520
521         while (selectedNode.getLocationInParent() == QualifiedName.NAME_PROPERTY) {
522             selectedNode= selectedNode.getParent();
523         }
524
525         Name node= null;
526         if (selectedNode instanceof SimpleType) {
527             node= ((SimpleType) selectedNode).getName();
528         } else if (selectedNode instanceof ArrayType) {
529             Type elementType= ((ArrayType) selectedNode).getElementType();
530             if (elementType.isSimpleType()) {
531                 node= ((SimpleType) elementType).getName();
532             } else {
533                 return;
534             }
535         } else if (selectedNode instanceof Name) {
536             node= (Name) selectedNode;
537         } else {
538             return;
539         }
540
541         // change to similar type proposals
542
addSimilarTypeProposals(kind, cu, node, 3, proposals);
543
544         while (node.getParent() instanceof QualifiedName) {
545             node= (Name) node.getParent();
546         }
547         
548         if (selectedNode != node) {
549             kind= evauateTypeKind(node, cu.getJavaProject());
550         }
551         if ((kind & (SimilarElementsRequestor.CLASSES | SimilarElementsRequestor.INTERFACES)) != 0) {
552             kind &= ~SimilarElementsRequestor.ANNOTATIONS; // only propose annotations when there are no other suggestions
553
}
554         addNewTypeProposals(cu, node, kind, 0, proposals);
555     }
556
557     private static void addSimilarTypeProposals(int kind, ICompilationUnit cu, Name node, int relevance, Collection JavaDoc proposals) throws CoreException {
558         SimilarElement[] elements= SimilarElementsRequestor.findSimilarElement(cu, node, kind);
559
560         // try to resolve type in context -> highest severity
561
String JavaDoc resolvedTypeName= null;
562         ITypeBinding binding= ASTResolving.guessBindingForTypeReference(node);
563         if (binding != null) {
564             ITypeBinding simpleBinding= binding;
565             if (simpleBinding.isArray()) {
566                 simpleBinding= simpleBinding.getElementType();
567             }
568             simpleBinding= simpleBinding.getTypeDeclaration();
569             
570             resolvedTypeName= simpleBinding.getQualifiedName();
571             CUCorrectionProposal proposal= createTypeRefChangeProposal(cu, resolvedTypeName, node, relevance + 2, elements.length);
572             proposals.add(proposal);
573             if (proposal instanceof AddImportCorrectionProposal)
574                 proposal.setRelevance(relevance + elements.length + 2);
575
576             if (binding.isParameterizedType() && node.getParent() instanceof SimpleType && !(node.getParent().getParent() instanceof Type)) {
577                 proposals.add(createTypeRefChangeFullProposal(cu, binding, node, relevance + 2));
578             }
579         } else {
580             ASTNode normalizedNode= ASTNodes.getNormalizedNode(node);
581             if (!(normalizedNode.getParent() instanceof Type) && node.getParent() != normalizedNode) {
582                 ITypeBinding normBinding= ASTResolving.guessBindingForTypeReference(normalizedNode);
583                 if (normBinding != null) {
584                     proposals.add(createTypeRefChangeFullProposal(cu, normBinding, normalizedNode, relevance + 2));
585                 }
586             }
587         }
588
589         // add all similar elements
590
for (int i= 0; i < elements.length; i++) {
591             SimilarElement elem= elements[i];
592             if ((elem.getKind() & SimilarElementsRequestor.ALL_TYPES) != 0) {
593                 String JavaDoc fullName= elem.getName();
594                 if (!fullName.equals(resolvedTypeName)) {
595                     proposals.add(createTypeRefChangeProposal(cu, fullName, node, relevance, elements.length));
596                 }
597             }
598         }
599     }
600         
601     private static CUCorrectionProposal createTypeRefChangeProposal(ICompilationUnit cu, String JavaDoc fullName, Name node, int relevance, int maxProposals) throws CoreException {
602         ImportRewrite importRewrite= null;
603         String JavaDoc simpleName= fullName;
604         String JavaDoc packName= Signature.getQualifier(fullName);
605         if (packName.length() > 0) { // no imports for primitive types, type variables
606
importRewrite= StubUtility.createImportRewrite((CompilationUnit) node.getRoot(), true);
607             simpleName= importRewrite.addImport(fullName);
608         }
609         
610         if (!isLikelyTypeName(simpleName)) {
611             relevance -= 2;
612         }
613
614         ASTRewriteCorrectionProposal proposal;
615         if (importRewrite != null && node.isSimpleName() && simpleName.equals(((SimpleName) node).getIdentifier())) { // import only
616
// import only
617
String JavaDoc[] arg= { simpleName, packName };
618             String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_importtype_description, arg);
619             Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_IMPDECL);
620             int boost= QualifiedTypeNameHistory.getBoost(fullName, 0, maxProposals);
621             proposal= new AddImportCorrectionProposal(label, cu, relevance + 100 + boost, image, packName, simpleName, (SimpleName)node);
622             proposal.setCommandId(ADD_IMPORT_ID);
623         } else {
624             String JavaDoc label;
625             if (packName.length() == 0) {
626                 label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changetype_nopack_description, simpleName);
627             } else {
628                 String JavaDoc[] arg= { simpleName, packName };
629                 label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changetype_description, arg);
630             }
631             ASTRewrite rewrite= ASTRewrite.create(node.getAST());
632             rewrite.replace(node, rewrite.createStringPlaceholder(simpleName, ASTNode.SIMPLE_TYPE), null);
633             Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
634             proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, relevance, image);
635         }
636         if (importRewrite != null) {
637             proposal.setImportRewrite(importRewrite);
638         }
639         return proposal;
640     }
641     
642     private static CUCorrectionProposal createTypeRefChangeFullProposal(ICompilationUnit cu, ITypeBinding binding, ASTNode node, int relevance) throws CoreException {
643         ASTRewrite rewrite= ASTRewrite.create(node.getAST());
644         String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_change_full_type_description, BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_DEFAULT));
645         Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
646         
647
648         ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, relevance + 3, image);
649         
650         ImportRewrite imports= proposal.createImportRewrite((CompilationUnit) node.getRoot());
651         Type type= imports.addImport(binding, node.getAST());
652         
653         rewrite.replace(node, type, null);
654         return proposal;
655     }
656
657     private static boolean isLikelyTypeName(String JavaDoc name) {
658         return name.length() > 0 && Character.isUpperCase(name.charAt(0));
659     }
660
661     private static boolean isLikelyPackageName(String JavaDoc name) {
662         if (name.length() != 0) {
663             int i= 0;
664             do {
665                 if (Character.isUpperCase(name.charAt(i))) {
666                     return false;
667                 }
668                 i= name.indexOf('.', i) + 1;
669             } while (i != 0 && i < name.length());
670         }
671         return true;
672     }
673
674     private static boolean isLikelyTypeParameterName(String JavaDoc name) {
675         return name.length() == 1 && Character.isUpperCase(name.charAt(0));
676     }
677
678     public static void addNewTypeProposals(ICompilationUnit cu, Name refNode, int kind, int relevance, Collection JavaDoc proposals) throws JavaModelException {
679         Name node= refNode;
680         do {
681             String JavaDoc typeName= ASTNodes.getSimpleNameIdentifier(node);
682             Name qualifier= null;
683             // only propose to create types for qualifiers when the name starts with upper case
684
boolean isPossibleName= isLikelyTypeName(typeName) || (node == refNode);
685             if (isPossibleName) {
686                 IPackageFragment enclosingPackage= null;
687                 IType enclosingType= null;
688                 if (node.isSimpleName()) {
689                     enclosingPackage= (IPackageFragment) cu.getParent();
690                     // don't suggest member type, user can select it in wizard
691
} else {
692                     Name qualifierName= ((QualifiedName) node).getQualifier();
693                      IBinding binding= qualifierName.resolveBinding();
694                      if (binding != null && binding.isRecovered()) {
695                          binding= null;
696                      }
697                      if (binding instanceof ITypeBinding) {
698                         enclosingType=(IType) binding.getJavaElement();
699                      } else if (binding instanceof IPackageBinding) {
700                         qualifier= qualifierName;
701                         enclosingPackage= (IPackageFragment) binding.getJavaElement();
702                      } else {
703                         IJavaElement[] res= cu.codeSelect(qualifierName.getStartPosition(), qualifierName.getLength());
704                         if (res!= null && res.length > 0 && res[0] instanceof IType) {
705                             enclosingType= (IType) res[0];
706                         } else {
707                             qualifier= qualifierName;
708                             enclosingPackage= JavaModelUtil.getPackageFragmentRoot(cu).getPackageFragment(ASTResolving.getFullName(qualifierName));
709                         }
710                      }
711                 }
712                 int rel= relevance;
713                 if (enclosingPackage != null && isLikelyPackageName(enclosingPackage.getElementName())) {
714                     rel += 3;
715                 }
716
717                 if ((enclosingPackage != null && !enclosingPackage.getCompilationUnit(typeName + JavaModelUtil.DEFAULT_CU_SUFFIX).exists()) // new top level type
718
|| (enclosingType != null && !enclosingType.isReadOnly() && !enclosingType.getType(typeName).exists())) { // new member type
719
IJavaElement enclosing= enclosingPackage != null ? (IJavaElement) enclosingPackage : enclosingType;
720
721                     if ((kind & SimilarElementsRequestor.CLASSES) != 0) {
722                         proposals.add(new NewCUCompletionUsingWizardProposal(cu, node, NewCUCompletionUsingWizardProposal.K_CLASS, enclosing, rel+3));
723                     }
724                     if ((kind & SimilarElementsRequestor.INTERFACES) != 0) {
725                         proposals.add(new NewCUCompletionUsingWizardProposal(cu, node, NewCUCompletionUsingWizardProposal.K_INTERFACE, enclosing, rel+2));
726                     }
727                     if ((kind & SimilarElementsRequestor.ENUMS) != 0) {
728                         proposals.add(new NewCUCompletionUsingWizardProposal(cu, node, NewCUCompletionUsingWizardProposal.K_ENUM, enclosing, rel));
729                     }
730                     if ((kind & SimilarElementsRequestor.ANNOTATIONS) != 0) {
731                         proposals.add(new NewCUCompletionUsingWizardProposal(cu, node, NewCUCompletionUsingWizardProposal.K_ANNOTATION, enclosing, rel + 1));
732                     }
733                 }
734             }
735             node= qualifier;
736         } while (node != null);
737
738         // type parameter proposals
739
if (refNode.isSimpleName() && ((kind & SimilarElementsRequestor.VARIABLES) != 0)) {
740             CompilationUnit root= (CompilationUnit) refNode.getRoot();
741             String JavaDoc name= ((SimpleName) refNode).getIdentifier();
742             BodyDeclaration declaration= ASTResolving.findParentBodyDeclaration(refNode);
743             int baseRel= relevance;
744             if (isLikelyTypeParameterName(name)) {
745                 baseRel += 4;
746             }
747             while (declaration != null) {
748                 IBinding binding= null;
749                 int rel= baseRel;
750                 if (declaration instanceof MethodDeclaration) {
751                     binding= ((MethodDeclaration) declaration).resolveBinding();
752                 } else if (declaration instanceof TypeDeclaration) {
753                     binding= ((TypeDeclaration) declaration).resolveBinding();
754                     rel++;
755                 }
756                 if (binding != null) {
757                     AddTypeParameterProposal proposal= new AddTypeParameterProposal(cu, binding, root, name, null, rel);
758                     proposals.add(proposal);
759                 }
760                 if (!Modifier.isStatic(declaration.getModifiers())) {
761                     declaration= ASTResolving.findParentBodyDeclaration(declaration.getParent());
762                 } else {
763                     declaration= null;
764                 }
765             }
766         }
767     }
768
769     public static void getMethodProposals(IInvocationContext context, IProblemLocation problem, boolean isOnlyParameterMismatch, Collection JavaDoc proposals) throws CoreException {
770
771         ICompilationUnit cu= context.getCompilationUnit();
772
773         CompilationUnit astRoot= context.getASTRoot();
774         ASTNode selectedNode= problem.getCoveringNode(astRoot);
775
776         if (!(selectedNode instanceof SimpleName)) {
777             return;
778         }
779         SimpleName nameNode= (SimpleName) selectedNode;
780
781         List JavaDoc arguments;
782         Expression sender;
783         boolean isSuperInvocation;
784
785         ASTNode invocationNode= nameNode.getParent();
786         if (invocationNode instanceof MethodInvocation) {
787             MethodInvocation methodImpl= (MethodInvocation) invocationNode;
788             arguments= methodImpl.arguments();
789             sender= methodImpl.getExpression();
790             isSuperInvocation= false;
791         } else if (invocationNode instanceof SuperMethodInvocation) {
792             SuperMethodInvocation methodImpl= (SuperMethodInvocation) invocationNode;
793             arguments= methodImpl.arguments();
794             sender= methodImpl.getQualifier();
795             isSuperInvocation= true;
796         } else {
797             return;
798         }
799
800         String JavaDoc methodName= nameNode.getIdentifier();
801         int nArguments= arguments.size();
802
803         // corrections
804
IBinding[] bindings= (new ScopeAnalyzer(astRoot)).getDeclarationsInScope(nameNode, ScopeAnalyzer.METHODS);
805
806         HashSet JavaDoc suggestedRenames= new HashSet JavaDoc();
807         for (int i= 0; i < bindings.length; i++) {
808             IMethodBinding binding= (IMethodBinding) bindings[i];
809             String JavaDoc curr= binding.getName();
810             if (!curr.equals(methodName) && binding.getParameterTypes().length == nArguments && NameMatcher.isSimilarName(methodName, curr) && suggestedRenames.add(curr)) {
811                 String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changemethod_description, curr);
812                 proposals.add(new RenameNodeCompletionProposal(label, context.getCompilationUnit(), problem.getOffset(), problem.getLength(), curr, 6));
813             }
814         }
815         suggestedRenames= null;
816
817         if (isOnlyParameterMismatch) {
818             ArrayList JavaDoc parameterMismatchs= new ArrayList JavaDoc();
819             for (int i= 0; i < bindings.length; i++) {
820                 IMethodBinding binding= (IMethodBinding) bindings[i];
821                 if (binding.getName().equals(methodName)) {
822                     parameterMismatchs.add(binding);
823                 }
824             }
825             addParameterMissmatchProposals(context, problem, parameterMismatchs, invocationNode, arguments, proposals);
826         }
827
828         // new method
829
addNewMethodProposals(cu, astRoot, sender, arguments, isSuperInvocation, invocationNode, methodName, proposals);
830
831         if (!isOnlyParameterMismatch && !isSuperInvocation && sender != null) {
832             addMissingCastParentsProposal(cu, (MethodInvocation) invocationNode, proposals);
833         }
834
835         if (!isSuperInvocation && sender == null && invocationNode.getParent() instanceof ThrowStatement) {
836             String JavaDoc str= "new "; //$NON-NLS-1$ // do it the manual way, copting all the arguments is nasty
837
String JavaDoc label= CorrectionMessages.UnresolvedElementsSubProcessor_addnewkeyword_description;
838             int relevance= Character.isUpperCase(methodName.charAt(0)) ? 7 : 4;
839             ReplaceCorrectionProposal proposal= new ReplaceCorrectionProposal(label, cu, invocationNode.getStartPosition(), 0, str, relevance);
840             proposals.add(proposal);
841         }
842
843     }
844
845     private static void addNewMethodProposals(ICompilationUnit cu, CompilationUnit astRoot, Expression sender, List JavaDoc arguments, boolean isSuperInvocation, ASTNode invocationNode, String JavaDoc methodName, Collection JavaDoc proposals) throws JavaModelException {
846         ITypeBinding nodeParentType= Bindings.getBindingOfParentType(invocationNode);
847         ITypeBinding binding= null;
848         if (sender != null) {
849             binding= sender.resolveTypeBinding();
850         } else {
851             binding= nodeParentType;
852             if (isSuperInvocation && binding != null) {
853                 binding= binding.getSuperclass();
854             }
855         }
856         if (binding != null && binding.isFromSource()) {
857             ITypeBinding senderDeclBinding= binding.getTypeDeclaration();
858
859             ICompilationUnit targetCU= ASTResolving.findCompilationUnitForBinding(cu, astRoot, senderDeclBinding);
860             if (targetCU != null) {
861                 String JavaDoc label;
862                 Image image;
863                 ITypeBinding[] parameterTypes= getParameterTypes(arguments);
864                 if (parameterTypes != null) {
865                     String JavaDoc sig= ASTResolving.getMethodSignature(methodName, parameterTypes, false);
866     
867                     if (ASTResolving.isUseableTypeInContext(parameterTypes, senderDeclBinding, false)) {
868                         if (nodeParentType == senderDeclBinding) {
869                             label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createmethod_description, sig);
870                             image= JavaPluginImages.get(JavaPluginImages.IMG_MISC_PRIVATE);
871                         } else {
872                             label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createmethod_other_description, new Object JavaDoc[] { sig, senderDeclBinding.getName() } );
873                             image= JavaPluginImages.get(JavaPluginImages.IMG_MISC_PUBLIC);
874                         }
875                         proposals.add(new NewMethodCompletionProposal(label, targetCU, invocationNode, arguments, senderDeclBinding, 5, image));
876                     }
877                     if (senderDeclBinding.isNested() && cu.equals(targetCU) && sender == null && Bindings.findMethodInHierarchy(senderDeclBinding, methodName, (ITypeBinding[]) null) == null) { // no covering method
878
ASTNode anonymDecl= astRoot.findDeclaringNode(senderDeclBinding);
879                         if (anonymDecl != null) {
880                             senderDeclBinding= Bindings.getBindingOfParentType(anonymDecl.getParent());
881                             if (!senderDeclBinding.isAnonymous() && ASTResolving.isUseableTypeInContext(parameterTypes, senderDeclBinding, false)) {
882                                 String JavaDoc[] args= new String JavaDoc[] { sig, ASTResolving.getTypeSignature(senderDeclBinding) };
883                                 label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createmethod_other_description, args);
884                                 image= JavaPluginImages.get(JavaPluginImages.IMG_MISC_PROTECTED);
885                                 proposals.add(new NewMethodCompletionProposal(label, targetCU, invocationNode, arguments, senderDeclBinding, 5, image));
886                             }
887                         }
888                     }
889                 }
890             }
891         }
892     }
893
894     private static void addMissingCastParentsProposal(ICompilationUnit cu, MethodInvocation invocationNode, Collection JavaDoc proposals) {
895         Expression sender= invocationNode.getExpression();
896         if (sender instanceof ThisExpression) {
897             return;
898         }
899
900         ITypeBinding senderBinding= sender.resolveTypeBinding();
901         if (senderBinding == null || Modifier.isFinal(senderBinding.getModifiers())) {
902             return;
903         }
904
905         if (sender instanceof Name && ((Name) sender).resolveBinding() instanceof ITypeBinding) {
906             return; // static access
907
}
908
909         ASTNode parent= invocationNode.getParent();
910         while (parent instanceof Expression && parent.getNodeType() != ASTNode.CAST_EXPRESSION) {
911             parent= parent.getParent();
912         }
913         boolean hasCastProposal= false;
914         if (parent instanceof CastExpression) {
915             // (TestCase) x.getName() -> ((TestCase) x).getName
916
hasCastProposal= useExistingParentCastProposal(cu, (CastExpression) parent, sender, invocationNode.getName(), getArgumentTypes(invocationNode.arguments()), proposals);
917         }
918         if (!hasCastProposal) {
919             // x.getName() -> ((TestCase) x).getName
920

921             Expression target= sender;
922             while (target instanceof ParenthesizedExpression) {
923                 target= ((ParenthesizedExpression) target).getExpression();
924             }
925
926             String JavaDoc label;
927             if (target.getNodeType() != ASTNode.CAST_EXPRESSION) {
928                 String JavaDoc targetName= null;
929                 if (target.getLength() <= 18) {
930                     targetName= ASTNodes.asString(target);
931                 }
932                 if (targetName == null) {
933                     label= CorrectionMessages.UnresolvedElementsSubProcessor_methodtargetcast_description;
934                 } else {
935                     label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_methodtargetcast2_description, targetName);
936                 }
937             } else {
938                 String JavaDoc targetName= null;
939                 if (target.getLength() <= 18) {
940                     targetName= ASTNodes.asString(((CastExpression)target).getExpression());
941                 }
942                 if (targetName == null) {
943                     label= CorrectionMessages.UnresolvedElementsSubProcessor_changemethodtargetcast_description;
944                 } else {
945                     label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changemethodtargetcast2_description, targetName);
946                 }
947             }
948             proposals.add(new CastCompletionProposal(label, cu, target, (ITypeBinding) null, 3));
949         }
950     }
951
952     private static boolean useExistingParentCastProposal(ICompilationUnit cu, CastExpression expression, Expression accessExpression, SimpleName accessSelector, ITypeBinding[] paramTypes, Collection JavaDoc proposals) {
953         ITypeBinding castType= expression.getType().resolveBinding();
954         if (castType == null) {
955             return false;
956         }
957         if (paramTypes != null) {
958             if (Bindings.findMethodInHierarchy(castType, accessSelector.getIdentifier(), paramTypes) == null) {
959                 return false;
960             }
961         } else if (Bindings.findFieldInHierarchy(castType, accessSelector.getIdentifier()) == null) {
962             return false;
963         }
964         ITypeBinding bindingToCast= accessExpression.resolveTypeBinding();
965         if (bindingToCast != null && !bindingToCast.isCastCompatible(castType)) {
966             return false;
967         }
968
969         IMethodBinding res= Bindings.findMethodInHierarchy(castType, accessSelector.getIdentifier(), paramTypes);
970         if (res != null) {
971             AST ast= expression.getAST();
972             ASTRewrite rewrite= ASTRewrite.create(ast);
973             CastExpression newCast= ast.newCastExpression();
974             newCast.setType((Type) ASTNode.copySubtree(ast, expression.getType()));
975             newCast.setExpression((Expression) rewrite.createCopyTarget(accessExpression));
976             ParenthesizedExpression parents= ast.newParenthesizedExpression();
977             parents.setExpression(newCast);
978
979             ASTNode node= rewrite.createCopyTarget(expression.getExpression());
980             rewrite.replace(expression, node, null);
981             rewrite.replace(accessExpression, parents, null);
982
983             String JavaDoc label= CorrectionMessages.UnresolvedElementsSubProcessor_missingcastbrackets_description;
984             Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CAST);
985             ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 8, image);
986             proposals.add(proposal);
987             return true;
988         }
989         return false;
990     }
991
992     private static void addParameterMissmatchProposals(IInvocationContext context, IProblemLocation problem, List JavaDoc similarElements, ASTNode invocationNode, List JavaDoc arguments, Collection JavaDoc proposals) throws CoreException {
993         int nSimilarElements= similarElements.size();
994         ITypeBinding[] argTypes= getArgumentTypes(arguments);
995         if (argTypes == null || nSimilarElements == 0) {
996             return;
997         }
998
999         for (int i= 0; i < nSimilarElements; i++) {
1000            IMethodBinding elem = (IMethodBinding) similarElements.get(i);
1001            int diff= elem.getParameterTypes().length - argTypes.length;
1002            if (diff == 0) {
1003                int nProposals= proposals.size();
1004                doEqualNumberOfParameters(context, invocationNode, problem, arguments, argTypes, elem, proposals);
1005                if (nProposals != proposals.size()) {
1006                    return; // only suggest for one method (avoid duplicated proposals)
1007
}
1008            } else if (diff > 0) {
1009                doMoreParameters(context, problem, invocationNode, arguments, argTypes, elem, proposals);
1010            } else {
1011                doMoreArguments(context, problem, invocationNode, arguments, argTypes, elem, proposals);
1012            }
1013        }
1014    }
1015
1016    private static void doMoreParameters(IInvocationContext context, IProblemLocation problem, ASTNode invocationNode, List JavaDoc arguments, ITypeBinding[] argTypes, IMethodBinding methodBinding, Collection JavaDoc proposals) throws CoreException {
1017        ITypeBinding[] paramTypes= methodBinding.getParameterTypes();
1018        int k= 0, nSkipped= 0;
1019        int diff= paramTypes.length - argTypes.length;
1020        int[] indexSkipped= new int[diff];
1021        for (int i= 0; i < paramTypes.length; i++) {
1022            if (k < argTypes.length && canAssign(argTypes[k], paramTypes[i])) {
1023                k++; // match
1024
} else {
1025                if (nSkipped >= diff) {
1026                    return; // too different
1027
}
1028                indexSkipped[nSkipped++]= i;
1029            }
1030        }
1031        ITypeBinding declaringType= methodBinding.getDeclaringClass();
1032        ICompilationUnit cu= context.getCompilationUnit();
1033        CompilationUnit astRoot= context.getASTRoot();
1034
1035        // add arguments
1036
{
1037            String JavaDoc[] arg= new String JavaDoc[] { ASTResolving.getMethodSignature(methodBinding, false) };
1038            String JavaDoc label;
1039            if (diff == 1) {
1040                label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_addargument_description, arg);
1041            } else {
1042                label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_addarguments_description, arg);
1043            }
1044            AddArgumentCorrectionProposal proposal= new AddArgumentCorrectionProposal(label, context.getCompilationUnit(), invocationNode, indexSkipped, paramTypes, 8);
1045            proposal.setImage(JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD));
1046            proposals.add(proposal);
1047        }
1048
1049        // remove parameters
1050
if (!declaringType.isFromSource()) {
1051            return;
1052        }
1053
1054        ICompilationUnit targetCU= ASTResolving.findCompilationUnitForBinding(cu, astRoot, declaringType);
1055        if (targetCU != null) {
1056            IMethodBinding methodDecl= methodBinding.getMethodDeclaration();
1057            ITypeBinding[] declParameterTypes= methodDecl.getParameterTypes();
1058
1059            ChangeDescription[] changeDesc= new ChangeDescription[declParameterTypes.length];
1060            ITypeBinding[] changedTypes= new ITypeBinding[diff];
1061            for (int i= diff - 1; i >= 0; i--) {
1062                int idx= indexSkipped[i];
1063                changeDesc[idx]= new RemoveDescription();
1064                changedTypes[i]= declParameterTypes[idx];
1065            }
1066            String JavaDoc[] arg= new String JavaDoc[] { ASTResolving.getMethodSignature(methodDecl, !cu.equals(targetCU)), getTypeNames(changedTypes) };
1067            String JavaDoc label;
1068            if (methodDecl.isConstructor()) {
1069                if (diff == 1) {
1070                    label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_removeparam_constr_description, arg);
1071                } else {
1072                    label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_removeparams_constr_description, arg);
1073                }
1074            } else {
1075                if (diff == 1) {
1076                    label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_removeparam_description, arg);
1077                } else {
1078                    label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_removeparams_description, arg);
1079                }
1080            }
1081
1082            Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_REMOVE);
1083            ChangeMethodSignatureProposal proposal= new ChangeMethodSignatureProposal(label, targetCU, invocationNode, methodDecl, changeDesc, null, 5, image);
1084            proposals.add(proposal);
1085        }
1086    }
1087
1088    private static String JavaDoc getTypeNames(ITypeBinding[] types) {
1089        StringBuffer JavaDoc buf= new StringBuffer JavaDoc();
1090        for (int i= 0; i < types.length; i++) {
1091            if (i > 0) {
1092                buf.append(", "); //$NON-NLS-1$
1093
}
1094            buf.append(ASTResolving.getTypeSignature(types[i]));
1095        }
1096        return buf.toString();
1097    }
1098
1099    private static String JavaDoc getArgumentName(ICompilationUnit cu, List JavaDoc arguments, int index) {
1100        String JavaDoc def= String.valueOf(index + 1);
1101
1102        ASTNode expr= (ASTNode) arguments.get(index);
1103        if (expr.getLength() > 18) {
1104            return def;
1105        }
1106        ASTMatcher matcher= new ASTMatcher();
1107        for (int i= 0; i < arguments.size(); i++) {
1108            if (i != index && matcher.safeSubtreeMatch(expr, arguments.get(i))) {
1109                return def;
1110            }
1111        }
1112        return '\'' + ASTNodes.asString(expr) + '\'';
1113    }
1114
1115    private static void doMoreArguments(IInvocationContext context, IProblemLocation problem, ASTNode invocationNode, List JavaDoc arguments, ITypeBinding[] argTypes, IMethodBinding methodRef, Collection JavaDoc proposals) throws CoreException {
1116        ITypeBinding[] paramTypes= methodRef.getParameterTypes();
1117        int k= 0, nSkipped= 0;
1118        int diff= argTypes.length - paramTypes.length;
1119        int[] indexSkipped= new int[diff];
1120        for (int i= 0; i < argTypes.length; i++) {
1121            if (k < paramTypes.length && canAssign(argTypes[i], paramTypes[k])) {
1122                k++; // match
1123
} else {
1124                if (nSkipped >= diff) {
1125                    return; // too different
1126
}
1127                indexSkipped[nSkipped++]= i;
1128            }
1129        }
1130
1131        ICompilationUnit cu= context.getCompilationUnit();
1132        CompilationUnit astRoot= context.getASTRoot();
1133
1134        // remove arguments
1135
{
1136            ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST());
1137
1138            for (int i= diff - 1; i >= 0; i--) {
1139                rewrite.remove((Expression) arguments.get(indexSkipped[i]), null);
1140            }
1141            String JavaDoc[] arg= new String JavaDoc[] { ASTResolving.getMethodSignature(methodRef, false) };
1142            String JavaDoc label;
1143            if (diff == 1) {
1144                label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_removeargument_description, arg);
1145            } else {
1146                label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_removearguments_description, arg);
1147            }
1148            Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_REMOVE);
1149            ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 8, image);
1150            proposals.add(proposal);
1151        }
1152
1153        IMethodBinding methodDecl= methodRef.getMethodDeclaration();
1154        ITypeBinding declaringType= methodDecl.getDeclaringClass();
1155
1156        // add parameters
1157
if (!declaringType.isFromSource()) {
1158            return;
1159        }
1160        ICompilationUnit targetCU= ASTResolving.findCompilationUnitForBinding(cu, astRoot, declaringType);
1161        if (targetCU != null) {
1162            boolean isDifferentCU= !cu.equals(targetCU);
1163
1164            if (isImplicitConstructor(methodDecl, targetCU)) {
1165                return;
1166            }
1167
1168            ChangeDescription[] changeDesc= new ChangeDescription[argTypes.length];
1169            ITypeBinding[] changeTypes= new ITypeBinding[diff];
1170            for (int i= diff - 1; i >= 0; i--) {
1171                int idx= indexSkipped[i];
1172                Expression arg= (Expression) arguments.get(idx);
1173                String JavaDoc name= arg instanceof SimpleName ? ((SimpleName) arg).getIdentifier() : null;
1174                ITypeBinding newType= Bindings.normalizeTypeBinding(argTypes[idx]);
1175                if (newType == null) {
1176                    newType= astRoot.getAST().resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
1177
}
1178                if (newType.isWildcardType()) {
1179                    newType= ASTResolving.normalizeWildcardType(newType, true, astRoot.getAST());
1180                }
1181                if (!ASTResolving.isUseableTypeInContext(newType, methodDecl, false)) {
1182                    return;
1183                }
1184                changeDesc[idx]= new InsertDescription(newType, name);
1185                changeTypes[i]= newType;
1186            }
1187            String JavaDoc[] arg= new String JavaDoc[] { ASTResolving.getMethodSignature(methodDecl, isDifferentCU), getTypeNames(changeTypes) };
1188            String JavaDoc label;
1189            if (methodDecl.isConstructor()) {
1190                if (diff == 1) {
1191                    label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_addparam_constr_description, arg);
1192                } else {
1193                    label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_addparams_constr_description, arg);
1194                }
1195            } else {
1196                if (diff == 1) {
1197                    label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_addparam_description, arg);
1198                } else {
1199                    label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_addparams_description, arg);
1200                }
1201            }
1202            Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD);
1203            ChangeMethodSignatureProposal proposal= new ChangeMethodSignatureProposal(label, targetCU, invocationNode, methodDecl, changeDesc, null, 5, image);
1204            proposals.add(proposal);
1205        }
1206    }
1207
1208    private static boolean isImplicitConstructor(IMethodBinding meth, ICompilationUnit targetCU) {
1209        return meth.isDefaultConstructor();
1210    }
1211
1212
1213
1214    private static ITypeBinding[] getParameterTypes(List JavaDoc args) {
1215        ITypeBinding[] params= new ITypeBinding[args.size()];
1216        for (int i= 0; i < args.size(); i++) {
1217            Expression expr= (Expression) args.get(i);
1218            ITypeBinding curr= Bindings.normalizeTypeBinding(expr.resolveTypeBinding());
1219            if (curr != null && curr.isWildcardType()) {
1220                curr= ASTResolving.normalizeWildcardType(curr, true, expr.getAST());
1221            }
1222            if (curr == null) {
1223                curr= expr.getAST().resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
1224
}
1225            params[i]= curr;
1226        }
1227        return params;
1228    }
1229
1230
1231
1232    private static void doEqualNumberOfParameters(IInvocationContext context, ASTNode invocationNode, IProblemLocation problem, List JavaDoc arguments, ITypeBinding[] argTypes, IMethodBinding methodBinding, Collection JavaDoc proposals) throws CoreException {
1233        ITypeBinding[] paramTypes= methodBinding.getParameterTypes();
1234        int[] indexOfDiff= new int[paramTypes.length];
1235        int nDiffs= 0;
1236        for (int n= 0; n < argTypes.length; n++) {
1237            if (!canAssign(argTypes[n], paramTypes[n])) {
1238                indexOfDiff[nDiffs++]= n;
1239            }
1240        }
1241        ITypeBinding declaringTypeDecl= methodBinding.getDeclaringClass().getTypeDeclaration();
1242
1243        ICompilationUnit cu= context.getCompilationUnit();
1244        CompilationUnit astRoot= context.getASTRoot();
1245
1246        ASTNode nameNode= problem.getCoveringNode(astRoot);
1247        if (nameNode == null) {
1248            return;
1249        }
1250
1251        if (nDiffs == 0) {
1252            if (nameNode.getParent() instanceof MethodInvocation) {
1253                MethodInvocation inv= (MethodInvocation) nameNode.getParent();
1254                if (inv.getExpression() == null) {
1255                    addQualifierToOuterProposal(context, inv, methodBinding, proposals);
1256                }
1257            }
1258            return;
1259        }
1260
1261        if (nDiffs == 1) { // one argument mismatching: try to fix
1262
int idx= indexOfDiff[0];
1263            Expression nodeToCast= (Expression) arguments.get(idx);
1264            ITypeBinding castType= paramTypes[idx];
1265            castType= Bindings.normalizeTypeBinding(castType);
1266            if (castType.isWildcardType()) {
1267                castType= ASTResolving.normalizeWildcardType(castType, false, nodeToCast.getAST());
1268            }
1269            if (castType != null) {
1270                ITypeBinding binding= nodeToCast.resolveTypeBinding();
1271                if (binding == null || binding.isCastCompatible(castType)) {
1272                    ASTRewriteCorrectionProposal proposal= TypeMismatchSubProcessor.createCastProposal(context, castType, nodeToCast, 6);
1273                    String JavaDoc castTypeName= BindingLabelProvider.getBindingLabel(castType, JavaElementLabels.ALL_DEFAULT);
1274                    String JavaDoc[] arg= new String JavaDoc[] { getArgumentName(cu, arguments, idx), castTypeName};
1275                    proposal.setDisplayName(Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_addargumentcast_description, arg));
1276                    proposals.add(proposal);
1277                }
1278                TypeMismatchSubProcessor.addChangeSenderTypeProposals(context, nodeToCast, castType, false, 5, proposals);
1279            }
1280        }
1281        if (nDiffs == 2) { // try to swap
1282
int idx1= indexOfDiff[0];
1283            int idx2= indexOfDiff[1];
1284            boolean canSwap= canAssign(argTypes[idx1], paramTypes[idx2]) && canAssign(argTypes[idx2], paramTypes[idx1]);
1285             if (canSwap) {
1286                Expression arg1= (Expression) arguments.get(idx1);
1287                Expression arg2= (Expression) arguments.get(idx2);
1288
1289                ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST());
1290                rewrite.replace(arg1, rewrite.createCopyTarget(arg2), null);
1291                rewrite.replace(arg2, rewrite.createCopyTarget(arg1), null);
1292                {
1293                    String JavaDoc[] arg= new String JavaDoc[] { getArgumentName(cu, arguments, idx1), getArgumentName(cu, arguments, idx2) };
1294                    String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_swaparguments_description, arg);
1295                    Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1296                    ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, 8, image);
1297                    proposals.add(proposal);
1298                }
1299
1300                if (declaringTypeDecl.isFromSource()) {
1301                    ICompilationUnit targetCU= ASTResolving.findCompilationUnitForBinding(cu, astRoot, declaringTypeDecl);
1302                    if (targetCU != null) {
1303                        ChangeDescription[] changeDesc= new ChangeDescription[paramTypes.length];
1304                        for (int i= 0; i < nDiffs; i++) {
1305                            changeDesc[idx1]= new SwapDescription(idx2);
1306                        }
1307                        IMethodBinding methodDecl= methodBinding.getMethodDeclaration();
1308                        ITypeBinding[] declParamTypes= methodDecl.getParameterTypes();
1309
1310                        ITypeBinding[] swappedTypes= new ITypeBinding[] { declParamTypes[idx1], declParamTypes[idx2] };
1311                        String JavaDoc[] args= new String JavaDoc[] { ASTResolving.getMethodSignature(methodDecl, !targetCU.equals(cu)), getTypeNames(swappedTypes) };
1312                        String JavaDoc label;
1313                        if (methodDecl.isConstructor()) {
1314                            label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_swapparams_constr_description, args);
1315                        } else {
1316                            label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_swapparams_description, args);
1317                        }
1318                        Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1319                        ChangeMethodSignatureProposal proposal= new ChangeMethodSignatureProposal(label, targetCU, invocationNode, methodDecl, changeDesc, null, 5, image);
1320                        proposals.add(proposal);
1321                    }
1322                }
1323                return;
1324            }
1325        }
1326
1327        if (declaringTypeDecl.isFromSource()) {
1328            ICompilationUnit targetCU= ASTResolving.findCompilationUnitForBinding(cu, astRoot, declaringTypeDecl);
1329            if (targetCU != null) {
1330                ChangeDescription[] changeDesc= createSignatureChangeDescription(indexOfDiff, nDiffs, paramTypes, arguments, argTypes);
1331                if (changeDesc != null) {
1332                
1333                    IMethodBinding methodDecl= methodBinding.getMethodDeclaration();
1334                    ITypeBinding[] declParamTypes= methodDecl.getParameterTypes();
1335    
1336                    ITypeBinding[] newParamTypes= new ITypeBinding[changeDesc.length];
1337                    for (int i= 0; i < newParamTypes.length; i++) {
1338                        newParamTypes[i]= changeDesc[i] == null ? declParamTypes[i] : ((EditDescription) changeDesc[i]).type;
1339                    }
1340                    boolean isVarArgs= methodDecl.isVarargs() && newParamTypes.length > 0 && newParamTypes[newParamTypes.length - 1].isArray();
1341                    String JavaDoc[] args= new String JavaDoc[] { ASTResolving.getMethodSignature(methodDecl, !targetCU.equals(cu)), ASTResolving.getMethodSignature(methodDecl.getName(), newParamTypes, isVarArgs) };
1342                    String JavaDoc label;
1343                    if (methodDecl.isConstructor()) {
1344                        label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changeparamsignature_constr_description, args);
1345                    } else {
1346                        label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changeparamsignature_description, args);
1347                    }
1348                    Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1349                    ChangeMethodSignatureProposal proposal= new ChangeMethodSignatureProposal(label, targetCU, invocationNode, methodDecl, changeDesc, null, 7, image);
1350                    proposals.add(proposal);
1351                }
1352            }
1353        }
1354    }
1355
1356    private static ChangeDescription[] createSignatureChangeDescription(int[] indexOfDiff, int nDiffs, ITypeBinding[] paramTypes, List JavaDoc arguments, ITypeBinding[] argTypes) {
1357        ChangeDescription[] changeDesc= new ChangeDescription[paramTypes.length];
1358        for (int i= 0; i < nDiffs; i++) {
1359            int diffIndex= indexOfDiff[i];
1360            Expression arg= (Expression) arguments.get(diffIndex);
1361            String JavaDoc name= arg instanceof SimpleName ? ((SimpleName) arg).getIdentifier() : null;
1362            ITypeBinding argType= argTypes[diffIndex];
1363            if (argType.isWildcardType()) {
1364                argType= ASTResolving.normalizeWildcardType(argType, true, arg.getAST());
1365                if (argType== null) {
1366                    return null;
1367                }
1368            }
1369            changeDesc[diffIndex]= new EditDescription(argType, name);
1370        }
1371        return changeDesc;
1372    }
1373
1374    private static ITypeBinding[] getArgumentTypes(List JavaDoc arguments) {
1375        ITypeBinding[] res= new ITypeBinding[arguments.size()];
1376        for (int i= 0; i < res.length; i++) {
1377            Expression expression= (Expression) arguments.get(i);
1378            ITypeBinding curr= expression.resolveTypeBinding();
1379            if (curr == null) {
1380                return null;
1381            }
1382            if (!curr.isNullType()) { // don't normalize null type
1383
curr= Bindings.normalizeTypeBinding(curr);
1384                if (curr == null) {
1385                    curr= expression.getAST().resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
1386
}
1387            }
1388            res[i]= curr;
1389        }
1390        return res;
1391    }
1392
1393    private static void addQualifierToOuterProposal(IInvocationContext context, MethodInvocation invocationNode, IMethodBinding binding, Collection JavaDoc proposals) throws CoreException {
1394        ITypeBinding declaringType= binding.getDeclaringClass();
1395        ITypeBinding parentType= Bindings.getBindingOfParentType(invocationNode);
1396        ITypeBinding currType= parentType;
1397
1398        boolean isInstanceMethod= !Modifier.isStatic(binding.getModifiers());
1399
1400        while (currType != null && !Bindings.isSuperType(declaringType, currType)) {
1401            if (isInstanceMethod && Modifier.isStatic(currType.getModifiers())) {
1402                return;
1403            }
1404            currType= currType.getDeclaringClass();
1405        }
1406        if (currType == null || currType == parentType) {
1407            return;
1408        }
1409
1410        ASTRewrite rewrite= ASTRewrite.create(invocationNode.getAST());
1411        
1412        String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_changetoouter_description, ASTResolving.getTypeSignature(currType));
1413        Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1414        ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, 8, image);
1415        
1416        ImportRewrite imports= proposal.createImportRewrite(context.getASTRoot());
1417        AST ast= invocationNode.getAST();
1418
1419        String JavaDoc qualifier= imports.addImport(currType);
1420        Name name= ASTNodeFactory.newName(ast, qualifier);
1421
1422        Expression newExpression;
1423        if (isInstanceMethod) {
1424            ThisExpression expr= ast.newThisExpression();
1425            expr.setQualifier(name);
1426            newExpression= expr;
1427        } else {
1428            newExpression= name;
1429        }
1430
1431        rewrite.set(invocationNode, MethodInvocation.EXPRESSION_PROPERTY, newExpression, null);
1432
1433        proposals.add(proposal);
1434    }
1435
1436
1437    public static void getConstructorProposals(IInvocationContext context, IProblemLocation problem, Collection JavaDoc proposals) throws CoreException {
1438        ICompilationUnit cu= context.getCompilationUnit();
1439
1440        CompilationUnit astRoot= context.getASTRoot();
1441        ASTNode selectedNode= problem.getCoveringNode(astRoot);
1442        if (selectedNode == null) {
1443            return;
1444        }
1445
1446        ITypeBinding targetBinding= null;
1447        List JavaDoc arguments= null;
1448        IMethodBinding recursiveConstructor= null;
1449
1450        int type= selectedNode.getNodeType();
1451        if (type == ASTNode.CLASS_INSTANCE_CREATION) {
1452            ClassInstanceCreation creation= (ClassInstanceCreation) selectedNode;
1453
1454            IBinding binding= creation.getType().resolveBinding();
1455            if (binding instanceof ITypeBinding) {
1456                targetBinding= (ITypeBinding) binding;
1457                arguments= creation.arguments();
1458            }
1459        } else if (type == ASTNode.SUPER_CONSTRUCTOR_INVOCATION) {
1460            ITypeBinding typeBinding= Bindings.getBindingOfParentType(selectedNode);
1461            if (typeBinding != null && !typeBinding.isAnonymous()) {
1462                targetBinding= typeBinding.getSuperclass();
1463                arguments= ((SuperConstructorInvocation) selectedNode).arguments();
1464            }
1465        } else if (type == ASTNode.CONSTRUCTOR_INVOCATION) {
1466            ITypeBinding typeBinding= Bindings.getBindingOfParentType(selectedNode);
1467            if (typeBinding != null && !typeBinding.isAnonymous()) {
1468                targetBinding= typeBinding;
1469                arguments= ((ConstructorInvocation) selectedNode).arguments();
1470                recursiveConstructor= ASTResolving.findParentMethodDeclaration(selectedNode).resolveBinding();
1471            }
1472        }
1473        if (targetBinding == null) {
1474            return;
1475        }
1476        IMethodBinding[] methods= targetBinding.getDeclaredMethods();
1477        ArrayList JavaDoc similarElements= new ArrayList JavaDoc();
1478        for (int i= 0; i < methods.length; i++) {
1479            IMethodBinding curr= methods[i];
1480            if (curr.isConstructor() && recursiveConstructor != curr) {
1481                similarElements.add(curr); // similar elements can contain a implicit default constructor
1482
}
1483        }
1484
1485        addParameterMissmatchProposals(context, problem, similarElements, selectedNode, arguments, proposals);
1486
1487        if (targetBinding.isFromSource()) {
1488            ITypeBinding targetDecl= targetBinding.getTypeDeclaration();
1489
1490            ICompilationUnit targetCU= ASTResolving.findCompilationUnitForBinding(cu, astRoot, targetDecl);
1491            if (targetCU != null) {
1492                String JavaDoc[] args= new String JavaDoc[] { ASTResolving.getMethodSignature( ASTResolving.getTypeSignature(targetDecl), getParameterTypes(arguments), false) };
1493                String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_createconstructor_description, args);
1494                Image image= JavaElementImageProvider.getDecoratedImage(JavaPluginImages.DESC_MISC_PUBLIC, JavaElementImageDescriptor.CONSTRUCTOR, JavaElementImageProvider.SMALL_SIZE);
1495                proposals.add(new NewMethodCompletionProposal(label, targetCU, selectedNode, arguments, targetDecl, 5, image));
1496            }
1497        }
1498    }
1499
1500    public static void getAmbiguosTypeReferenceProposals(IInvocationContext context, IProblemLocation problem, Collection JavaDoc proposals) throws CoreException {
1501        final ICompilationUnit cu= context.getCompilationUnit();
1502        int offset= problem.getOffset();
1503        int len= problem.getLength();
1504
1505        IJavaElement[] elements= cu.codeSelect(offset, len);
1506        for (int i= 0; i < elements.length; i++) {
1507            IJavaElement curr= elements[i];
1508            if (curr instanceof IType && !TypeFilter.isFiltered((IType) curr)) {
1509                String JavaDoc qualifiedTypeName= JavaModelUtil.getFullyQualifiedName((IType) curr);
1510
1511                CompilationUnit root= context.getASTRoot();
1512                
1513                String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_importexplicit_description, qualifiedTypeName);
1514                Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_IMPDECL);
1515                ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, ASTRewrite.create(root.getAST()), 5, image);
1516
1517                ImportRewrite imports= proposal.createImportRewrite(root);
1518                imports.addImport(qualifiedTypeName);
1519                
1520                proposals.add(proposal);
1521            }
1522        }
1523    }
1524
1525    public static void getArrayAccessProposals(IInvocationContext context, IProblemLocation problem, Collection JavaDoc proposals) {
1526
1527        CompilationUnit root= context.getASTRoot();
1528        ASTNode selectedNode= problem.getCoveringNode(root);
1529        if (!(selectedNode instanceof MethodInvocation)) {
1530            return;
1531        }
1532
1533        MethodInvocation decl= (MethodInvocation) selectedNode;
1534        SimpleName nameNode= decl.getName();
1535        String JavaDoc methodName= nameNode.getIdentifier();
1536
1537        IBinding[] bindings= (new ScopeAnalyzer(root)).getDeclarationsInScope(nameNode, ScopeAnalyzer.METHODS);
1538        for (int i= 0; i < bindings.length; i++) {
1539            String JavaDoc currName= bindings[i].getName();
1540            if (NameMatcher.isSimilarName(methodName, currName)) {
1541                String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_arraychangetomethod_description, currName);
1542                proposals.add(new RenameNodeCompletionProposal(label, context.getCompilationUnit(), nameNode.getStartPosition(), nameNode.getLength(), currName, 6));
1543            }
1544        }
1545        // always suggest 'length'
1546
String JavaDoc lengthId= "length"; //$NON-NLS-1$
1547
String JavaDoc label= CorrectionMessages.UnresolvedElementsSubProcessor_arraychangetolength_description;
1548        int offset= nameNode.getStartPosition();
1549        int length= decl.getStartPosition() + decl.getLength() - offset;
1550        proposals.add(new RenameNodeCompletionProposal(label, context.getCompilationUnit(), offset, length, lengthId, 7));
1551    }
1552
1553    public static void getAnnotationMemberProposals(IInvocationContext context, IProblemLocation problem, Collection JavaDoc proposals) throws CoreException {
1554        CompilationUnit astRoot= context.getASTRoot();
1555        ICompilationUnit cu= context.getCompilationUnit();
1556        ASTNode selectedNode= problem.getCoveringNode(astRoot);
1557
1558        Annotation annotation;
1559        String JavaDoc memberName;
1560        if (selectedNode.getLocationInParent() == MemberValuePair.NAME_PROPERTY) {
1561            if (selectedNode.getParent().getLocationInParent() != NormalAnnotation.VALUES_PROPERTY) {
1562                return;
1563            }
1564            annotation= (Annotation) selectedNode.getParent().getParent();
1565            memberName= ((SimpleName) selectedNode).getIdentifier();
1566        } else if (selectedNode.getLocationInParent() == SingleMemberAnnotation.VALUE_PROPERTY) {
1567            annotation= (Annotation) selectedNode.getParent();
1568            memberName= "value"; //$NON-NLS-1$
1569
} else {
1570            return;
1571        }
1572        
1573        ITypeBinding annotBinding= annotation.resolveTypeBinding();
1574        if (annotBinding == null) {
1575            return;
1576        }
1577
1578        
1579        if (annotation instanceof NormalAnnotation) {
1580            // similar names
1581
IMethodBinding[] otherMembers= annotBinding.getDeclaredMethods();
1582            for (int i= 0; i < otherMembers.length; i++) {
1583                IMethodBinding binding= otherMembers[i];
1584                String JavaDoc curr= binding.getName();
1585                int relevance= NameMatcher.isSimilarName(memberName, curr) ? 6 : 3;
1586                String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_UnresolvedElementsSubProcessor_changetoattribute_description, curr);
1587                proposals.add(new RenameNodeCompletionProposal(label, cu, problem.getOffset(), problem.getLength(), curr, relevance));
1588            }
1589        }
1590        
1591        if (annotBinding.isFromSource()) {
1592            ICompilationUnit targetCU= ASTResolving.findCompilationUnitForBinding(cu, astRoot, annotBinding);
1593            if (targetCU != null) {
1594                String JavaDoc label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_UnresolvedElementsSubProcessor_createattribute_description, memberName);
1595                Image image= JavaPluginImages.get(JavaPluginImages.IMG_MISC_PUBLIC);
1596                proposals.add(new NewAnnotationMemberProposal(label, targetCU, selectedNode, annotBinding, 5, image));
1597            }
1598        }
1599    }
1600
1601
1602}
1603
Popular Tags