/******************************************************************************* * Copyright (c) 2005, 2008 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * tyeung@bea.com - initial API and implementation * IBM Corporation - implemented methods from IBinding * IBM Corporation - renamed from ResolvedAnnotation to AnnotationBinding *******************************************************************************/ package org.eclipse.jdt.core.dom; import org.eclipse.jdt.core.IAnnotatable; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; /** * Internal class */ class AnnotationBinding implements IAnnotationBinding { static final AnnotationBinding[] NoAnnotations= new AnnotationBinding[0]; private org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding binding; private BindingResolver bindingResolver; private String key; AnnotationBinding(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding annotation, BindingResolver resolver) { if (annotation == null) throw new IllegalStateException(); this.binding= annotation; this.bindingResolver= resolver; } public IAnnotationBinding[] getAnnotations() { return NoAnnotations; } public ITypeBinding getAnnotationType() { ITypeBinding typeBinding= this.bindingResolver.getTypeBinding(this.binding.getAnnotationType()); if (typeBinding == null) return null; return typeBinding; } public IMemberValuePairBinding[] getDeclaredMemberValuePairs() { ReferenceBinding typeBinding= this.binding.getAnnotationType(); if (typeBinding == null || ((typeBinding.tagBits & TagBits.HasMissingType) != 0)) { return MemberValuePairBinding.NoPair; } ElementValuePair[] internalPairs= this.binding.getElementValuePairs(); int length= internalPairs.length; IMemberValuePairBinding[] pairs= length == 0 ? MemberValuePairBinding.NoPair : new MemberValuePairBinding[length]; int counter= 0; for (int i= 0; i < length; i++) { ElementValuePair valuePair= internalPairs[i]; if (valuePair.binding == null) continue; pairs[counter++]= this.bindingResolver.getMemberValuePairBinding(valuePair); } if (counter == 0) return MemberValuePairBinding.NoPair; if (counter != length) { // resize System.arraycopy(pairs, 0, (pairs= new MemberValuePairBinding[counter]), 0, counter); } return pairs; } public IMemberValuePairBinding[] getAllMemberValuePairs() { IMemberValuePairBinding[] pairs= getDeclaredMemberValuePairs(); ReferenceBinding typeBinding= this.binding.getAnnotationType(); if (typeBinding == null || ((typeBinding.tagBits & TagBits.HasMissingType) != 0)) return pairs; MethodBinding[] methods= typeBinding.availableMethods(); // resilience int methodLength= methods == null ? 0 : methods.length; if (methodLength == 0) return pairs; int declaredLength= pairs.length; if (declaredLength == methodLength) return pairs; HashtableOfObject table= new HashtableOfObject(declaredLength); for (int i= 0; i < declaredLength; i++) { char[] internalName= ((MemberValuePairBinding)pairs[i]).internalName(); if (internalName == null) continue; table.put(internalName, pairs[i]); } // handle case of more methods than declared members IMemberValuePairBinding[] allPairs= new IMemberValuePairBinding[methodLength]; for (int i= 0; i < methodLength; i++) { Object pair= table.get(methods[i].selector); allPairs[i]= pair == null ? new DefaultValuePairBinding(methods[i], this.bindingResolver) : (IMemberValuePairBinding)pair; } return allPairs; } public IJavaElement getJavaElement() { if (!(this.bindingResolver instanceof DefaultBindingResolver)) return null; ASTNode node= (ASTNode)((DefaultBindingResolver)this.bindingResolver).bindingsToAstNodes.get(this); if (!(node instanceof Annotation)) return null; ASTNode parent= node.getParent(); IJavaElement parentElement= null; switch (parent.getNodeType()) { case ASTNode.PACKAGE_DECLARATION: IJavaElement cu= ((CompilationUnit)parent.getParent()).getJavaElement(); if (cu instanceof ICompilationUnit) { String pkgName= ((PackageDeclaration)parent).getName().getFullyQualifiedName(); parentElement= ((ICompilationUnit)cu).getPackageDeclaration(pkgName); } break; case ASTNode.ENUM_DECLARATION: case ASTNode.TYPE_DECLARATION: case ASTNode.ANNOTATION_TYPE_DECLARATION: parentElement= ((AbstractTypeDeclaration)parent).resolveBinding().getJavaElement(); break; case ASTNode.FIELD_DECLARATION: VariableDeclarationFragment fragment= (VariableDeclarationFragment)((FieldDeclaration)parent).fragments().get(0); parentElement= fragment.resolveBinding().getJavaElement(); break; case ASTNode.METHOD_DECLARATION: parentElement= ((MethodDeclaration)parent).resolveBinding().getJavaElement(); break; case ASTNode.VARIABLE_DECLARATION_STATEMENT: fragment= (VariableDeclarationFragment)((VariableDeclarationStatement)parent).fragments().get(0); parentElement= fragment.resolveBinding().getJavaElement(); break; default: return null; } if (!(parentElement instanceof IAnnotatable)) return null; if ((parentElement instanceof IMember) && ((IMember)parentElement).isBinary()) { return ((IAnnotatable)parentElement).getAnnotation(getAnnotationType().getQualifiedName()); } return ((IAnnotatable)parentElement).getAnnotation(getName()); } public String getKey() { if (this.key == null) { String recipientKey= getRecipientKey(); this.key= new String(this.binding.computeUniqueKey(recipientKey.toCharArray())); } return this.key; } private String getRecipientKey() { if (!(this.bindingResolver instanceof DefaultBindingResolver)) return ""; //$NON-NLS-1$ DefaultBindingResolver resolver= (DefaultBindingResolver)this.bindingResolver; ASTNode node= (ASTNode)resolver.bindingsToAstNodes.get(this); if (node == null) { // Can happen if annotation bindings have been resolved before having parsed the declaration return ""; //$NON-NLS-1$ } ASTNode recipient= node.getParent(); switch (recipient.getNodeType()) { case ASTNode.PACKAGE_DECLARATION: String pkgName= ((PackageDeclaration)recipient).getName().getFullyQualifiedName(); return pkgName.replace('.', '/'); case ASTNode.TYPE_DECLARATION: return ((TypeDeclaration)recipient).resolveBinding().getKey(); case ASTNode.FIELD_DECLARATION: VariableDeclarationFragment fragment= (VariableDeclarationFragment)((FieldDeclaration)recipient).fragments().get(0); return fragment.resolveBinding().getKey(); case ASTNode.METHOD_DECLARATION: return ((MethodDeclaration)recipient).resolveBinding().getKey(); case ASTNode.VARIABLE_DECLARATION_STATEMENT: fragment= (VariableDeclarationFragment)((VariableDeclarationStatement)recipient).fragments().get(0); return fragment.resolveBinding().getKey(); default: return ""; //$NON-NLS-1$ } } public int getKind() { return IBinding.ANNOTATION; } public int getModifiers() { return Modifier.NONE; } public String getName() { ITypeBinding annotationType= getAnnotationType(); if (annotationType == null) { return new String(this.binding.getAnnotationType().sourceName()); } else { return annotationType.getName(); } } public boolean isDeprecated() { ReferenceBinding typeBinding= this.binding.getAnnotationType(); if (typeBinding == null) return false; return typeBinding.isDeprecated(); } public boolean isEqualTo(IBinding otherBinding) { if (this == otherBinding) return true; if (otherBinding.getKind() != IBinding.ANNOTATION) return false; IAnnotationBinding other= (IAnnotationBinding)otherBinding; if (!getAnnotationType().isEqualTo(other.getAnnotationType())) return false; IMemberValuePairBinding[] memberValuePairs= getDeclaredMemberValuePairs(); IMemberValuePairBinding[] otherMemberValuePairs= other.getDeclaredMemberValuePairs(); if (memberValuePairs.length != otherMemberValuePairs.length) return false; for (int i= 0, length= memberValuePairs.length; i < length; i++) { if (!memberValuePairs[i].isEqualTo(otherMemberValuePairs[i])) return false; } return true; } /* * (non-Javadoc) * @see org.eclipse.jdt.core.dom.IBinding#isRecovered() */ public boolean isRecovered() { ReferenceBinding annotationType= this.binding.getAnnotationType(); return annotationType == null || (annotationType.tagBits & TagBits.HasMissingType) != 0; } public boolean isSynthetic() { return false; } public String toString() { ITypeBinding type= getAnnotationType(); final StringBuffer buffer= new StringBuffer(); buffer.append('@'); if (type != null) buffer.append(type.getName()); buffer.append('('); IMemberValuePairBinding[] pairs= getDeclaredMemberValuePairs(); for (int i= 0, len= pairs.length; i < len; i++) { if (i != 0) buffer.append(", "); //$NON-NLS-1$ buffer.append(pairs[i].toString()); } buffer.append(')'); return buffer.toString(); } }