| /******************************************************************************* |
| * Copyright (c) 2000, 2011 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.ui.text.correction; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| |
| import org.eclipse.swt.graphics.Image; |
| |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.dom.AST; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.ASTVisitor; |
| import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; |
| import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration; |
| import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; |
| import org.eclipse.jdt.core.dom.Block; |
| import org.eclipse.jdt.core.dom.BodyDeclaration; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.EnumDeclaration; |
| import org.eclipse.jdt.core.dom.Expression; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| import org.eclipse.jdt.core.dom.Javadoc; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.PrimitiveType; |
| import org.eclipse.jdt.core.dom.ReturnStatement; |
| import org.eclipse.jdt.core.dom.TagElement; |
| import org.eclipse.jdt.core.dom.TextElement; |
| import org.eclipse.jdt.core.dom.Type; |
| import org.eclipse.jdt.core.dom.TypeDeclaration; |
| import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; |
| |
| import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext; |
| import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
| import org.eclipse.jdt.internal.corext.dom.Bindings; |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| |
| import org.eclipse.jdt.ui.text.java.IInvocationContext; |
| import org.eclipse.jdt.ui.text.java.IProblemLocation; |
| import org.eclipse.jdt.ui.text.java.correction.ASTRewriteCorrectionProposal; |
| import org.eclipse.jdt.ui.text.java.correction.ICommandAccess; |
| |
| import org.eclipse.jdt.internal.ui.JavaPluginImages; |
| import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedCorrectionProposal; |
| import org.eclipse.jdt.internal.ui.text.correction.proposals.MissingReturnTypeCorrectionProposal; |
| import org.eclipse.jdt.internal.ui.text.correction.proposals.ReplaceCorrectionProposal; |
| import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; |
| import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider; |
| |
| |
| public class ReturnTypeSubProcessor { |
| |
| private static class ReturnStatementCollector extends ASTVisitor { |
| private ArrayList<ReturnStatement> fResult= new ArrayList<ReturnStatement>(); |
| |
| public ITypeBinding getTypeBinding(AST ast) { |
| boolean couldBeObject= false; |
| for (int i= 0; i < fResult.size(); i++) { |
| ReturnStatement node= fResult.get(i); |
| Expression expr= node.getExpression(); |
| if (expr != null) { |
| ITypeBinding binding= Bindings.normalizeTypeBinding(expr.resolveTypeBinding()); |
| if (binding != null) { |
| return binding; |
| } else { |
| couldBeObject= true; |
| } |
| } else { |
| return ast.resolveWellKnownType("void"); //$NON-NLS-1$ |
| } |
| } |
| if (couldBeObject) { |
| return ast.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$ |
| } |
| return ast.resolveWellKnownType("void"); //$NON-NLS-1$ |
| } |
| |
| @Override |
| public boolean visit(ReturnStatement node) { |
| fResult.add(node); |
| return false; |
| } |
| |
| @Override |
| public boolean visit(AnonymousClassDeclaration node) { |
| return false; |
| } |
| |
| @Override |
| public boolean visit(TypeDeclaration node) { |
| return false; |
| } |
| |
| @Override |
| public boolean visit(EnumDeclaration node) { |
| return false; |
| } |
| |
| @Override |
| public boolean visit(AnnotationTypeDeclaration node) { |
| return false; |
| } |
| |
| } |
| |
| |
| public static void addMethodWithConstrNameProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) { |
| ICompilationUnit cu= context.getCompilationUnit(); |
| |
| ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot()); |
| if (selectedNode instanceof MethodDeclaration) { |
| MethodDeclaration declaration= (MethodDeclaration) selectedNode; |
| |
| ASTRewrite rewrite= ASTRewrite.create(declaration.getAST()); |
| rewrite.set(declaration, MethodDeclaration.CONSTRUCTOR_PROPERTY, Boolean.TRUE, null); |
| |
| String label= CorrectionMessages.ReturnTypeSubProcessor_constrnamemethod_description; |
| Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE); |
| ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 5, image); |
| proposals.add(proposal); |
| } |
| |
| } |
| |
| public static void addVoidMethodReturnsProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) { |
| ICompilationUnit cu= context.getCompilationUnit(); |
| |
| CompilationUnit astRoot= context.getASTRoot(); |
| ASTNode selectedNode= problem.getCoveringNode(astRoot); |
| if (selectedNode == null) { |
| return; |
| } |
| |
| BodyDeclaration decl= ASTResolving.findParentBodyDeclaration(selectedNode); |
| if (decl instanceof MethodDeclaration && selectedNode.getNodeType() == ASTNode.RETURN_STATEMENT) { |
| ReturnStatement returnStatement= (ReturnStatement) selectedNode; |
| Expression expr= returnStatement.getExpression(); |
| if (expr != null) { |
| AST ast= astRoot.getAST(); |
| |
| ITypeBinding binding= Bindings.normalizeTypeBinding(expr.resolveTypeBinding()); |
| if (binding == null) { |
| binding= ast.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$ |
| } |
| if (binding.isWildcardType()) { |
| binding= ASTResolving.normalizeWildcardType(binding, true, ast); |
| } |
| |
| MethodDeclaration methodDeclaration= (MethodDeclaration) decl; |
| |
| ASTRewrite rewrite= ASTRewrite.create(ast); |
| |
| String label= Messages.format(CorrectionMessages.ReturnTypeSubProcessor_voidmethodreturns_description, BindingLabelProvider.getBindingLabel(binding, BindingLabelProvider.DEFAULT_TEXTFLAGS)); |
| Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE); |
| LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, 6, image); |
| ImportRewrite imports= proposal.createImportRewrite(astRoot); |
| ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(methodDeclaration, imports); |
| Type newReturnType= imports.addImport(binding, ast, importRewriteContext); |
| |
| if (methodDeclaration.isConstructor()) { |
| rewrite.set(methodDeclaration, MethodDeclaration.CONSTRUCTOR_PROPERTY, Boolean.FALSE, null); |
| rewrite.set(methodDeclaration, MethodDeclaration.RETURN_TYPE2_PROPERTY, newReturnType, null); |
| } else { |
| rewrite.replace(methodDeclaration.getReturnType2(), newReturnType, null); |
| } |
| String key= "return_type"; //$NON-NLS-1$ |
| proposal.addLinkedPosition(rewrite.track(newReturnType), true, key); |
| ITypeBinding[] bindings= ASTResolving.getRelaxingTypes(ast, binding); |
| for (int i= 0; i < bindings.length; i++) { |
| proposal.addLinkedPositionProposal(key, bindings[i]); |
| } |
| |
| Javadoc javadoc= methodDeclaration.getJavadoc(); |
| if (javadoc != null) { |
| TagElement newTag= ast.newTagElement(); |
| newTag.setTagName(TagElement.TAG_RETURN); |
| TextElement commentStart= ast.newTextElement(); |
| newTag.fragments().add(commentStart); |
| |
| JavadocTagsSubProcessor.insertTag(rewrite.getListRewrite(javadoc, Javadoc.TAGS_PROPERTY), newTag, null); |
| proposal.addLinkedPosition(rewrite.track(commentStart), false, "comment_start"); //$NON-NLS-1$ |
| |
| } |
| proposals.add(proposal); |
| } |
| ASTRewrite rewrite= ASTRewrite.create(decl.getAST()); |
| rewrite.remove(returnStatement.getExpression(), null); |
| |
| String label= CorrectionMessages.ReturnTypeSubProcessor_removereturn_description; |
| Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE); |
| ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 5, image); |
| proposals.add(proposal); |
| } |
| } |
| |
| |
| |
| public static void addMissingReturnTypeProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) { |
| ICompilationUnit cu= context.getCompilationUnit(); |
| |
| CompilationUnit astRoot= context.getASTRoot(); |
| ASTNode selectedNode= problem.getCoveringNode(astRoot); |
| if (selectedNode == null) { |
| return; |
| } |
| BodyDeclaration decl= ASTResolving.findParentBodyDeclaration(selectedNode); |
| if (decl instanceof MethodDeclaration) { |
| MethodDeclaration methodDeclaration= (MethodDeclaration) decl; |
| |
| ReturnStatementCollector eval= new ReturnStatementCollector(); |
| decl.accept(eval); |
| |
| AST ast= astRoot.getAST(); |
| |
| ITypeBinding typeBinding= eval.getTypeBinding(decl.getAST()); |
| typeBinding= Bindings.normalizeTypeBinding(typeBinding); |
| if (typeBinding == null) { |
| typeBinding= ast.resolveWellKnownType("void"); //$NON-NLS-1$ |
| } |
| if (typeBinding.isWildcardType()) { |
| typeBinding= ASTResolving.normalizeWildcardType(typeBinding, true, ast); |
| } |
| |
| ASTRewrite rewrite= ASTRewrite.create(ast); |
| |
| String label= Messages.format(CorrectionMessages.ReturnTypeSubProcessor_missingreturntype_description, BindingLabelProvider.getBindingLabel(typeBinding, BindingLabelProvider.DEFAULT_TEXTFLAGS)); |
| Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE); |
| LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, 6, image); |
| |
| ImportRewrite imports= proposal.createImportRewrite(astRoot); |
| ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(decl, imports); |
| Type type= imports.addImport(typeBinding, ast, importRewriteContext); |
| |
| rewrite.set(methodDeclaration, MethodDeclaration.RETURN_TYPE2_PROPERTY, type, null); |
| rewrite.set(methodDeclaration, MethodDeclaration.CONSTRUCTOR_PROPERTY, Boolean.FALSE, null); |
| |
| Javadoc javadoc= methodDeclaration.getJavadoc(); |
| if (javadoc != null && typeBinding != null) { |
| TagElement newTag= ast.newTagElement(); |
| newTag.setTagName(TagElement.TAG_RETURN); |
| TextElement commentStart= ast.newTextElement(); |
| newTag.fragments().add(commentStart); |
| |
| JavadocTagsSubProcessor.insertTag(rewrite.getListRewrite(javadoc, Javadoc.TAGS_PROPERTY), newTag, null); |
| proposal.addLinkedPosition(rewrite.track(commentStart), false, "comment_start"); //$NON-NLS-1$ |
| } |
| |
| String key= "return_type"; //$NON-NLS-1$ |
| proposal.addLinkedPosition(rewrite.track(type), true, key); |
| if (typeBinding != null) { |
| ITypeBinding[] bindings= ASTResolving.getRelaxingTypes(ast, typeBinding); |
| for (int i= 0; i < bindings.length; i++) { |
| proposal.addLinkedPositionProposal(key, bindings[i]); |
| } |
| } |
| |
| proposals.add(proposal); |
| |
| // change to constructor |
| ASTNode parentType= ASTResolving.findParentType(decl); |
| if (parentType instanceof AbstractTypeDeclaration) { |
| boolean isInterface= parentType instanceof TypeDeclaration && ((TypeDeclaration) parentType).isInterface(); |
| if (!isInterface) { |
| String constructorName= ((AbstractTypeDeclaration) parentType).getName().getIdentifier(); |
| ASTNode nameNode= methodDeclaration.getName(); |
| label= Messages.format(CorrectionMessages.ReturnTypeSubProcessor_wrongconstructorname_description, BasicElementLabels.getJavaElementName(constructorName)); |
| proposals.add(new ReplaceCorrectionProposal(label, cu, nameNode.getStartPosition(), nameNode.getLength(), constructorName, 5)); |
| } |
| } |
| } |
| } |
| |
| public static void addMissingReturnStatementProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) { |
| ICompilationUnit cu= context.getCompilationUnit(); |
| |
| ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot()); |
| if (selectedNode == null) { |
| return; |
| } |
| BodyDeclaration decl= ASTResolving.findParentBodyDeclaration(selectedNode); |
| if (decl instanceof MethodDeclaration) { |
| MethodDeclaration methodDecl= (MethodDeclaration) decl; |
| Block block= methodDecl.getBody(); |
| if (block == null) { |
| return; |
| } |
| ReturnStatement existingStatement= (selectedNode instanceof ReturnStatement) ? (ReturnStatement) selectedNode : null; |
| proposals.add( new MissingReturnTypeCorrectionProposal(cu, methodDecl, existingStatement, 6)); |
| |
| Type returnType= methodDecl.getReturnType2(); |
| if (returnType != null && !"void".equals(ASTNodes.asString(returnType))) { //$NON-NLS-1$ |
| AST ast= methodDecl.getAST(); |
| ASTRewrite rewrite= ASTRewrite.create(ast); |
| rewrite.replace(returnType, ast.newPrimitiveType(PrimitiveType.VOID), null); |
| Javadoc javadoc= methodDecl.getJavadoc(); |
| if (javadoc != null) { |
| TagElement tagElement= JavadocTagsSubProcessor.findTag(javadoc, TagElement.TAG_RETURN, null); |
| if (tagElement != null) { |
| rewrite.remove(tagElement, null); |
| } |
| } |
| |
| String label= CorrectionMessages.ReturnTypeSubProcessor_changetovoid_description; |
| Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE); |
| ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, cu, rewrite, 5, image); |
| proposals.add(proposal); |
| } |
| } |
| } |
| |
| public static void addMethodRetunsVoidProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws JavaModelException { |
| CompilationUnit astRoot= context.getASTRoot(); |
| ASTNode selectedNode= problem.getCoveringNode(astRoot); |
| if (!(selectedNode instanceof ReturnStatement)) { |
| return; |
| } |
| ReturnStatement returnStatement= (ReturnStatement) selectedNode; |
| Expression expression= returnStatement.getExpression(); |
| if (expression == null) { |
| return; |
| } |
| BodyDeclaration decl= ASTResolving.findParentBodyDeclaration(selectedNode); |
| if (decl instanceof MethodDeclaration) { |
| MethodDeclaration methDecl= (MethodDeclaration) decl; |
| Type retType= methDecl.getReturnType2(); |
| if (retType == null || retType.resolveBinding() == null) { |
| return; |
| } |
| TypeMismatchSubProcessor.addChangeSenderTypeProposals(context, expression, retType.resolveBinding(), false, 4, proposals); |
| } |
| } |
| } |