1 11 12 package org.eclipse.jdt.apt.core.internal.declaration; 13 14 import java.util.ArrayList ; 15 import java.util.Collection ; 16 import java.util.Collections ; 17 import java.util.List ; 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 private static final String HAS_INCONSISTENT_TYPE_HIERACHY = "has inconsistent hierarchy"; public TypeDeclarationImpl(final ITypeBinding binding, 50 final BaseProcessorEnv env) 51 { 52 super(binding, env); 53 } 54 55 public String getQualifiedName() 56 { 57 ITypeBinding type = getTypeBinding(); 58 return type.getQualifiedName(); 59 } 60 61 public String 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 ("unchecked") 81 private void getASTFields( 82 final AbstractTypeDeclaration typeDecl, 83 final List <FieldDeclaration> results){ 84 final List 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 <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 <FieldDeclaration> getFields() 106 { 107 final List <FieldDeclaration> results = new ArrayList <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 getASTFields(typeDecl, results); 122 break; 123 default: 124 throw new IllegalStateException ("expecting a AbstractTypeDeclaration but got " + node.getClass().getName() ); 127 } 128 } 129 } 130 final IVariableBinding[] fields = typeBinding.getDeclaredFields(); 133 for( IVariableBinding field : fields ){ 134 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 <TypeDeclaration> getNestedTypes() 146 { 147 final ITypeBinding[] memberTypes = getDeclarationBinding().getDeclaredTypes(); 148 final List <TypeDeclaration> results = new ArrayList <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 <TypeParameterDeclaration> getFormalTypeParameters() 158 { 159 final ITypeBinding[] typeParams = getDeclarationBinding().getTypeParameters(); 160 final List <TypeParameterDeclaration> results = new ArrayList <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 public Collection <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 <TypeMirror> result = new ArrayList <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 <InterfaceType> getSuperinterfaces() 211 { 212 final ITypeBinding[] superInterfaceBindings = getDeclarationBinding().getInterfaces(); 213 if( superInterfaceBindings == null || superInterfaceBindings.length == 0 ) 214 return Collections.emptyList(); 215 final List <InterfaceType> results = new ArrayList <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 231 public ITypeBinding getDeclarationBinding() 232 { 233 final ITypeBinding type = getTypeBinding(); 234 return type.getTypeDeclaration(); 235 } 236 237 240 @SuppressWarnings ("unchecked") 241 protected void getASTMethods( 242 final AbstractTypeDeclaration typeDecl, 243 final List <MethodDeclaration> results){ 244 final List 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 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 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 <? extends MethodDeclaration> _getMethods() 285 { 286 final List <MethodDeclaration> results = new ArrayList <MethodDeclaration>(); 287 if( isFromSource() ){ 288 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 getASTMethods(typeDecl, results); 303 break; 304 default: 305 throw new IllegalStateException ("expecting a AbstractTypeDeclaration but got " + node.getClass().getName() ); 308 } 309 } 310 } 311 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 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 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 { 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()); 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 |