KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > text > java > MethodProposalInfo


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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.java;
12
13
14 import java.util.HashMap JavaDoc;
15 import java.util.Map JavaDoc;
16
17 import org.eclipse.jdt.core.CompletionProposal;
18 import org.eclipse.jdt.core.IJavaProject;
19 import org.eclipse.jdt.core.IMember;
20 import org.eclipse.jdt.core.IMethod;
21 import org.eclipse.jdt.core.IType;
22 import org.eclipse.jdt.core.ITypeParameter;
23 import org.eclipse.jdt.core.JavaModelException;
24 import org.eclipse.jdt.core.Signature;
25
26 import org.eclipse.jdt.internal.corext.template.java.SignatureUtil;
27
28
29 /**
30  * Proposal info that computes the javadoc lazily when it is queried.
31  *
32  * @since 3.1
33  */

34 public final class MethodProposalInfo extends MemberProposalInfo {
35
36     /**
37      * Fallback in case we can't match a generic method. The fall back is only based
38      * on method name and number of parameters.
39      */

40     private IMethod fFallbackMatch;
41
42     /**
43      * Creates a new proposal info.
44      *
45      * @param project the java project to reference when resolving types
46      * @param proposal the proposal to generate information for
47      */

48     public MethodProposalInfo(IJavaProject project, CompletionProposal proposal) {
49         super(project, proposal);
50     }
51
52     /**
53      * Resolves the member described by the receiver and returns it if found.
54      * Returns <code>null</code> if no corresponding member can be found.
55      *
56      * @return the resolved member or <code>null</code> if none is found
57      * @throws JavaModelException if accessing the java model fails
58      */

59     protected IMember resolveMember() throws JavaModelException {
60         char[] declarationSignature= fProposal.getDeclarationSignature();
61         String JavaDoc typeName= SignatureUtil.stripSignatureToFQN(String.valueOf(declarationSignature));
62         IType type= fJavaProject.findType(typeName);
63         if (type != null) {
64             String JavaDoc name= String.valueOf(fProposal.getName());
65             String JavaDoc[] parameters= Signature.getParameterTypes(String.valueOf(SignatureUtil.fix83600(fProposal.getSignature())));
66             for (int i= 0; i < parameters.length; i++) {
67                 parameters[i]= SignatureUtil.getLowerBound(parameters[i]);
68             }
69             boolean isConstructor= fProposal.isConstructor();
70
71             return findMethod(name, parameters, isConstructor, type);
72         }
73
74         return null;
75     }
76
77     /* adapted from JavaModelUtil */
78
79     /**
80      * Finds a method in a type. This searches for a method with the same name
81      * and signature. Parameter types are only compared by the simple name, no
82      * resolving for the fully qualified type name is done. Constructors are
83      * only compared by parameters, not the name.
84      *
85      * @param name The name of the method to find
86      * @param paramTypes The type signatures of the parameters e.g.
87      * <code>{"QString;","I"}</code>
88      * @param isConstructor If the method is a constructor
89      * @return The first found method or <code>null</code>, if nothing found
90      */

91     private IMethod findMethod(String JavaDoc name, String JavaDoc[] paramTypes, boolean isConstructor, IType type) throws JavaModelException {
92         Map JavaDoc typeVariables= computeTypeVariables(type);
93         return findMethod(name, paramTypes, isConstructor, type.getMethods(), typeVariables);
94     }
95
96     /**
97      * The type and method signatures received in
98      * <code>CompletionProposals</code> of type <code>METHOD_REF</code>
99      * contain concrete type bounds. When comparing parameters of the signature
100      * with an <code>IMethod</code>, we have to make sure that we match the
101      * case where the formal method declaration uses a type variable which in
102      * the signature is already substituted with a concrete type (bound).
103      * <p>
104      * This method creates a map from type variable names to type signatures
105      * based on the position they appear in the type declaration. The type
106      * signatures are filtered through
107      * {@link SignatureUtil#getLowerBound(char[])}.
108      * </p>
109      *
110      * @param type the type to get the variables from
111      * @return a map from type variables to concrete type signatures
112      * @throws JavaModelException if accessing the java model fails
113      */

114     private Map JavaDoc computeTypeVariables(IType type) throws JavaModelException {
115         Map JavaDoc map= new HashMap JavaDoc();
116         char[] declarationSignature= fProposal.getDeclarationSignature();
117         if (declarationSignature == null) // array methods don't contain a declaration signature
118
return map;
119         char[][] concreteParameters= Signature.getTypeArguments(declarationSignature);
120
121         ITypeParameter[] typeParameters= type.getTypeParameters();
122         for (int i= 0; i < typeParameters.length; i++) {
123             String JavaDoc variable= typeParameters[i].getElementName();
124             if (concreteParameters.length > i)
125                 // use lower bound since method equality is only parameter based
126
map.put(variable, SignatureUtil.getLowerBound(concreteParameters[i]));
127             else
128                 // fProposal.getDeclarationSignature() is a raw type - use Object
129
map.put(variable, "Ljava.lang.Object;".toCharArray()); //$NON-NLS-1$
130
}
131
132         return map;
133     }
134
135     /**
136      * Finds a method by name. This searches for a method with a name and
137      * signature. Parameter types are only compared by the simple name, no
138      * resolving for the fully qualified type name is done. Constructors are
139      * only compared by parameters, not the name.
140      *
141      * @param name The name of the method to find
142      * @param paramTypes The type signatures of the parameters e.g.
143      * <code>{"QString;","I"}</code>
144      * @param isConstructor If the method is a constructor
145      * @param methods The methods to search in
146      * @param typeVariables a map from type variables to concretely used types
147      * @return The found method or <code>null</code>, if nothing found
148      */

149     private IMethod findMethod(String JavaDoc name, String JavaDoc[] paramTypes, boolean isConstructor, IMethod[] methods, Map JavaDoc typeVariables) throws JavaModelException {
150         for (int i= methods.length - 1; i >= 0; i--) {
151             if (isSameMethodSignature(name, paramTypes, isConstructor, methods[i], typeVariables)) {
152                 return methods[i];
153             }
154         }
155         return fFallbackMatch;
156     }
157
158     /**
159      * Tests if a method equals to the given signature. Parameter types are only
160      * compared by the simple name, no resolving for the fully qualified type
161      * name is done. Constructors are only compared by parameters, not the name.
162      *
163      * @param name Name of the method
164      * @param paramTypes The type signatures of the parameters e.g.
165      * <code>{"QString;","I"}</code>
166      * @param isConstructor Specifies if the method is a constructor
167      * @param method the method to be compared with this info's method
168      * @param typeVariables a map from type variables to types
169      * @return Returns <code>true</code> if the method has the given name and
170      * parameter types and constructor state.
171      */

172     private boolean isSameMethodSignature(String JavaDoc name, String JavaDoc[] paramTypes, boolean isConstructor, IMethod method, Map JavaDoc typeVariables) throws JavaModelException {
173         if (isConstructor || name.equals(method.getElementName())) {
174             if (isConstructor == method.isConstructor()) {
175                 String JavaDoc[] otherParams= method.getParameterTypes(); // types may be type variables
176
if (paramTypes.length == otherParams.length) {
177                     fFallbackMatch= method;
178                     String JavaDoc signature= method.getSignature();
179                     String JavaDoc[] otherParamsFromSignature= Signature.getParameterTypes(signature); // types are resolved / upper-bounded
180
// no need to check method type variables since these are
181
// not yet bound when proposing a method
182
for (int i= 0; i < paramTypes.length; i++) {
183                         String JavaDoc ourParamName= computeSimpleTypeName(paramTypes[i], typeVariables);
184                         String JavaDoc otherParamName1= computeSimpleTypeName(otherParams[i], typeVariables);
185                         String JavaDoc otherParamName2= computeSimpleTypeName(otherParamsFromSignature[i], typeVariables);
186                         
187                         if (!ourParamName.equals(otherParamName1) && !ourParamName.equals(otherParamName2)) {
188                             return false;
189                         }
190                     }
191                     return true;
192                 }
193             }
194         }
195         return false;
196     }
197
198     /**
199      * Returns the simple erased name for a given type signature, possibly replacing type variables.
200      *
201      * @param signature the type signature
202      * @param typeVariables the Map&lt;SimpleName, VariableName>
203      * @return the simple erased name for signature
204      */

205     private String JavaDoc computeSimpleTypeName(String JavaDoc signature, Map JavaDoc typeVariables) {
206         // method equality uses erased types
207
String JavaDoc erasure= Signature.getTypeErasure(signature);
208         erasure= erasure.replaceAll("/", "."); //$NON-NLS-1$//$NON-NLS-2$
209
String JavaDoc simpleName= Signature.getSimpleName(Signature.toString(erasure));
210         char[] typeVar= (char[]) typeVariables.get(simpleName);
211         if (typeVar != null)
212             simpleName= String.valueOf(Signature.getSignatureSimpleName(typeVar));
213         return simpleName;
214     }
215 }
216
Popular Tags