KickJava   Java API By Example, From Geeks To Geeks.

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


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 package org.eclipse.jdt.internal.ui.text.correction;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Collection JavaDoc;
15
16 import org.eclipse.core.runtime.CoreException;
17
18 import org.eclipse.swt.graphics.Image;
19
20 import org.eclipse.jdt.core.ICompilationUnit;
21 import org.eclipse.jdt.core.JavaModelException;
22 import org.eclipse.jdt.core.dom.AST;
23 import org.eclipse.jdt.core.dom.ASTNode;
24 import org.eclipse.jdt.core.dom.ArrayInitializer;
25 import org.eclipse.jdt.core.dom.Assignment;
26 import org.eclipse.jdt.core.dom.BodyDeclaration;
27 import org.eclipse.jdt.core.dom.CastExpression;
28 import org.eclipse.jdt.core.dom.CompilationUnit;
29 import org.eclipse.jdt.core.dom.Expression;
30 import org.eclipse.jdt.core.dom.FieldAccess;
31 import org.eclipse.jdt.core.dom.IBinding;
32 import org.eclipse.jdt.core.dom.IMethodBinding;
33 import org.eclipse.jdt.core.dom.ITypeBinding;
34 import org.eclipse.jdt.core.dom.IVariableBinding;
35 import org.eclipse.jdt.core.dom.MemberValuePair;
36 import org.eclipse.jdt.core.dom.MethodDeclaration;
37 import org.eclipse.jdt.core.dom.MethodInvocation;
38 import org.eclipse.jdt.core.dom.Name;
39 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
40 import org.eclipse.jdt.core.dom.SuperFieldAccess;
41 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
42 import org.eclipse.jdt.core.dom.Type;
43 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
44 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
45 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
46
47 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
48 import org.eclipse.jdt.internal.corext.dom.Bindings;
49 import org.eclipse.jdt.internal.corext.util.Messages;
50
51 import org.eclipse.jdt.ui.JavaElementLabels;
52 import org.eclipse.jdt.ui.text.java.IInvocationContext;
53 import org.eclipse.jdt.ui.text.java.IProblemLocation;
54
55 import org.eclipse.jdt.internal.ui.JavaPluginImages;
56 import org.eclipse.jdt.internal.ui.text.correction.ChangeMethodSignatureProposal.ChangeDescription;
57 import org.eclipse.jdt.internal.ui.text.correction.ChangeMethodSignatureProposal.InsertDescription;
58 import org.eclipse.jdt.internal.ui.text.correction.ChangeMethodSignatureProposal.RemoveDescription;
59 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
60
61
62 public class TypeMismatchSubProcessor {
63
64     private TypeMismatchSubProcessor() {
65     }
66
67     public static void addTypeMismatchProposals(IInvocationContext context, IProblemLocation problem, Collection JavaDoc proposals) throws CoreException {
68         String JavaDoc[] args= problem.getProblemArguments();
69         if (args.length != 2) {
70             return;
71         }
72
73         ICompilationUnit cu= context.getCompilationUnit();
74
75         CompilationUnit astRoot= context.getASTRoot();
76         AST ast= astRoot.getAST();
77         
78         ASTNode selectedNode= problem.getCoveredNode(astRoot);
79         if (!(selectedNode instanceof Expression)) {
80             return;
81         }
82         Expression nodeToCast= (Expression) selectedNode;
83         Name receiverNode= null;
84         ITypeBinding castTypeBinding= null;
85
86         int parentNodeType= selectedNode.getParent().getNodeType();
87         if (parentNodeType == ASTNode.ASSIGNMENT) {
88             Assignment assign= (Assignment) selectedNode.getParent();
89             Expression leftHandSide= assign.getLeftHandSide();
90             if (selectedNode.equals(leftHandSide)) {
91                 nodeToCast= assign.getRightHandSide();
92             }
93             castTypeBinding= assign.getLeftHandSide().resolveTypeBinding();
94             if (leftHandSide instanceof Name) {
95                 receiverNode= (Name) leftHandSide;
96             } else if (leftHandSide instanceof FieldAccess) {
97                 receiverNode= ((FieldAccess) leftHandSide).getName();
98             }
99         } else if (parentNodeType == ASTNode.VARIABLE_DECLARATION_FRAGMENT) {
100             VariableDeclarationFragment frag= (VariableDeclarationFragment) selectedNode.getParent();
101             if (selectedNode.equals(frag.getName()) || selectedNode.equals(frag.getInitializer())) {
102                 nodeToCast= frag.getInitializer();
103                 castTypeBinding= ASTNodes.getType(frag).resolveBinding();
104                 receiverNode= frag.getName();
105             }
106         } else if (parentNodeType == ASTNode.MEMBER_VALUE_PAIR) {
107             receiverNode= ((MemberValuePair) selectedNode.getParent()).getName();
108             castTypeBinding= ASTResolving.guessBindingForReference(nodeToCast);
109         } else if (parentNodeType == ASTNode.SINGLE_MEMBER_ANNOTATION) {
110             receiverNode= ((SingleMemberAnnotation) selectedNode.getParent()).getTypeName(); // use the type name
111
castTypeBinding= ASTResolving.guessBindingForReference(nodeToCast);
112         } else {
113             // try to find the binding corresponding to 'castTypeName'
114
castTypeBinding= ASTResolving.guessBindingForReference(nodeToCast);
115         }
116         if (castTypeBinding == null) {
117             return;
118         }
119
120         if (!(nodeToCast instanceof ArrayInitializer)) {
121             ITypeBinding binding= nodeToCast.resolveTypeBinding();
122             if (binding == null || binding.isCastCompatible(castTypeBinding) || nodeToCast instanceof CastExpression) {
123                 proposals.add(createCastProposal(context, castTypeBinding, nodeToCast, 7));
124             }
125         }
126
127         ITypeBinding currBinding= nodeToCast.resolveTypeBinding();
128
129         boolean nullOrVoid= currBinding == null || "void".equals(currBinding.getName()); //$NON-NLS-1$
130

131         // change method return statement to actual type
132
if (!nullOrVoid && parentNodeType == ASTNode.RETURN_STATEMENT) {
133             BodyDeclaration decl= ASTResolving.findParentBodyDeclaration(selectedNode);
134             if (decl instanceof MethodDeclaration) {
135                 MethodDeclaration methodDeclaration= (MethodDeclaration) decl;
136
137
138                 currBinding= Bindings.normalizeTypeBinding(currBinding);
139                 if (currBinding == null) {
140                     currBinding= ast.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
141
}
142                 if (currBinding.isWildcardType()) {
143                     currBinding= ASTResolving.normalizeWildcardType(currBinding, true, ast);
144                 }
145
146                 ASTRewrite rewrite= ASTRewrite.create(ast);
147
148                 String JavaDoc label= Messages.format(CorrectionMessages.TypeMismatchSubProcessor_changereturntype_description, currBinding.getName());
149                 Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
150                 LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, 6, image);
151
152                 ImportRewrite imports= proposal.createImportRewrite(astRoot);
153
154                 Type newReturnType= imports.addImport(currBinding, ast);
155                 rewrite.replace(methodDeclaration.getReturnType2(), newReturnType, null);
156
157                 String JavaDoc returnKey= "return"; //$NON-NLS-1$
158
proposal.addLinkedPosition(rewrite.track(newReturnType), true, returnKey);
159                 ITypeBinding[] typeSuggestions= ASTResolving.getRelaxingTypes(ast, currBinding);
160                 for (int i= 0; i < typeSuggestions.length; i++) {
161                     proposal.addLinkedPositionProposal(returnKey, typeSuggestions[i]);
162                 }
163                 proposals.add(proposal);
164             }
165         }
166
167         if (!nullOrVoid && receiverNode != null) {
168             currBinding= Bindings.normalizeTypeBinding(currBinding);
169             if (currBinding == null) {
170                 currBinding= ast.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
171
}
172             if (currBinding.isWildcardType()) {
173                 currBinding= ASTResolving.normalizeWildcardType(currBinding, true, ast);
174             }
175             addChangeSenderTypeProposals(context, receiverNode, currBinding, true, 6, proposals);
176         }
177
178         addChangeSenderTypeProposals(context, nodeToCast, castTypeBinding, false, 5, proposals);
179     }
180
181     public static void addChangeSenderTypeProposals(IInvocationContext context, Expression nodeToCast, ITypeBinding castTypeBinding, boolean isAssignedNode, int relevance, Collection JavaDoc proposals) throws JavaModelException {
182         IBinding callerBinding= null;
183         switch (nodeToCast.getNodeType()) {
184             case ASTNode.METHOD_INVOCATION:
185                 callerBinding= ((MethodInvocation) nodeToCast).resolveMethodBinding();
186                 break;
187             case ASTNode.SUPER_METHOD_INVOCATION:
188                 callerBinding= ((SuperMethodInvocation) nodeToCast).resolveMethodBinding();
189                 break;
190             case ASTNode.FIELD_ACCESS:
191                 callerBinding= ((FieldAccess) nodeToCast).resolveFieldBinding();
192                 break;
193             case ASTNode.SUPER_FIELD_ACCESS:
194                 callerBinding= ((SuperFieldAccess) nodeToCast).resolveFieldBinding();
195                 break;
196             case ASTNode.SIMPLE_NAME:
197             case ASTNode.QUALIFIED_NAME:
198                 callerBinding= ((Name) nodeToCast).resolveBinding();
199                 break;
200         }
201
202         ICompilationUnit cu= context.getCompilationUnit();
203         CompilationUnit astRoot= context.getASTRoot();
204
205         ICompilationUnit targetCu= null;
206         ITypeBinding declaringType= null;
207         IBinding callerBindingDecl= callerBinding;
208         if (callerBinding instanceof IVariableBinding) {
209             IVariableBinding variableBinding= (IVariableBinding) callerBinding;
210
211             if (variableBinding.isEnumConstant()) {
212                 return;
213             }
214             if (!variableBinding.isField()) {
215                 targetCu= cu;
216             } else {
217                 callerBindingDecl= variableBinding.getVariableDeclaration();
218                 ITypeBinding declaringClass= variableBinding.getDeclaringClass();
219                 if (declaringClass == null) {
220                     return; // array length
221
}
222                 declaringType= declaringClass.getTypeDeclaration();
223             }
224         } else if (callerBinding instanceof IMethodBinding) {
225             IMethodBinding methodBinding= (IMethodBinding) callerBinding;
226             if (!methodBinding.isConstructor()) {
227                 declaringType= methodBinding.getDeclaringClass().getTypeDeclaration();
228                 callerBindingDecl= methodBinding.getMethodDeclaration();
229             }
230         } else if (callerBinding instanceof ITypeBinding && nodeToCast.getLocationInParent() == SingleMemberAnnotation.TYPE_NAME_PROPERTY) {
231             declaringType= (ITypeBinding) callerBinding;
232             callerBindingDecl= Bindings.findMethodInType(declaringType, "value", (String JavaDoc[]) null); //$NON-NLS-1$
233
if (callerBindingDecl == null) {
234                 return;
235             }
236         }
237
238         if (declaringType != null && declaringType.isFromSource()) {
239             targetCu= ASTResolving.findCompilationUnitForBinding(cu, astRoot, declaringType);
240         }
241         if (targetCu != null && ASTResolving.isUseableTypeInContext(castTypeBinding, callerBindingDecl, false)) {
242             proposals.add(new TypeChangeCompletionProposal(targetCu, callerBindingDecl, astRoot, castTypeBinding, isAssignedNode, relevance));
243         }
244
245         // add interface to resulting type
246
if (!isAssignedNode) {
247             ITypeBinding nodeType= nodeToCast.resolveTypeBinding();
248             if (castTypeBinding.isInterface() && nodeType != null && nodeType.isClass() && !nodeType.isAnonymous() && nodeType.isFromSource()) {
249                 ITypeBinding typeDecl= nodeType.getTypeDeclaration();
250                 ICompilationUnit nodeCu= ASTResolving.findCompilationUnitForBinding(cu, astRoot, typeDecl);
251                 if (nodeCu != null && ASTResolving.isUseableTypeInContext(castTypeBinding, typeDecl, true)) {
252                     proposals.add(new ImplementInterfaceProposal(nodeCu, typeDecl, astRoot, castTypeBinding, relevance - 1));
253                 }
254             }
255         }
256     }
257
258     public static ASTRewriteCorrectionProposal createCastProposal(IInvocationContext context, ITypeBinding castTypeBinding, Expression nodeToCast, int relevance) {
259         ICompilationUnit cu= context.getCompilationUnit();
260
261         String JavaDoc label;
262         String JavaDoc castType= BindingLabelProvider.getBindingLabel(castTypeBinding, JavaElementLabels.ALL_DEFAULT);
263         if (nodeToCast.getNodeType() == ASTNode.CAST_EXPRESSION) {
264             label= Messages.format(CorrectionMessages.TypeMismatchSubProcessor_changecast_description, castType);
265         } else {
266             label= Messages.format(CorrectionMessages.TypeMismatchSubProcessor_addcast_description, castType);
267         }
268         return new CastCompletionProposal(label, cu, nodeToCast, castTypeBinding, relevance);
269     }
270
271     public static void addIncompatibleReturnTypeProposals(IInvocationContext context, IProblemLocation problem, Collection JavaDoc proposals) throws JavaModelException {
272         CompilationUnit astRoot= context.getASTRoot();
273         ASTNode selectedNode= problem.getCoveringNode(astRoot);
274         if (selectedNode == null) {
275             return;
276         }
277         MethodDeclaration decl= ASTResolving.findParentMethodDeclaration(selectedNode);
278         if (decl == null) {
279             return;
280         }
281         IMethodBinding methodDeclBinding= decl.resolveBinding();
282         if (methodDeclBinding == null) {
283             return;
284         }
285
286         IMethodBinding overridden= Bindings.findOverriddenMethod(methodDeclBinding, false);
287         if (overridden == null || overridden.getReturnType() == methodDeclBinding.getReturnType()) {
288             return;
289         }
290
291
292         ICompilationUnit cu= context.getCompilationUnit();
293         IMethodBinding methodDecl= methodDeclBinding.getMethodDeclaration();
294         proposals.add(new TypeChangeCompletionProposal(cu, methodDecl, astRoot, overridden.getReturnType(), false, 8));
295
296         ICompilationUnit targetCu= cu;
297
298         IMethodBinding overriddenDecl= overridden.getMethodDeclaration();
299         ITypeBinding overridenDeclType= overriddenDecl.getDeclaringClass();
300
301         ITypeBinding returnType= methodDeclBinding.getReturnType();
302         if (overridenDeclType.isFromSource()) {
303             targetCu= ASTResolving.findCompilationUnitForBinding(cu, astRoot, overridenDeclType);
304         }
305         if (targetCu != null && ASTResolving.isUseableTypeInContext(returnType, overriddenDecl, false)) {
306             TypeChangeCompletionProposal proposal= new TypeChangeCompletionProposal(targetCu, overriddenDecl, astRoot, returnType, false, 7);
307             if (overridenDeclType.isInterface()) {
308                 proposal.setDisplayName(Messages.format(CorrectionMessages.TypeMismatchSubProcessor_changereturnofimplemented_description, overriddenDecl.getName()));
309             } else {
310                 proposal.setDisplayName(Messages.format(CorrectionMessages.TypeMismatchSubProcessor_changereturnofoverridden_description, overriddenDecl.getName()));
311             }
312             proposals.add(proposal);
313         }
314     }
315
316     public static void addIncompatibleThrowsProposals(IInvocationContext context, IProblemLocation problem, Collection JavaDoc proposals) throws JavaModelException {
317         CompilationUnit astRoot= context.getASTRoot();
318         ASTNode selectedNode= problem.getCoveringNode(astRoot);
319         if (!(selectedNode instanceof MethodDeclaration)) {
320             return;
321         }
322         MethodDeclaration decl= (MethodDeclaration) selectedNode;
323         IMethodBinding methodDeclBinding= decl.resolveBinding();
324         if (methodDeclBinding == null) {
325             return;
326         }
327
328         IMethodBinding overridden= Bindings.findOverriddenMethod(methodDeclBinding, false);
329         if (overridden == null) {
330             return;
331         }
332
333         ICompilationUnit cu= context.getCompilationUnit();
334
335         ITypeBinding[] methodExceptions= methodDeclBinding.getExceptionTypes();
336         ITypeBinding[] definedExceptions= overridden.getExceptionTypes();
337
338         ArrayList JavaDoc undeclaredExceptions= new ArrayList JavaDoc();
339         {
340             ChangeDescription[] changes= new ChangeDescription[methodExceptions.length];
341
342             for (int i= 0; i < methodExceptions.length; i++) {
343                 if (!isDeclaredException(methodExceptions[i], definedExceptions)) {
344                     changes[i]= new RemoveDescription();
345                     undeclaredExceptions.add(methodExceptions[i]);
346                 }
347             }
348             String JavaDoc label= Messages.format(CorrectionMessages.TypeMismatchSubProcessor_removeexceptions_description, methodDeclBinding.getName());
349             Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_REMOVE);
350             proposals.add(new ChangeMethodSignatureProposal(label, cu, astRoot, methodDeclBinding, null, changes, 8, image));
351         }
352
353         ITypeBinding declaringType= overridden.getDeclaringClass();
354         ICompilationUnit targetCu= cu;
355         if (declaringType.isFromSource()) {
356             targetCu= ASTResolving.findCompilationUnitForBinding(cu, astRoot, declaringType);
357         }
358         if (targetCu != null) {
359             ChangeDescription[] changes= new ChangeDescription[definedExceptions.length + undeclaredExceptions.size()];
360
361             for (int i= 0; i < undeclaredExceptions.size(); i++) {
362                 changes[i + definedExceptions.length]= new InsertDescription((ITypeBinding) undeclaredExceptions.get(i), ""); //$NON-NLS-1$
363
}
364             IMethodBinding overriddenDecl= overridden.getMethodDeclaration();
365             String JavaDoc[] args= { declaringType.getName(), overridden.getName() };
366             String JavaDoc label= Messages.format(CorrectionMessages.TypeMismatchSubProcessor_addexceptions_description, args);
367             Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD);
368             proposals.add(new ChangeMethodSignatureProposal(label, targetCu, astRoot, overriddenDecl, null, changes, 7, image));
369         }
370     }
371
372     private static boolean isDeclaredException(ITypeBinding curr, ITypeBinding[] declared) {
373         for (int i= 0; i < declared.length; i++) {
374             if (Bindings.isSuperType(declared[i], curr)) {
375                 return true;
376             }
377         }
378         return false;
379     }
380
381
382 }
383
Popular Tags