KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > apt > core > internal > declaration > TypeDeclarationImpl


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.declaration;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.util.List JavaDoc;
18
19 import org.eclipse.core.resources.IFile;
20 import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv;
21 import org.eclipse.jdt.apt.core.internal.util.Factory;
22 import org.eclipse.jdt.core.dom.ASTNode;
23 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
24 import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
25 import org.eclipse.jdt.core.dom.BodyDeclaration;
26 import org.eclipse.jdt.core.dom.IBinding;
27 import org.eclipse.jdt.core.dom.IMethodBinding;
28 import org.eclipse.jdt.core.dom.ITypeBinding;
29 import org.eclipse.jdt.core.dom.IVariableBinding;
30 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
31
32 import com.sun.mirror.declaration.Declaration;
33 import com.sun.mirror.declaration.FieldDeclaration;
34 import com.sun.mirror.declaration.MethodDeclaration;
35 import com.sun.mirror.declaration.PackageDeclaration;
36 import com.sun.mirror.declaration.TypeDeclaration;
37 import com.sun.mirror.declaration.TypeParameterDeclaration;
38 import com.sun.mirror.type.DeclaredType;
39 import com.sun.mirror.type.InterfaceType;
40 import com.sun.mirror.type.ReferenceType;
41 import com.sun.mirror.type.TypeMirror;
42 import com.sun.mirror.util.DeclarationVisitor;
43
44 public abstract class TypeDeclarationImpl extends MemberDeclarationImpl
45     implements TypeDeclaration, DeclaredType, ReferenceType, EclipseMirrorType
46 {
47     // jdt core compiler add a field to a type with the following name when there is a hierachy problem with the type.
48
private static final String JavaDoc HAS_INCONSISTENT_TYPE_HIERACHY = "has inconsistent hierarchy"; //$NON-NLS-1$
49
public TypeDeclarationImpl(final ITypeBinding binding,
50                                final BaseProcessorEnv env)
51     {
52         super(binding, env);
53     }
54
55     public String JavaDoc getQualifiedName()
56     {
57         ITypeBinding type = getTypeBinding();
58         return type.getQualifiedName();
59     }
60
61     public String JavaDoc getSimpleName()
62     {
63         ITypeBinding type = getTypeBinding();
64         return type.getName();
65     }
66
67     public PackageDeclaration getPackage()
68     {
69         ITypeBinding binding = getDeclarationBinding();
70         return new PackageDeclarationImpl(binding.getPackage(), this, _env, false);
71     }
72
73     public void accept(DeclarationVisitor visitor)
74     {
75         visitor.visitTypeDeclaration(this);
76     }
77
78     public ITypeBinding getTypeBinding(){ return (ITypeBinding)_binding; }
79     
80     @SuppressWarnings JavaDoc("unchecked")
81     private void getASTFields(
82             final AbstractTypeDeclaration typeDecl,
83             final List JavaDoc<FieldDeclaration> results){
84         final List JavaDoc bodyDecls = typeDecl.bodyDeclarations();
85         for( int i=0, len=bodyDecls.size(); i<len; i++ ){
86             final BodyDeclaration bodyDecl = (BodyDeclaration)bodyDecls.get(i);
87             IFile file = null;
88             if( bodyDecl.getNodeType() == ASTNode.FIELD_DECLARATION ){
89                 final List JavaDoc<VariableDeclarationFragment> fragments =
90                     ((org.eclipse.jdt.core.dom.FieldDeclaration)bodyDecl).fragments();
91                 for( VariableDeclarationFragment frag : fragments ){
92                     final IBinding fieldBinding = frag.resolveBinding();
93                     if( fieldBinding == null ){
94                         if( file == null )
95                             file = getResource();
96                         final EclipseDeclarationImpl decl = Factory.createDeclaration(frag, file, _env);
97                         if( decl != null )
98                             results.add((FieldDeclaration)decl);
99                     }
100                 }
101             }
102         }
103     }
104
105     public Collection JavaDoc<FieldDeclaration> getFields()
106     {
107         final List JavaDoc<FieldDeclaration> results = new ArrayList JavaDoc<FieldDeclaration>();
108         final ITypeBinding typeBinding = getDeclarationBinding();
109         if( isFromSource() ){
110             final ASTNode node =
111                 _env.getASTNodeForBinding(typeBinding);
112             if( node != null ){
113                 switch( node.getNodeType() )
114                 {
115                 case ASTNode.TYPE_DECLARATION:
116                 case ASTNode.ANNOTATION_TYPE_DECLARATION:
117                 case ASTNode.ENUM_DECLARATION:
118                     AbstractTypeDeclaration typeDecl =
119                         (AbstractTypeDeclaration)node;
120                     // built the ast based methods first.
121
getASTFields(typeDecl, results);
122                     break;
123                 default:
124                     // the ast node for a type binding should be a AbstractTypeDeclaration.
125
throw new IllegalStateException JavaDoc("expecting a AbstractTypeDeclaration but got " //$NON-NLS-1$
126
+ node.getClass().getName() );
127                 }
128             }
129         }
130         // either type is binary or
131
// constructing the binding based fields for source type.
132
final IVariableBinding[] fields = typeBinding.getDeclaredFields();
133         for( IVariableBinding field : fields ){
134             // note that the name HAS_INCONSISTENT_TYPE_HIERACHY is not a legal java identifier
135
// so there is no chance that we are filtering out actual declared fields.
136
if( field.isSynthetic() || HAS_INCONSISTENT_TYPE_HIERACHY.equals(field.getName()))
137                 continue;
138             Declaration mirrorDecl = Factory.createDeclaration(field, _env);
139             if( mirrorDecl != null)
140                 results.add( (FieldDeclaration)mirrorDecl);
141         }
142         return results;
143     }
144
145     public Collection JavaDoc<TypeDeclaration> getNestedTypes()
146     {
147         final ITypeBinding[] memberTypes = getDeclarationBinding().getDeclaredTypes();
148         final List JavaDoc<TypeDeclaration> results = new ArrayList JavaDoc<TypeDeclaration>(memberTypes.length);
149         for( ITypeBinding type : memberTypes ){
150             Declaration mirrorDecl = Factory.createReferenceType(type, _env);
151             if( mirrorDecl != null )
152                 results.add((TypeDeclaration)mirrorDecl);
153         }
154         return results;
155     }
156
157     public Collection JavaDoc<TypeParameterDeclaration> getFormalTypeParameters()
158     {
159         final ITypeBinding[] typeParams = getDeclarationBinding().getTypeParameters();
160         final List JavaDoc<TypeParameterDeclaration> results = new ArrayList JavaDoc<TypeParameterDeclaration>(typeParams.length);
161         for( ITypeBinding typeParam : typeParams ){
162             Declaration mirrorDecl = Factory.createDeclaration(typeParam, _env);
163             if( mirrorDecl != null )
164                 results.add( (TypeParameterDeclaration)mirrorDecl );
165         }
166         return results;
167     }
168
169     public TypeDeclaration getDeclaringType()
170     {
171         final ITypeBinding decl = getDeclarationBinding();
172         if( decl.isMember() )
173             return Factory.createReferenceType(decl.getDeclaringClass(), _env);
174         return null;
175     }
176
177     // Start of implementation of DeclaredType API
178
public Collection JavaDoc<TypeMirror> getActualTypeArguments()
179     {
180         final ITypeBinding type = getTypeBinding();
181         final ITypeBinding[] typeArgs = type.getTypeArguments();
182         if( typeArgs == null || typeArgs.length == 0 )
183             return Collections.emptyList();
184
185         final Collection JavaDoc<TypeMirror> result = new ArrayList JavaDoc<TypeMirror>(typeArgs.length);
186         for( ITypeBinding arg : typeArgs ){
187             final TypeMirror mirror = Factory.createTypeMirror(arg, _env);
188             if (mirror == null)
189                 result.add(Factory.createErrorClassType(arg));
190             else
191                 result.add(mirror);
192         }
193
194         return result;
195     }
196
197     public DeclaredType getContainingType()
198     {
199         final ITypeBinding outer = getTypeBinding().getDeclaringClass();
200         return Factory.createReferenceType(outer, _env);
201     }
202
203     public TypeDeclaration getDeclaration()
204     {
205         final ITypeBinding declBinding = getDeclarationBinding();
206         if( declBinding == _binding ) return this;
207         else return Factory.createReferenceType(declBinding, _env);
208     }
209     
210     public Collection JavaDoc<InterfaceType> getSuperinterfaces()
211     {
212         final ITypeBinding[] superInterfaceBindings = getDeclarationBinding().getInterfaces();
213         if( superInterfaceBindings == null || superInterfaceBindings.length == 0 )
214             return Collections.emptyList();
215         final List JavaDoc<InterfaceType> results = new ArrayList JavaDoc<InterfaceType>(superInterfaceBindings.length);
216         for( ITypeBinding binding : superInterfaceBindings ){
217             if( binding.isInterface() ){
218                 final TypeDeclarationImpl mirrorDecl = Factory.createReferenceType(binding, _env);
219                 if( mirrorDecl.kind() == MirrorKind.TYPE_INTERFACE ){
220                     results.add((InterfaceType)mirrorDecl);
221                 }
222             }
223             else results.add(Factory.createErrorInterfaceType(binding));
224         }
225         return results;
226     }
227
228
229     // End of implementation of DeclaredType API
230

231     public ITypeBinding getDeclarationBinding()
232     {
233         final ITypeBinding type = getTypeBinding();
234         return type.getTypeDeclaration();
235     }
236     
237     /**
238      * create mirror methods that does not have a binding represention.
239      */

240     @SuppressWarnings JavaDoc("unchecked")
241     protected void getASTMethods(
242             final AbstractTypeDeclaration typeDecl,
243             final List JavaDoc<MethodDeclaration> results){
244         final List JavaDoc bodyDecls = typeDecl.bodyDeclarations();
245         IFile file = null;
246         for( int i=0, len=bodyDecls.size(); i<len; i++ ){
247             final BodyDeclaration bodyDecl = (BodyDeclaration)bodyDecls.get(i);
248             switch(bodyDecl.getNodeType()){
249             case ASTNode.METHOD_DECLARATION:
250                 final org.eclipse.jdt.core.dom.MethodDeclaration methodDecl =
251                         (org.eclipse.jdt.core.dom.MethodDeclaration)bodyDecl;
252                 
253                 if( !methodDecl.isConstructor() ){
254                     final IMethodBinding methodBinding = methodDecl.resolveBinding();
255                     // built an ast based representation.
256
if( methodBinding == null ){
257                         if( file == null )
258                             file = getResource();
259                         MethodDeclaration mirrorDecl =
260                             (MethodDeclaration)Factory.createDeclaration(methodDecl, file, _env);
261                         if( mirrorDecl != null )
262                             results.add(mirrorDecl);
263                     }
264                 }
265                 break;
266             case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION:
267                 final AnnotationTypeMemberDeclaration memberDecl =
268                     (AnnotationTypeMemberDeclaration)bodyDecl;
269                 final IMethodBinding methodBinding = memberDecl.resolveBinding();
270                 // built an ast based representation.
271
if( methodBinding == null ){
272                     if( file == null )
273                         file = getResource();
274                     MethodDeclaration mirrorDecl =
275                         (MethodDeclaration)Factory.createDeclaration(memberDecl, file, _env);
276                     if( mirrorDecl != null )
277                         results.add(mirrorDecl);
278                 }
279                 break;
280             }
281         }
282     }
283
284     protected List JavaDoc<? extends MethodDeclaration> _getMethods()
285     {
286         final List JavaDoc<MethodDeclaration> results = new ArrayList JavaDoc<MethodDeclaration>();
287         if( isFromSource() ){
288             // need to consult the ast since methods with broken signature
289
// do not appear in bindings.
290
final ITypeBinding typeBinding = getDeclarationBinding();
291             final ASTNode node =
292                 _env.getASTNodeForBinding(typeBinding);
293             if( node != null ){
294                 switch( node.getNodeType() )
295                 {
296                 case ASTNode.TYPE_DECLARATION:
297                 case ASTNode.ANNOTATION_TYPE_DECLARATION:
298                 case ASTNode.ENUM_DECLARATION:
299                     AbstractTypeDeclaration typeDecl =
300                         (AbstractTypeDeclaration)node;
301                     // built the ast based methods first.
302
getASTMethods(typeDecl, results);
303                     break;
304                 default:
305                     // the ast node for a type binding should be a AbstractTypeDeclaration.
306
throw new IllegalStateException JavaDoc("expecting a AbstractTypeDeclaration but got " //$NON-NLS-1$
307
+ node.getClass().getName() );
308                 }
309             }
310         }
311         // build methods for binding type or
312
// build the binding based method for source type.
313
final IMethodBinding[] methods = getDeclarationBinding().getDeclaredMethods();
314         for( IMethodBinding method : methods ){
315             if( method.isConstructor() || method.isSynthetic() ) continue;
316             Declaration mirrorDecl = Factory.createDeclaration(method, _env);
317             if( mirrorDecl != null)
318                 results.add((MethodDeclaration)mirrorDecl);
319         }
320         return results;
321     }
322     
323     public String JavaDoc toString()
324     {
325         return getQualifiedName();
326     }
327
328     public boolean isFromSource(){ return getDeclarationBinding().isFromSource(); }
329
330     public boolean isAssignmentCompatible(EclipseMirrorType left) {
331         return isSubTypeCompatible(left);
332     }
333
334     public boolean isSubTypeCompatible(EclipseMirrorType type) {
335         // Operate on erasures - ignore generics for now
336
// Also ignore boxing for now
337
ITypeBinding thisErased = getTypeBinding().getErasure();
338         ITypeBinding typeErased = type.getTypeBinding().getErasure();
339         
340         if (kind() == MirrorKind.TYPE_CLASS) {
341             if (type.kind() == MirrorKind.TYPE_CLASS)
342                 return isSubClassOf(thisErased, typeErased);
343             if (type.kind() == MirrorKind.TYPE_INTERFACE)
344                 return isImplementorOf(thisErased, typeErased);
345             return false;
346         }
347         else { //kind() == MirrorKind.TYPE_INTERFACE
348
if (type.kind() == MirrorKind.TYPE_INTERFACE)
349                 return isImplementorOf(thisErased, typeErased);
350             if (type.kind() == MirrorKind.TYPE_CLASS)
351                 return "java.lang.Object".equals(getQualifiedName()); //$NON-NLS-1$
352
return false;
353         }
354     }
355
356     private static boolean isImplementorOf(ITypeBinding t1, ITypeBinding t2) {
357         if (eq(t1,t2)) return true;
358         ITypeBinding[] intfs = t1.getInterfaces();
359         
360         for (ITypeBinding intf : intfs) {
361             if (isImplementorOf(intf.getErasure(), t2))
362                 return true;
363         }
364         return false;
365     }
366
367     private static boolean isSubClassOf(ITypeBinding t1, ITypeBinding t2) {
368         while(t1 != null) {
369             if (eq(t1, t2)) return true;
370             t1 = t1.getSuperclass();
371         }
372         return false;
373     }
374
375     private static boolean eq(ITypeBinding t1, ITypeBinding t2) {
376         return t1.getQualifiedName().equals(t2.getQualifiedName());
377     }
378 }
379
Popular Tags