blob: fae289490ed13ea4a1963bb6490b77947bee2c84 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2011 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.apt.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ElementVisitor;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.NestingKind;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.apt.dispatch.BaseProcessingEnvImpl;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
public class TypeElementImpl extends ElementImpl implements TypeElement {
private final ElementKind _kindHint;
/**
* In general, clients should call {@link Factory#newDeclaredType(ReferenceBinding)} or
* {@link Factory#newElement(org.eclipse.jdt.internal.compiler.lookup.Binding)} to
* create new instances.
*/
TypeElementImpl(BaseProcessingEnvImpl env, ReferenceBinding binding, ElementKind kindHint) {
super(env, binding);
_kindHint = kindHint;
}
@Override
public <R, P> R accept(ElementVisitor<R, P> v, P p)
{
return v.visitType(this, p);
}
@Override
protected AnnotationBinding[] getAnnotationBindings()
{
return ((ReferenceBinding)_binding).getAnnotations();
}
@Override
public List<? extends Element> getEnclosedElements() {
ReferenceBinding binding = (ReferenceBinding)_binding;
List<Element> enclosed = new ArrayList<Element>(binding.fieldCount() + binding.methods().length);
for (MethodBinding method : binding.methods()) {
ExecutableElement executable = new ExecutableElementImpl(_env, method);
enclosed.add(executable);
}
for (FieldBinding field : binding.fields()) {
// TODO no field should be excluded according to the JLS
if (!field.isSynthetic()) {
VariableElement variable = new VariableElementImpl(_env, field);
enclosed.add(variable);
}
}
for (ReferenceBinding memberType : binding.memberTypes()) {
TypeElement type = new TypeElementImpl(_env, memberType, null);
enclosed.add(type);
}
return Collections.unmodifiableList(enclosed);
}
@Override
public Element getEnclosingElement() {
ReferenceBinding binding = (ReferenceBinding)_binding;
ReferenceBinding enclosingType = binding.enclosingType();
if (null == enclosingType) {
// this is a top level type; get its package
return _env.getFactory().newPackageElement(binding.fPackage);
}
else {
return _env.getFactory().newElement(binding.enclosingType());
}
}
@Override
public String getFileName() {
char[] name = ((ReferenceBinding)_binding).getFileName();
if (name == null)
return null;
return new String(name);
}
@Override
public List<? extends TypeMirror> getInterfaces() {
ReferenceBinding binding = (ReferenceBinding)_binding;
if (null == binding.superInterfaces() || binding.superInterfaces().length == 0) {
return Collections.emptyList();
}
List<TypeMirror> interfaces = new ArrayList<TypeMirror>(binding.superInterfaces().length);
for (ReferenceBinding interfaceBinding : binding.superInterfaces()) {
TypeMirror interfaceType = _env.getFactory().newTypeMirror(interfaceBinding);
if (interfaceType.getKind() == TypeKind.ERROR) {
if (this._env.getSourceVersion().compareTo(SourceVersion.RELEASE_6) > 0) {
// for jdk 7 and above, add error types
interfaces.add(interfaceType);
}
} else {
interfaces.add(interfaceType);
}
}
return Collections.unmodifiableList(interfaces);
}
@Override
public ElementKind getKind() {
if (null != _kindHint) {
return _kindHint;
}
ReferenceBinding refBinding = (ReferenceBinding)_binding;
// The order of these comparisons is important: e.g., enum is subset of class
if (refBinding.isEnum()) {
return ElementKind.ENUM;
}
else if (refBinding.isAnnotationType()) {
return ElementKind.ANNOTATION_TYPE;
}
else if (refBinding.isInterface()) {
return ElementKind.INTERFACE;
}
else if (refBinding.isClass()) {
return ElementKind.CLASS;
}
else {
throw new IllegalArgumentException("TypeElement " + new String(refBinding.shortReadableName()) + //$NON-NLS-1$
" has unexpected attributes " + refBinding.modifiers); //$NON-NLS-1$
}
}
@Override
public Set<Modifier> getModifiers()
{
ReferenceBinding refBinding = (ReferenceBinding)_binding;
int modifiers = refBinding.modifiers;
if (refBinding.isInterface() && refBinding.isNestedType()) {
modifiers |= ClassFileConstants.AccStatic;
}
return Factory.getModifiers(modifiers, getKind(), refBinding.isBinaryBinding());
}
@Override
public NestingKind getNestingKind() {
ReferenceBinding refBinding = (ReferenceBinding)_binding;
if (refBinding.isAnonymousType()) {
return NestingKind.ANONYMOUS;
} else if (refBinding.isLocalType()) {
return NestingKind.LOCAL;
} else if (refBinding.isMemberType()) {
return NestingKind.MEMBER;
}
return NestingKind.TOP_LEVEL;
}
@Override
PackageElement getPackage()
{
ReferenceBinding binding = (ReferenceBinding)_binding;
return _env.getFactory().newPackageElement((PackageBinding)binding.fPackage);
}
@Override
public Name getQualifiedName() {
ReferenceBinding binding = (ReferenceBinding)_binding;
char[] qName;
if (binding.isMemberType()) {
qName = CharOperation.concatWith(binding.enclosingType().compoundName, binding.sourceName, '.');
CharOperation.replace(qName, '$', '.');
} else {
qName = CharOperation.concatWith(binding.compoundName, '.');
}
return new NameImpl(qName);
}
/*
* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.apt.model.ElementImpl#getSimpleName()
* @return last segment of name, e.g. for pa.pb.X.Y return Y.
*/
@Override
public Name getSimpleName()
{
ReferenceBinding binding = (ReferenceBinding)_binding;
return new NameImpl(binding.sourceName());
}
@Override
public TypeMirror getSuperclass() {
ReferenceBinding binding = (ReferenceBinding)_binding;
ReferenceBinding superBinding = binding.superclass();
if (null == superBinding || binding.isInterface()) {
return _env.getFactory().getNoType(TypeKind.NONE);
}
// superclass of a type must be a DeclaredType
return _env.getFactory().newTypeMirror(superBinding);
}
@Override
public List<? extends TypeParameterElement> getTypeParameters() {
ReferenceBinding binding = (ReferenceBinding)_binding;
TypeVariableBinding[] variables = binding.typeVariables();
if (variables.length == 0) {
return Collections.emptyList();
}
List<TypeParameterElement> params = new ArrayList<TypeParameterElement>(variables.length);
for (TypeVariableBinding variable : variables) {
params.add(_env.getFactory().newTypeParameterElement(variable, this));
}
return Collections.unmodifiableList(params);
}
@Override
public boolean hides(Element hidden)
{
if (!(hidden instanceof TypeElementImpl)) {
return false;
}
ReferenceBinding hiddenBinding = (ReferenceBinding)((TypeElementImpl)hidden)._binding;
if (hiddenBinding.isPrivate()) {
return false;
}
ReferenceBinding hiderBinding = (ReferenceBinding)_binding;
if (TypeBinding.equalsEquals(hiddenBinding, hiderBinding)) {
return false;
}
if (!hiddenBinding.isMemberType() || !hiderBinding.isMemberType()) {
return false;
}
if (!CharOperation.equals(hiddenBinding.sourceName, hiderBinding.sourceName)) {
return false;
}
return null != hiderBinding.enclosingType().findSuperTypeOriginatingFrom(hiddenBinding.enclosingType());
}
@Override
public String toString() {
ReferenceBinding binding = (ReferenceBinding) this._binding;
char[] concatWith = CharOperation.concatWith(binding.compoundName, '.');
if (binding.isNestedType()) {
CharOperation.replace(concatWith, '$', '.');
return new String(concatWith);
}
return new String(concatWith);
}
}