1 11 package org.eclipse.jdt.internal.ui.text.correction; 12 13 import java.util.ArrayList ; 14 import java.util.Collection ; 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 proposals) throws CoreException { 68 String [] 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(); castTypeBinding= ASTResolving.guessBindingForReference(nodeToCast); 112 } else { 113 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()); 131 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"); } 142 if (currBinding.isWildcardType()) { 143 currBinding= ASTResolving.normalizeWildcardType(currBinding, true, ast); 144 } 145 146 ASTRewrite rewrite= ASTRewrite.create(ast); 147 148 String 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 returnKey= "return"; 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"); } 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 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; } 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 []) null); 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 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 label; 262 String 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 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 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 undeclaredExceptions= new ArrayList (); 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 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), ""); } 364 IMethodBinding overriddenDecl= overridden.getMethodDeclaration(); 365 String [] args= { declaringType.getName(), overridden.getName() }; 366 String 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 |