| /******************************************************************************* |
| * Copyright (c) 2005, 2007 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 |
| *******************************************************************************/ |
| package org.eclipse.jdt.apt.core.internal.declaration; |
| |
| import java.lang.annotation.Annotation; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv; |
| import org.eclipse.jdt.apt.core.internal.util.SourcePositionImpl; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.BodyDeclaration; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.IExtendedModifier; |
| import org.eclipse.jdt.core.dom.IAnnotationBinding; |
| import org.eclipse.jdt.core.dom.SingleVariableDeclaration; |
| import org.eclipse.jdt.core.dom.VariableDeclaration; |
| import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
| |
| import com.sun.mirror.declaration.AnnotationMirror; |
| import com.sun.mirror.declaration.Modifier; |
| import com.sun.mirror.util.SourcePosition; |
| |
| /** |
| * Most mirror implementation are based on bindings but in some cases because of |
| * incomplete information no bindings will be created at all. This implementation |
| * is to allow clients to get to the partial information that's available on certain |
| * declarations. |
| * |
| * The prefered implementation of the API is to rely on the binding since it is a more |
| * complete and versatile representation of a declaration. |
| */ |
| public abstract class ASTBasedDeclarationImpl extends EclipseDeclarationImpl { |
| |
| static final String EMPTY_STRING = ""; //$NON-NLS-1$ |
| /** either a <code>BodyDeclaration</code> or a <code>VariableDeclaration</code> */ |
| protected final ASTNode _astNode; |
| /** the file which this ast node came from */ |
| protected final IFile _file; |
| public ASTBasedDeclarationImpl( |
| ASTNode astNode, |
| IFile file, |
| BaseProcessorEnv env) |
| { |
| super(env); |
| assert astNode != null : "ast node cannot be missing"; //$NON-NLS-1$ |
| assert file != null : "file cannot be missing";//$NON-NLS-1$ |
| |
| assert astNode instanceof BodyDeclaration || |
| astNode instanceof VariableDeclaration : |
| "ast node must be either a body declaration or a variable declaration"; //$NON-NLS-1$ |
| |
| _astNode = astNode; |
| _file = file; |
| } |
| |
| public Collection<Modifier> getModifiers() |
| { |
| int modBits = 0; |
| if( _astNode instanceof BodyDeclaration ) |
| modBits = ((BodyDeclaration)_astNode).getModifiers(); |
| else if( _astNode instanceof SingleVariableDeclaration ) |
| modBits = ((SingleVariableDeclaration)_astNode).getModifiers(); |
| else{ |
| ASTNode parent = ((VariableDeclarationFragment)_astNode).getParent(); |
| if( _astNode instanceof BodyDeclaration ) |
| modBits = ((BodyDeclaration)parent).getModifiers(); |
| } |
| |
| return getModifiers(modBits); |
| } |
| |
| private Collection<Modifier> getModifiers(int modBits) |
| { |
| final List<Modifier> mods = new ArrayList<Modifier>(4); |
| if( org.eclipse.jdt.core.dom.Modifier.isAbstract(modBits) ) |
| mods.add(Modifier.ABSTRACT); |
| if( org.eclipse.jdt.core.dom.Modifier.isFinal(modBits) ) |
| mods.add(Modifier.FINAL); |
| if( org.eclipse.jdt.core.dom.Modifier.isNative(modBits) ) |
| mods.add(Modifier.NATIVE); |
| if( org.eclipse.jdt.core.dom.Modifier.isPrivate(modBits) ) |
| mods.add(Modifier.PRIVATE); |
| if( org.eclipse.jdt.core.dom.Modifier.isProtected(modBits) ) |
| mods.add(Modifier.PROTECTED); |
| if( org.eclipse.jdt.core.dom.Modifier.isPublic(modBits) ) |
| mods.add(Modifier.PUBLIC); |
| if( org.eclipse.jdt.core.dom.Modifier.isStatic(modBits) ) |
| mods.add(Modifier.STATIC); |
| if( org.eclipse.jdt.core.dom.Modifier.isStrictfp(modBits) ) |
| mods.add(Modifier.STRICTFP); |
| if( org.eclipse.jdt.core.dom.Modifier.isSynchronized(modBits) ) |
| mods.add(Modifier.SYNCHRONIZED); |
| if( org.eclipse.jdt.core.dom.Modifier.isTransient(modBits) ) |
| mods.add(Modifier.TRANSIENT); |
| if( org.eclipse.jdt.core.dom.Modifier.isVolatile(modBits) ) |
| mods.add(Modifier.VOLATILE); |
| return mods; |
| |
| } |
| |
| public <A extends Annotation> A getAnnotation(Class<A> annotationClass) |
| { |
| final IAnnotationBinding[] instances = getAnnotationInstancesFromAST(); |
| return _getAnnotation(annotationClass, instances); |
| } |
| |
| public Collection<AnnotationMirror> getAnnotationMirrors() |
| { |
| final IAnnotationBinding[] instances = getAnnotationInstancesFromAST(); |
| return _getAnnotationMirrors(instances); |
| } |
| |
| @SuppressWarnings("unchecked") // DOM AST API returns raw collections |
| private IAnnotationBinding[] getAnnotationInstancesFromAST() |
| { |
| IAnnotationBinding[] instances = null; |
| List extendsMods = null; |
| switch( _astNode.getNodeType() ) |
| { |
| case ASTNode.TYPE_DECLARATION: |
| case ASTNode.ANNOTATION_TYPE_DECLARATION: |
| case ASTNode.ENUM_DECLARATION: |
| case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION: |
| case ASTNode.METHOD_DECLARATION: |
| case ASTNode.FIELD_DECLARATION: |
| case ASTNode.ENUM_CONSTANT_DECLARATION: |
| extendsMods = ((BodyDeclaration)_astNode).modifiers(); |
| break; |
| |
| case ASTNode.SINGLE_VARIABLE_DECLARATION: |
| extendsMods = ((SingleVariableDeclaration)_astNode).modifiers(); |
| break; |
| case ASTNode.VARIABLE_DECLARATION_FRAGMENT: |
| final ASTNode parent = ((VariableDeclarationFragment)_astNode).getParent(); |
| if( parent instanceof BodyDeclaration ) |
| extendsMods = ((BodyDeclaration)parent).modifiers(); |
| break; |
| |
| default: |
| throw new IllegalStateException(); |
| } |
| if( extendsMods != null ){ |
| int count = 0; |
| for( Object obj : extendsMods ){ |
| final IExtendedModifier extMod = (IExtendedModifier)obj; |
| if( extMod.isAnnotation() ) |
| count ++; |
| } |
| instances = new IAnnotationBinding[count]; |
| int index = 0; |
| for( Object obj : extendsMods ){ |
| final IExtendedModifier extMod = (IExtendedModifier)obj; |
| if( extMod.isAnnotation() ) |
| instances[index ++] = |
| ((org.eclipse.jdt.core.dom.Annotation)extMod).resolveAnnotationBinding(); |
| } |
| } |
| return instances; |
| } |
| |
| public boolean isFromSource(){ return true; } |
| |
| ASTNode getAstNode(){ |
| return _astNode; |
| } |
| |
| CompilationUnit getCompilationUnit(){ |
| return (CompilationUnit)_astNode.getRoot(); |
| } |
| |
| public IFile getResource(){ |
| return _file; |
| } |
| |
| public SourcePosition getPosition() |
| { |
| final ASTNode node = getRangeNode(); |
| if( node == null ) return null; |
| final CompilationUnit unit = getCompilationUnit(); |
| final int start = node.getStartPosition(); |
| return new SourcePositionImpl( |
| start, |
| node.getLength(), |
| unit.getLineNumber(start), |
| unit.getColumnNumber(start), |
| this); |
| |
| } |
| |
| public boolean isBindingBased(){ return false; } |
| |
| public boolean equals(Object obj) |
| { |
| if(obj instanceof ASTBasedDeclarationImpl) |
| return _astNode == ((ASTBasedDeclarationImpl)obj)._astNode; |
| |
| return false; |
| } |
| |
| public int hashCode(){ |
| return _astNode.hashCode(); |
| } |
| } |