org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.13 - (download) (annotate)
Thu Oct 23 13:56:41 2008 UTC (13 months ago) by jeromel
Branch: MAIN
CVS Tags: v_943, v_942, v_974_R35x, v_969_R35x, v_A03, v_A02, v_A01, v_A00, v_A07, v_A06, v_A05, v_A04, v_A09, v_A08, v_968_R35x, v_958, v_959, v_950, v_951, v_952, v_953, v_954, v_955, v_956, v_957, v_971_R35x, v_929, v_928, v_925, v_924, v_927, v_926, v_921, v_920, v_923, v_922, v_961, v_960, v_963, v_962, v_964_R35x, v_977_R35x, R3_5, v_A18, v_A19, v_A14, v_A15, v_A16, v_A10, v_A11, v_A12, v_A13, v_966_R35x, v_938, v_939, v_936, v_937, v_934, v_935, v_932, v_933, v_930, v_931, v_970_R35x, v_A21, v_A20, v_A23, v_A22, v_975_R35x, v_976_R35x, v_967_R35x, v_965_R35x, v_A21d, v_A21a, jsr308_A22, v_972_R35x, v_949, v_948, v_947, v_945, v_944, v_941, v_940, R3_5_1, v_A17b, v_A17c, v_973_R35x, v_946, HEAD
Branch point for: JSR_308, R3_5_maintenance
Changes since 1.12: +4 -0 lines
HEAD - 248309
/*******************************************************************************
 * 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.*;

/**
 * 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();
	}

}