KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > apt > core > internal > util > TypesUtil


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 BEA Systems, Inc.
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  * tyeung@bea.com - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jdt.apt.core.internal.util;
13
14 import com.sun.mirror.declaration.PackageDeclaration;
15 import com.sun.mirror.declaration.TypeDeclaration;
16 import com.sun.mirror.declaration.TypeParameterDeclaration;
17 import com.sun.mirror.type.ArrayType;
18 import com.sun.mirror.type.DeclaredType;
19 import com.sun.mirror.type.PrimitiveType;
20 import com.sun.mirror.type.ReferenceType;
21 import com.sun.mirror.type.TypeMirror;
22 import com.sun.mirror.type.TypeVariable;
23 import com.sun.mirror.type.VoidType;
24 import com.sun.mirror.type.WildcardType;
25 import com.sun.mirror.util.Types;
26 import java.util.Collection JavaDoc;
27
28 import org.eclipse.jdt.apt.core.internal.NonEclipseImplementationException;
29 import org.eclipse.jdt.apt.core.internal.declaration.*;
30 import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv;
31 import org.eclipse.jdt.apt.core.internal.type.ArrayTypeImpl;
32 import org.eclipse.jdt.core.BindingKey;
33 import org.eclipse.jdt.core.Signature;
34 import org.eclipse.jdt.core.dom.IPackageBinding;
35 import org.eclipse.jdt.core.dom.ITypeBinding;
36
37 public class TypesUtil implements Types
38 {
39     private static final String JavaDoc[] NO_ARGS = new String JavaDoc[0];
40     private final BaseProcessorEnv _env;
41     
42     public static void main(String JavaDoc[] args){}
43
44     public TypesUtil(BaseProcessorEnv env){
45         _env = env;
46         assert env != null : "null environment."; //$NON-NLS-1$
47
}
48     
49     public ArrayType getArrayType(TypeMirror componentType)
50     {
51         if( componentType == null ) return null;
52         if( componentType instanceof EclipseMirrorType ){
53             final EclipseMirrorType impl = (EclipseMirrorType)componentType;
54             // the leaf type of the array
55
final ITypeBinding leaf;
56             final int dimension;
57             switch( impl.kind() )
58             {
59                 case TYPE_ERROR: case TYPE_VOID:
60                     throw new IllegalArgumentException JavaDoc("Illegal element type for array"); //$NON-NLS-1$
61
case TYPE_ARRAY:
62                     final ITypeBinding array = ((ArrayTypeImpl)componentType).getTypeBinding();
63                     dimension = array.getDimensions() + 1;
64                     leaf = array.getElementType();
65                     break;
66                 default:
67                     leaf = impl.getTypeBinding();
68                     dimension = 1;
69                     break;
70             }
71             if( leaf == null || leaf.isParameterizedType() )
72                 throw new IllegalArgumentException JavaDoc("illegal component type: " + componentType); //$NON-NLS-1$
73

74             final String JavaDoc bindingKey = BindingKey.createArrayTypeBindingKey(leaf.getKey(), dimension);
75             final ITypeBinding arrayType = _env.getTypeBindingFromKey(bindingKey);
76             if(arrayType == null)
77                 return null;
78             return (ArrayType)Factory.createTypeMirror(arrayType, _env);
79         }
80         
81         throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
82
" Found " + componentType.getClass().getName()); //$NON-NLS-1$
83

84     }
85
86     /**
87      * @param outer a type
88      * @param inner the simple name of the nested class
89      * @return the binding that correspond to <code>outer.getQualifiedName()</code>.<code>inner</code>
90      * or null if it cannot be located.
91      */

92     private ITypeBinding findMemberType(ITypeBinding outer, String JavaDoc inner )
93     {
94         if( outer == null || inner == null ) return null;
95
96         outer = outer.getTypeDeclaration();
97
98         final ITypeBinding[] nestedTypes = outer.getDeclaredTypes();
99         // first we search throw the ones that are directly declared within 'outer'
100
for( ITypeBinding nestedType : nestedTypes ){
101             if( inner.equals(nestedType.getName()) )
102                 return nestedType;
103         }
104         // then we look up the hierachy chain.
105
// first we search the super type
106
ITypeBinding result = findMemberType(outer.getSuperclass(), inner);
107         if( result != null ) return result;
108         
109         // then the super interfaces
110
final ITypeBinding[] interfaces = outer.getInterfaces();
111         for( ITypeBinding interfaceType : interfaces ){
112             result = findMemberType(interfaceType, inner);
113             if( result != null ) return result;
114         }
115         
116         // can't find it.
117
return null;
118     }
119
120     public com.sun.mirror.type.DeclaredType getDeclaredType(DeclaredType containing, TypeDeclaration decl, TypeMirror... typeArgs)
121     {
122         if( decl == null ) return null;
123     
124         final ITypeBinding outerBinding = getTypeBinding(containing);
125         final ITypeBinding memberBinding;
126         
127         if( containing == null )
128             memberBinding = getTypeBinding(decl);
129         else{
130             if( outerBinding.isGenericType() )
131                  throw new IllegalArgumentException JavaDoc("[containing], " + containing + ", is a generic type."); //$NON-NLS-1$ //$NON-NLS-2$
132
// make sure 'decl' is a valid member of 'outerBinding'
133
memberBinding = findMemberType(outerBinding, decl.getSimpleName() );
134             if( memberBinding == null )
135                 throw new IllegalArgumentException JavaDoc(decl + " is not a member type of " + containing ); //$NON-NLS-1$
136
}
137         
138         final int numArgs = typeArgs == null ? 0 : typeArgs.length;
139         
140         if( memberBinding.isGenericType() ){
141             final String JavaDoc[] argKeys = numArgs == 0 ? NO_ARGS : new String JavaDoc[numArgs];
142             for( int i=0; i<numArgs; i++ ){
143                 final ITypeBinding binding = getTypeBinding(typeArgs[i]);
144                 assert binding != null : "failed to get binding mirror type"; //$NON-NLS-1$
145
argKeys[i] = binding.getKey();
146             }
147             
148             final ITypeBinding[] typeParams = memberBinding.getTypeParameters();
149             final int numTypeParams = typeParams == null ? 0 : typeParams.length;
150             // if no argument then a raw type will be created, otherwise it's an error when the
151
// number of type parameter and arguments don't agree.
152
if( numTypeParams != numArgs && numArgs != 0 )
153                 throw new IllegalArgumentException JavaDoc("type, " + memberBinding.getQualifiedName() + ", require " + numTypeParams + " type arguments " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
154
"but found " + numArgs ); //$NON-NLS-1$
155

156             final String JavaDoc typeKey = BindingKey.createParameterizedTypeBindingKey(memberBinding.getKey(), argKeys);
157             final ITypeBinding resultBinding = _env.getTypeBindingFromKey(typeKey);
158             return Factory.createReferenceType(resultBinding, _env);
159         }
160         else{
161             if( numArgs != 0 )
162                 throw new IllegalArgumentException JavaDoc("type, " + memberBinding + " is not a generic type and cannot have type arguments."); //$NON-NLS-1$ //$NON-NLS-2$
163
// simple case, turning a non-generic TypeDeclaration into a DeclaredType
164
return (DeclaredType)decl;
165         }
166     }
167
168     public com.sun.mirror.type.DeclaredType getDeclaredType(TypeDeclaration decl, TypeMirror... typeArgs)
169     {
170         return getDeclaredType(null, decl, typeArgs);
171     }
172
173     public TypeMirror getErasure(TypeMirror t)
174     {
175         if( t == null ) return null;
176         
177         if(t instanceof EclipseMirrorType){
178             final EclipseMirrorType impl = (EclipseMirrorType)t;
179             final ITypeBinding binding;
180             switch( impl.kind() )
181             {
182                 case TYPE_PRIMITIVE:
183                 case TYPE_VOID:
184                 case TYPE_ERROR:
185                     return t;
186                 
187                 default:
188                     binding = impl.getTypeBinding();
189             }
190             final ITypeBinding erasure = binding.getErasure();
191             if( erasure == binding ) return t;
192             TypeMirror m_erasure = Factory.createTypeMirror(erasure, impl.getEnvironment() );
193             if( m_erasure == null )
194                 return Factory.createErrorClassType(erasure);
195             return m_erasure;
196         }
197
198         throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
199
" Found " + t.getClass().getName()); //$NON-NLS-1$
200
}
201
202     public PrimitiveType getPrimitiveType(PrimitiveType.Kind kind)
203     {
204         if( kind == null ) return null;
205         switch(kind)
206         {
207             case BOOLEAN: return _env.getBooleanType();
208             case BYTE: return _env.getByteType();
209             case CHAR: return _env.getCharType();
210             case DOUBLE: return _env.getDoubleType();
211             case FLOAT: return _env.getFloatType();
212             case INT: return _env.getIntType();
213             case LONG: return _env.getLongType();
214             case SHORT: return _env.getShortType();
215           
216             default: throw new IllegalStateException JavaDoc("unknown primitive kind : " + kind); //$NON-NLS-1$
217
}
218     }
219
220     public TypeVariable getTypeVariable(TypeParameterDeclaration tparam)
221     {
222         if( tparam == null ) return null;
223         if( tparam instanceof TypeParameterDeclarationImpl)
224             return (TypeVariable) tparam;
225
226         throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
227
" Found " + tparam.getClass().getName()); //$NON-NLS-1$
228
}
229
230     public VoidType getVoidType()
231     {
232         return _env.getVoidType();
233     }
234
235     public WildcardType getWildcardType(Collection JavaDoc<ReferenceType> upperBounds, Collection JavaDoc<ReferenceType> lowerBounds)
236     {
237         final String JavaDoc boundKey;
238         final char boundKind;
239         final int upperBoundCount = upperBounds == null ? 0 : upperBounds.size();
240         final int lowerBoundCount = lowerBounds == null ? 0 : lowerBounds.size();
241         if( upperBoundCount == 0 && lowerBoundCount == 0 ){
242             boundKey = null;
243             boundKind = Signature.C_STAR;
244         }
245         else if( upperBoundCount == 1 && lowerBoundCount == 0){
246             final ITypeBinding binding = getTypeBinding(upperBounds.iterator().next());
247             boundKey = binding.getKey();
248             boundKind = Signature.C_EXTENDS;
249         }
250         else if(lowerBoundCount == 1 && upperBoundCount == 0){
251             final ITypeBinding binding = getTypeBinding(lowerBounds.iterator().next());
252             boundKey = binding.getKey();
253             boundKind = Signature.C_SUPER;
254         }
255         else
256             throw new IllegalArgumentException JavaDoc("Wildcard can only have a upper bound, a lower bound or be unbounded."); //$NON-NLS-1$
257

258         final String JavaDoc wildcardkey = BindingKey.createWilcardTypeBindingKey(boundKey, boundKind);
259         final ITypeBinding wildcard = _env.getTypeBindingFromKey(wildcardkey);
260         return (WildcardType)Factory.createTypeMirror(wildcard, _env);
261     }
262
263     /**
264      * @return true iff t2 = t1 does not require explicit casting and not cause an error.
265      */

266     public boolean isAssignable(TypeMirror t1, TypeMirror t2)
267     {
268         EclipseMirrorType left = (EclipseMirrorType)t1;
269         EclipseMirrorType right = (EclipseMirrorType)t2;
270         return left.isAssignmentCompatible(right);
271         
272     }
273
274     public boolean isSubtype(TypeMirror t1, TypeMirror t2)
275     {
276         EclipseMirrorType left = (EclipseMirrorType)t1;
277         EclipseMirrorType right = (EclipseMirrorType)t2;
278         
279         return left.isSubTypeCompatible(right);
280     }
281     
282     public static IPackageBinding getPackageBinding(PackageDeclaration pkg)
283         throws NonEclipseImplementationException
284     {
285         if(pkg == null) return null;
286         if( pkg instanceof EclipseMirrorObject ){
287             final PackageDeclarationImpl impl = (PackageDeclarationImpl)pkg;
288             return impl.getPackageBinding();
289         }
290
291         throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
292
" Found " + pkg.getClass().getName()); //$NON-NLS-1$
293
}
294
295     /**
296      * @return the binding correspond to the given type.
297      * Return null if the type is an error marker.
298      * @throws NonEclipseImplementationException
299      */

300
301     private static ITypeBinding getTypeBinding(TypeMirror type)
302         throws NonEclipseImplementationException
303     {
304         if(type == null ) return null;
305         if( type instanceof EclipseMirrorType ){
306             return ((EclipseMirrorType)type).getTypeBinding();
307         }
308
309         throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
310
" Found " + type.getClass().getName()); //$NON-NLS-1$
311
}
312
313     /**
314      * @return the binding correspond to the given type.
315      * @throws NonEclipseImplementationException
316      */

317     public static ITypeBinding getTypeBinding(TypeDeclaration type)
318         throws NonEclipseImplementationException
319     {
320         if(type == null ) return null;
321         if( type instanceof EclipseMirrorObject ){
322             return ((TypeDeclarationImpl)type).getTypeBinding();
323         }
324         throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
325
" Found " + type.getClass().getName()); //$NON-NLS-1$
326
}
327 }
328
Popular Tags