| /******************************************************************************* |
| * Copyright (c) 2000, 2005 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.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.CoreException; |
| |
| import org.eclipse.swt.graphics.Image; |
| |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.NamingConventions; |
| import org.eclipse.jdt.core.Signature; |
| import org.eclipse.jdt.core.dom.AST; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; |
| import org.eclipse.jdt.core.dom.ArrayType; |
| import org.eclipse.jdt.core.dom.ClassInstanceCreation; |
| import org.eclipse.jdt.core.dom.Expression; |
| import org.eclipse.jdt.core.dom.ExpressionStatement; |
| import org.eclipse.jdt.core.dom.IBinding; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.MethodInvocation; |
| import org.eclipse.jdt.core.dom.Modifier; |
| import org.eclipse.jdt.core.dom.Name; |
| import org.eclipse.jdt.core.dom.ParameterizedType; |
| import org.eclipse.jdt.core.dom.SimpleName; |
| import org.eclipse.jdt.core.dom.SingleVariableDeclaration; |
| import org.eclipse.jdt.core.dom.SuperMethodInvocation; |
| 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.internal.corext.codemanipulation.StubUtility; |
| import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
| import org.eclipse.jdt.internal.corext.dom.Bindings; |
| |
| public class NewMethodCompletionProposal extends AbstractMethodCompletionProposal { |
| |
| private static final String KEY_NAME= "name"; //$NON-NLS-1$ |
| private static final String KEY_TYPE= "type"; //$NON-NLS-1$ |
| |
| private List fArguments; |
| |
| // invocationNode is MethodInvocation, ConstructorInvocation, SuperConstructorInvocation, ClassInstanceCreation, SuperMethodInvocation |
| public NewMethodCompletionProposal(String label, ICompilationUnit targetCU, ASTNode invocationNode, List arguments, ITypeBinding binding, int relevance, Image image) { |
| super(label, targetCU, invocationNode, binding, relevance, image); |
| fArguments= arguments; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.ui.text.correction.AbstractMethodCompletionProposal#evaluateModifiers(org.eclipse.jdt.core.dom.ASTNode) |
| */ |
| protected int evaluateModifiers(ASTNode targetTypeDecl) { |
| if (getSenderBinding().isAnnotation()) { |
| return 0; |
| } |
| if (getSenderBinding().isInterface()) { |
| // for interface and annotation members copy the modifiers from an existing field |
| MethodDeclaration[] methodDecls= ((TypeDeclaration) targetTypeDecl).getMethods(); |
| if (methodDecls.length > 0) { |
| return methodDecls[0].getModifiers(); |
| } |
| return 0; |
| } |
| ASTNode invocationNode= getInvocationNode(); |
| if (invocationNode instanceof MethodInvocation) { |
| int modifiers= 0; |
| Expression expression= ((MethodInvocation)invocationNode).getExpression(); |
| if (expression != null) { |
| if (expression instanceof Name && ((Name) expression).resolveBinding().getKind() == IBinding.TYPE) { |
| modifiers |= Modifier.STATIC; |
| } |
| } else if (ASTResolving.isInStaticContext(invocationNode)) { |
| modifiers |= Modifier.STATIC; |
| } |
| ASTNode node= ASTResolving.findParentType(invocationNode); |
| if (targetTypeDecl.equals(node)) { |
| modifiers |= Modifier.PRIVATE; |
| } else if (node instanceof AnonymousClassDeclaration && ASTNodes.isParent(node, targetTypeDecl)) { |
| modifiers |= Modifier.PROTECTED; |
| if (ASTResolving.isInStaticContext(node)) { |
| modifiers |= Modifier.STATIC; |
| } |
| } else { |
| modifiers |= Modifier.PUBLIC; |
| } |
| return modifiers; |
| } |
| return Modifier.PUBLIC; |
| } |
| |
| /*(non-Javadoc) |
| * @see org.eclipse.jdt.internal.ui.text.correction.AbstractMethodCompletionProposal#isConstructor() |
| */ |
| protected boolean isConstructor() { |
| ASTNode node= getInvocationNode(); |
| |
| return node.getNodeType() != ASTNode.METHOD_INVOCATION && node.getNodeType() != ASTNode.SUPER_METHOD_INVOCATION; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.ui.text.correction.AbstractMethodCompletionProposal#getNewName(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) |
| */ |
| protected SimpleName getNewName(ASTRewrite rewrite) { |
| ASTNode invocationNode= getInvocationNode(); |
| String name; |
| if (invocationNode instanceof MethodInvocation) { |
| name= ((MethodInvocation)invocationNode).getName().getIdentifier(); |
| } else if (invocationNode instanceof SuperMethodInvocation) { |
| name= ((SuperMethodInvocation)invocationNode).getName().getIdentifier(); |
| } else { |
| name= getSenderBinding().getName(); // name of the class |
| } |
| AST ast= rewrite.getAST(); |
| SimpleName newNameNode= ast.newSimpleName(name); |
| addLinkedPosition(rewrite.track(newNameNode), false, KEY_NAME); |
| |
| ASTNode invocationName= getInvocationNameNode(); |
| if (invocationName != null && invocationName.getAST() == ast) { // in the same CU |
| addLinkedPosition(rewrite.track(invocationName), true, KEY_NAME); |
| } |
| return newNameNode; |
| } |
| |
| private ASTNode getInvocationNameNode() { |
| ASTNode node= getInvocationNode(); |
| if (node instanceof MethodInvocation) { |
| return ((MethodInvocation)node).getName(); |
| } else if (node instanceof SuperMethodInvocation) { |
| return ((SuperMethodInvocation)node).getName(); |
| } else if (node instanceof ClassInstanceCreation) { |
| Type type= ((ClassInstanceCreation)node).getType(); |
| while (type instanceof ParameterizedType) { |
| type= ((ParameterizedType) type).getType(); |
| } |
| return type; |
| } |
| return null; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.ui.text.correction.AbstractMethodCompletionProposal#getNewMethodType(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) |
| */ |
| protected Type getNewMethodType(ASTRewrite rewrite) throws CoreException { |
| ASTNode node= getInvocationNode(); |
| AST ast= rewrite.getAST(); |
| |
| Type newTypeNode= null; |
| ITypeBinding[] otherProposals= null; |
| |
| if (node.getParent() instanceof MethodInvocation) { |
| MethodInvocation parent= (MethodInvocation) node.getParent(); |
| if (parent.getExpression() == node) { |
| ITypeBinding[] bindings= ASTResolving.getQualifierGuess(node.getRoot(), parent.getName().getIdentifier(), parent.arguments(), getSenderBinding()); |
| if (bindings.length > 0) { |
| newTypeNode= getImportRewrite().addImport(bindings[0], ast); |
| otherProposals= bindings; |
| } |
| } |
| } |
| if (newTypeNode == null) { |
| ITypeBinding binding= ASTResolving.guessBindingForReference(node); |
| if (binding != null && binding.isWildcardType()) { |
| binding= ASTResolving.normalizeWildcardType(binding, false, ast); |
| } |
| if (binding != null) { |
| newTypeNode= getImportRewrite().addImport(binding, ast); |
| } else { |
| ASTNode parent= node.getParent(); |
| if (parent instanceof ExpressionStatement) { |
| return null; |
| } |
| newTypeNode= ASTResolving.guessTypeForReference(ast, node); |
| if (newTypeNode == null) { |
| newTypeNode= ast.newSimpleType(ast.newSimpleName("Object")); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| addLinkedPosition(rewrite.track(newTypeNode), false, KEY_TYPE); |
| if (otherProposals != null) { |
| for (int i= 0; i < otherProposals.length; i++) { |
| addLinkedPositionProposal(KEY_TYPE, otherProposals[i]); |
| } |
| } |
| |
| return newTypeNode; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.ui.text.correction.AbstractMethodCompletionProposal#addNewParameters(org.eclipse.jdt.core.dom.rewrite.ASTRewrite, java.util.List, java.util.List) |
| */ |
| protected void addNewParameters(ASTRewrite rewrite, List takenNames, List params) throws CoreException { |
| AST ast= rewrite.getAST(); |
| |
| List arguments= fArguments; |
| |
| for (int i= 0; i < arguments.size(); i++) { |
| Expression elem= (Expression) arguments.get(i); |
| SingleVariableDeclaration param= ast.newSingleVariableDeclaration(); |
| |
| // argument type |
| String argTypeKey= "arg_type_" + i; //$NON-NLS-1$ |
| Type type= evaluateParameterType(ast, elem, argTypeKey); |
| param.setType(type); |
| |
| // argument name |
| String argNameKey= "arg_name_" + i; //$NON-NLS-1$ |
| String name= evaluateParameterName(takenNames, elem, type, argNameKey); |
| param.setName(ast.newSimpleName(name)); |
| |
| params.add(param); |
| |
| addLinkedPosition(rewrite.track(param.getType()), false, argTypeKey); |
| addLinkedPosition(rewrite.track(param.getName()), false, argNameKey); |
| } |
| } |
| |
| private Type evaluateParameterType(AST ast, Expression elem, String key) throws CoreException { |
| ITypeBinding binding= Bindings.normalizeTypeBinding(elem.resolveTypeBinding()); |
| if (binding != null && binding.isWildcardType()) { |
| binding= ASTResolving.normalizeWildcardType(binding, true, ast); |
| } |
| if (binding != null) { |
| ITypeBinding[] typeProposals= ASTResolving.getRelaxingTypes(ast, binding); |
| for (int i= 0; i < typeProposals.length; i++) { |
| addLinkedPositionProposal(key, typeProposals[i]); |
| } |
| return getImportRewrite().addImport(binding, ast); |
| } |
| return ast.newSimpleType(ast.newSimpleName("Object")); //$NON-NLS-1$ |
| } |
| |
| private String evaluateParameterName(List takenNames, Expression argNode, Type type, String key) { |
| IJavaProject project= getCompilationUnit().getJavaProject(); |
| String[] excludedNames= (String[]) takenNames.toArray(new String[takenNames.size()]); |
| |
| String favourite= null; |
| HashSet namesTaken= new HashSet(); |
| String baseName= ASTResolving.getBaseNameFromExpression(project, argNode); |
| if (baseName != null) { |
| String[] suggestions= StubUtility.getArgumentNameSuggestions(project, baseName, 0, excludedNames); |
| if (suggestions.length > 0) { |
| favourite= suggestions[0]; |
| } |
| addNameProposals(key, suggestions, namesTaken); |
| } |
| |
| int dim= 0; |
| if (type.isArrayType()) { |
| ArrayType arrayType= (ArrayType) type; |
| dim= arrayType.getDimensions(); |
| type= arrayType.getElementType(); |
| } |
| String typeName= ASTNodes.asString(type); |
| String packName= Signature.getQualifier(typeName); |
| |
| String[] names= NamingConventions.suggestArgumentNames(project, packName, typeName, dim, excludedNames); |
| if (favourite == null) { |
| favourite= names[0]; |
| } |
| addNameProposals(key, names, namesTaken); |
| |
| takenNames.add(favourite); |
| return favourite; |
| } |
| |
| private void addNameProposals(String key, String[] names, Set namesTaken) { |
| for (int i= 0; i < names.length; i++) { |
| String curr= names[i]; |
| if (namesTaken.add(curr)) { |
| addLinkedPositionProposal(key, curr, null); |
| } |
| } |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.ui.text.correction.AbstractMethodCompletionProposal#addNewExceptions(org.eclipse.jdt.core.dom.rewrite.ASTRewrite, java.util.List) |
| */ |
| protected void addNewExceptions(ASTRewrite rewrite, List exceptions) throws CoreException { |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.ui.text.correction.AbstractMethodCompletionProposal#addNewTypeParameters(org.eclipse.jdt.core.dom.rewrite.ASTRewrite, java.util.List, java.util.List) |
| */ |
| protected void addNewTypeParameters(ASTRewrite rewrite, List takenNames, List params) throws CoreException { |
| |
| } |
| |
| |
| } |