blob: 118c4facec60eb71dc49c727843caa5c10b75c8c [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.Collections;
import java.util.List;
import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv;
import org.eclipse.jdt.apt.core.internal.util.PackageUtil;
import org.eclipse.jdt.apt.core.internal.util.SourcePositionImpl;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IPackageBinding;
import com.sun.mirror.declaration.AnnotationMirror;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;
import com.sun.mirror.declaration.ClassDeclaration;
import com.sun.mirror.declaration.EnumDeclaration;
import com.sun.mirror.declaration.InterfaceDeclaration;
import com.sun.mirror.declaration.Modifier;
import com.sun.mirror.declaration.PackageDeclaration;
import com.sun.mirror.declaration.TypeDeclaration;
import com.sun.mirror.util.DeclarationVisitor;
import com.sun.mirror.util.SourcePosition;
public class PackageDeclarationImpl extends DeclarationImpl implements PackageDeclaration
{
// If this package came from directly requesting it via the environment,
// need to hide the source position, as this is an artifact of our implementation
private final boolean _hideSourcePosition;
/** The back-pointer to the type declaration that created this package declaration
* @see TypeDeclarationImpl#getPackage()
*/
private final TypeDeclarationImpl _typeDecl;
// Lazily initialized unless specified in constructor.
private IPackageFragment[] _pkgFragments = null;
public PackageDeclarationImpl(
final IPackageBinding binding,
final TypeDeclarationImpl typeDecl,
final BaseProcessorEnv env,
final boolean hideSourcePosition)
{
this(binding,
typeDecl,
env,
hideSourcePosition,
null);
}
public PackageDeclarationImpl(
final IPackageBinding binding,
final TypeDeclarationImpl typeDecl,
final BaseProcessorEnv env,
final boolean hideSourcePosition,
final IPackageFragment[] pkgFragments)
{
super(binding, env);
_typeDecl = typeDecl;
_hideSourcePosition = hideSourcePosition;
_pkgFragments = pkgFragments;
}
public IPackageBinding getPackageBinding(){ return (IPackageBinding)_binding; }
public void accept(DeclarationVisitor visitor)
{
visitor.visitPackageDeclaration(this);
}
public <A extends Annotation> A getAnnotation(Class<A> anno)
{
return _getAnnotation(anno, getPackageBinding().getAnnotations());
}
public Collection<AnnotationMirror> getAnnotationMirrors()
{
return _getAnnotationMirrors(getPackageBinding().getAnnotations());
}
public Collection<AnnotationTypeDeclaration> getAnnotationTypes()
{
// jdt currently have no support for package declaration.
return Collections.emptyList();
}
public Collection<ClassDeclaration> getClasses() {
initFragments();
List<IType> types = getTypesInPackage(_pkgFragments);
List<ClassDeclaration> classes = new ArrayList<ClassDeclaration>();
for (IType type : types) {
try {
// isClass() will return true if TypeDeclaration is an InterfaceDeclaration
if (type.isClass()) {
TypeDeclaration td = _env.getTypeDeclaration( type );
if ( td instanceof ClassDeclaration ) {
classes.add((ClassDeclaration)td);
}
}
}
catch (JavaModelException ex) {} // No longer exists, don't return it
}
return classes;
}
public Collection<EnumDeclaration> getEnums() {
initFragments();
List<IType> types = getTypesInPackage(_pkgFragments);
List<EnumDeclaration> enums = new ArrayList<EnumDeclaration>();
for (IType type : types) {
try {
if (type.isEnum()) {
enums.add((EnumDeclaration)_env.getTypeDeclaration(type));
}
}
catch (JavaModelException ex) {} // No longer exists, don't return it
}
return enums;
}
public Collection<InterfaceDeclaration> getInterfaces() {
initFragments();
List<IType> types = getTypesInPackage(_pkgFragments);
List<InterfaceDeclaration> interfaces = new ArrayList<InterfaceDeclaration>();
for (IType type : types) {
try {
if (type.isInterface()) {
interfaces.add((InterfaceDeclaration)_env.getTypeDeclaration(type));
}
}
catch (JavaModelException ex) {} // No longer exists, don't return it
}
return interfaces;
}
public String getDocComment()
{
return null;
}
public Collection<Modifier> getModifiers()
{
// package doesn't have modifiers.
return Collections.emptyList();
}
public SourcePosition getPosition()
{
if (_hideSourcePosition)
return null;
if(_typeDecl.isFromSource()){
final CompilationUnit unit = _typeDecl.getCompilationUnit();
final ASTNode node = unit.findDeclaringNode(getDeclarationBinding());
if( node == null ) return null;
final int start = node.getStartPosition();
return new SourcePositionImpl(start,
node.getLength(),
unit.getLineNumber(start),
unit.getColumnNumber(start),
this);
}
return null;
}
public String getQualifiedName()
{
return getPackageBinding().getName();
}
public String getSimpleName()
{
IPackageBinding pkg = getPackageBinding();
final String[] components = pkg.getNameComponents();
if( components == null || components.length == 0 ) return ""; //$NON-NLS-1$
return components[components.length - 1];
}
public MirrorKind kind(){ return MirrorKind.PACKAGE; }
public String toString(){ return getQualifiedName(); }
public IPackageBinding getDeclarationBinding(){ return (IPackageBinding)_binding; }
public boolean isFromSource(){ return _typeDecl.isFromSource(); }
/**
* Make sure to call this before attempting to access _pkgFragments.
* We initialize this field lazily, because it is very expensive to compute and
* there are some common questions such as getQualifiedName() that can be
* answered without initializing it at all.
*/
private void initFragments() {
if (null == _pkgFragments) {
_pkgFragments = PackageUtil.getPackageFragments(_binding.getName(), _env);
}
}
private static List<IType> getTypesInPackage(final IPackageFragment[] fragments) {
List<IType> types = new ArrayList<IType>();
try {
// Get all top-level classes -- ignore local, member, and anonymous classes
for (IPackageFragment fragment : fragments) {
for (IClassFile classFile : fragment.getClassFiles()) {
IType type = classFile.getType();
if (! (type.isLocal() || type.isMember() || type.isAnonymous()) ) {
types.add(type);
}
}
for (ICompilationUnit compUnit : fragment.getCompilationUnits()) {
for (IType type : compUnit.getTypes()) {
if (! (type.isLocal() || type.isMember() || type.isAnonymous()) ) {
types.add(type);
}
}
}
}
}
catch (JavaModelException jme) {
// Ignore -- project is in a bad state. This will get recalled if necessary
}
return types;
}
}