KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > template > java > SignatureUtil


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.corext.template.java;
12
13 import java.util.Arrays JavaDoc;
14
15 import org.eclipse.jdt.core.IType;
16 import org.eclipse.jdt.core.JavaModelException;
17 import org.eclipse.jdt.core.Signature;
18
19 /**
20  * Utilities for Signature operations.
21  *
22  * @see Signature
23  * @since 3.1
24  */

25 public final class SignatureUtil {
26     
27     /**
28      * The signature of the null type. This type does not really exist in the
29      * type system. It represents the bound of type variables that have no lower
30      * bound, for example the parameter type to the <code>add</code> method of
31      * an instance of <code>java.util.List&lt;? extends Number&gt;</code>.
32      * <p>
33      * The only possible value that has that type is <code>null</code>.
34      * </p>
35      * <p>
36      * The representation of the null type is the signature of a type variable
37      * named <code>null</code> ({@value}), which will only work if no such
38      * variable gets declared in the same context.
39      */

40     private static final String JavaDoc NULL_TYPE_SIGNATURE= "Tnull;"; //$NON-NLS-1$
41
private static final char[] NULL_TYPE_SIGNATURE_ARRAY= NULL_TYPE_SIGNATURE.toCharArray();
42     /**
43      * The signature of <code>java.lang.Object</code> ({@value}).
44      */

45     private static final String JavaDoc OBJECT_SIGNATURE= "Ljava.lang.Object;"; //$NON-NLS-1$
46
private static final char[] OBJECT_SIGNATURE_ARRAY= OBJECT_SIGNATURE.toCharArray();
47
48     private SignatureUtil() {
49         // do not instantiate
50
}
51     
52     /**
53      * Returns <code>true</code> if <code>signature</code> is the
54      * signature of the <code>java.lang.Object</code> type.
55      *
56      * @param signature the signature
57      * @return <code>true</code> if <code>signature</code> is the
58      * signature of the <code>java.lang.Object</code> type,
59      * <code>false</code> otherwise
60      */

61     public static boolean isJavaLangObject(String JavaDoc signature) {
62         return OBJECT_SIGNATURE.equals(signature);
63     }
64     
65     /**
66      * Returns the upper bound of a type signature. Returns the signature of <code>java.lang.Object</code> if
67      * <code>signature</code> is a lower bound (<code>? super T</code>); returns
68      * the signature of the type <code>T</code> of an upper bound (<code>? extends T</code>)
69      * or <code>signature</code> itself if it is not a bound signature.
70      *
71      * @param signature the signature
72      * @return the upper bound signature of <code>signature</code>
73      */

74     public static String JavaDoc getUpperBound(String JavaDoc signature) {
75         return String.valueOf(getUpperBound(signature.toCharArray()));
76     }
77
78     /**
79      * Returns the upper bound of a type signature. Returns the signature of <code>java.lang.Object</code> if
80      * <code>signature</code> is a lower bound (<code>? super T</code>); returns
81      * the signature of the type <code>T</code> of an upper bound (<code>? extends T</code>)
82      * or <code>signature</code> itself if it is not a bound signature.
83      *
84      * @param signature the signature
85      * @return the upper bound signature of <code>signature</code>
86      */

87     public static char[] getUpperBound(char[] signature) {
88         if (signature.length < 1)
89             return signature;
90         
91         if (signature[0] == Signature.C_STAR)
92             return OBJECT_SIGNATURE_ARRAY;
93         
94         int superIndex= indexOf(signature, Signature.C_SUPER);
95         if (superIndex == 0)
96             return OBJECT_SIGNATURE_ARRAY;
97         
98         if (superIndex != -1) {
99             char afterSuper= signature[superIndex + 1];
100             if (afterSuper == Signature.C_STAR) {
101                 char[] type= new char[signature.length - 1];
102                 System.arraycopy(signature, 0, type, 0, superIndex);
103                 type[superIndex]= Signature.C_STAR;
104                 System.arraycopy(signature, superIndex + 2, type, superIndex + 1, signature.length - superIndex - 2);
105                 return getUpperBound(type);
106             }
107                 
108             if (afterSuper == Signature.C_EXTENDS) {
109                 int typeEnd= typeEnd(signature, superIndex + 1);
110                 char[] type= new char[signature.length - (typeEnd - superIndex - 1)];
111                 System.arraycopy(signature, 0, type, 0, superIndex);
112                 type[superIndex]= Signature.C_STAR;
113                 System.arraycopy(signature, typeEnd, type, superIndex + 1, signature.length - typeEnd);
114                 return getUpperBound(type);
115             }
116                 
117         }
118         
119         if (signature[0] == Signature.C_EXTENDS) {
120             char[] type= new char[signature.length - 1];
121             System.arraycopy(signature, 1, type, 0, signature.length - 1);
122             return type;
123         }
124         
125         return signature;
126     }
127
128     /**
129      * Returns the lower bound of a type signature. Returns the null type
130      * signature if <code>signature</code> is a wildcard or upper bound (<code>? extends T</code>);
131      * returns the signature of the type <code>T</code> of a lower bound (<code>? super T</code>)
132      * or <code>signature</code> itself if it is not a bound signature.
133      *
134      * @param signature the signature
135      * @return the lower bound signature of <code>signature</code>
136      */

137     public static String JavaDoc getLowerBound(String JavaDoc signature) {
138         return String.valueOf(getLowerBound(signature.toCharArray()));
139     }
140
141     /**
142      * Returns the lower bound of a type signature. Returns the null type
143      * signature if <code>signature</code> is a wildcard or upper bound (<code>? extends T</code>);
144      * returns the signature of the type <code>T</code> of a lower bound (<code>? super T</code>)
145      * or <code>signature</code> itself if it is not a bound signature.
146      *
147      * @param signature the signature
148      * @return the lower bound signature of <code>signature</code>
149      */

150     public static char[] getLowerBound(char[] signature) {
151         if (signature.length < 1)
152             return signature;
153         
154         if (signature.length == 1 && signature[0] == Signature.C_STAR)
155             return signature;
156         
157         int superIndex= indexOf(signature, Signature.C_EXTENDS);
158         if (superIndex == 0)
159             return NULL_TYPE_SIGNATURE_ARRAY;
160         
161         if (superIndex != -1) {
162             char afterSuper= signature[superIndex + 1];
163             if (afterSuper == Signature.C_STAR || afterSuper == Signature.C_EXTENDS)
164                 // impossible captured type
165
return NULL_TYPE_SIGNATURE_ARRAY;
166         }
167         
168         char[][] typeArguments= Signature.getTypeArguments(signature);
169         for (int i= 0; i < typeArguments.length; i++)
170             if (Arrays.equals(typeArguments[i], NULL_TYPE_SIGNATURE_ARRAY))
171                 return NULL_TYPE_SIGNATURE_ARRAY;
172         
173         if (signature[0] == Signature.C_SUPER) {
174             char[] type= new char[signature.length - 1];
175             System.arraycopy(signature, 1, type, 0, signature.length - 1);
176             return type;
177         }
178         
179         return signature;
180     }
181
182     private static int indexOf(char[] signature, char ch) {
183         for (int i= 0; i < signature.length; i++) {
184             if (signature[i] == ch)
185                 return i;
186         }
187         return -1;
188     }
189
190     /**
191      * Returns the fully qualified type name of the given signature, with any
192      * type parameters and arrays erased.
193      *
194      * @param signature the signature
195      * @return the fully qualified type name of the signature
196      */

197     public static String JavaDoc stripSignatureToFQN(String JavaDoc signature) throws IllegalArgumentException JavaDoc {
198         signature= Signature.getTypeErasure(signature);
199         signature= Signature.getElementType(signature);
200         return Signature.toString(signature);
201     }
202     
203     /**
204      * Returns the qualified signature corresponding to
205      * <code>signature</code>.
206      *
207      * @param signature the signature to qualify
208      * @param context the type inside which an unqualified type will be
209      * resolved to find the qualifier, or <code>null</code> if no
210      * context is available
211      * @return the qualified signature
212      */

213     public static String JavaDoc qualifySignature(final String JavaDoc signature, final IType context) {
214         if (context == null)
215             return signature;
216         
217         String JavaDoc qualifier= Signature.getSignatureQualifier(signature);
218         if (qualifier.length() > 0)
219             return signature;
220
221         String JavaDoc elementType= Signature.getElementType(signature);
222         String JavaDoc erasure= Signature.getTypeErasure(elementType);
223         String JavaDoc simpleName= Signature.getSignatureSimpleName(erasure);
224         String JavaDoc genericSimpleName= Signature.getSignatureSimpleName(elementType);
225         
226         int dim= Signature.getArrayCount(signature);
227         
228         try {
229             String JavaDoc[][] strings= context.resolveType(simpleName);
230             if (strings != null && strings.length > 0)
231                 qualifier= strings[0][0];
232         } catch (JavaModelException e) {
233             // ignore - not found
234
}
235         
236         if (qualifier.length() == 0)
237             return signature;
238         
239         String JavaDoc qualifiedType= Signature.toQualifiedName(new String JavaDoc[] {qualifier, genericSimpleName});
240         String JavaDoc qualifiedSignature= Signature.createTypeSignature(qualifiedType, true);
241         String JavaDoc newSignature= Signature.createArraySignature(qualifiedSignature, dim);
242         
243         return newSignature;
244     }
245     
246     /**
247      * Takes a method signature
248      * <code>[&lt; typeVariableName : formalTypeDecl &gt;] ( paramTypeSig1* ) retTypeSig</code>
249      * and returns it with any parameter signatures filtered through
250      * <code>getLowerBound</code> and the return type filtered through
251      * <code>getUpperBound</code>. Any preceding formal type variable
252      * declarations are removed.
253      * <p>
254      * TODO this is a temporary workaround for
255      * https://bugs.eclipse.org/bugs/show_bug.cgi?id=83600
256      * </p>
257      *
258      * @param signature the method signature to convert
259      * @return the signature with no bounded types
260      */

261     public static char[] unboundedSignature(char[] signature) {
262         if (signature == null || signature.length < 2)
263             return signature;
264         
265         final boolean BUG_83600= true;
266         // XXX the signatures from CompletionRequestor contain a superfluous '+'
267
// before type parameters to parameter types
268
if (BUG_83600) {
269             signature= fix83600(signature);
270         }
271         
272         StringBuffer JavaDoc res= new StringBuffer JavaDoc("("); //$NON-NLS-1$
273
char[][] parameters= Signature.getParameterTypes(signature);
274         for (int i= 0; i < parameters.length; i++) {
275             char[] param= parameters[i];
276             res.append(getLowerBound(param));
277         }
278         res.append(')');
279         res.append(getUpperBound(Signature.getReturnType(signature)));
280         return res.toString().toCharArray();
281     }
282
283     /**
284      * TODO this is a temporary workaround for
285      * https://bugs.eclipse.org/bugs/show_bug.cgi?id=83600 and
286      * https://bugs.eclipse.org/bugs/show_bug.cgi?id=85293
287      *
288      * @param signature the method signature to convert
289      * @return the fixed signature
290      */

291     public static char[] fix83600(char[] signature) {
292         if (signature == null || signature.length < 2)
293             return signature;
294         
295         return Signature.removeCapture(signature);
296     }
297
298     private static int typeEnd(char[] signature, int pos) {
299         int depth= 0;
300         while (pos < signature.length) {
301             switch (signature[pos]) {
302                 case Signature.C_GENERIC_START:
303                     depth++;
304                     break;
305                 case Signature.C_GENERIC_END:
306                     depth--;
307                     break;
308                 case Signature.C_SEMICOLON:
309                     if (depth == 0)
310                         return pos + 1;
311                     break;
312             }
313             pos++;
314         }
315         return pos + 1;
316     }
317 }
318
Popular Tags