blob: 908f8e0ce7d42a7d8e0c9e6c29670fe98495280d [file] [log] [blame]
/*******************************************************************************
* 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();
}
}