package org.checkerframework.framework.util.element;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.TargetType;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.javacutil.ErrorReporter;
/**
* Applies the annotations present for a class type parameter onto an AnnotatedTypeVariable. See
* {@link TypeParamElementAnnotationApplier} for details.
*/
public class ClassTypeParamApplier extends TypeParamElementAnnotationApplier {
public static void apply(
AnnotatedTypeVariable type, Element element, AnnotatedTypeFactory typeFactory) {
new ClassTypeParamApplier(type, element, typeFactory).extractAndApply();
}
/** @return true if element represents a type parameter for a class */
public static boolean accepts(final AnnotatedTypeMirror type, final Element element) {
return element.getKind() == ElementKind.TYPE_PARAMETER
&& element.getEnclosingElement() instanceof Symbol.ClassSymbol;
}
/** The class that holds the type parameter element */
private final Symbol.ClassSymbol enclosingClass;
ClassTypeParamApplier(
AnnotatedTypeVariable type, Element element, AnnotatedTypeFactory typeFactory) {
super(type, element, typeFactory);
if (!(element.getEnclosingElement() instanceof Symbol.ClassSymbol)) {
ErrorReporter.errorAbort(
"TypeParameter not enclosed by class? Type( "
+ type
+ " ) "
+ "Element ( "
+ element
+ " ) ");
}
enclosingClass = (Symbol.ClassSymbol) element.getEnclosingElement();
}
/** @return TargetType.CLASS_TYPE_PARAMETER */
@Override
protected TargetType lowerBoundTarget() {
return TargetType.CLASS_TYPE_PARAMETER;
}
/** @return TargetType.CLASS_TYPE_PARAMETER_BOUND */
@Override
protected TargetType upperBoundTarget() {
return TargetType.CLASS_TYPE_PARAMETER_BOUND;
}
/** @return the index of element in the type parameter list of its enclosing class */
@Override
public int getElementIndex() {
return enclosingClass.getTypeParameters().indexOf(element);
}
@Override
protected TargetType[] validTargets() {
return new TargetType[] {TargetType.CLASS_EXTENDS};
}
/** @return the raw type attributes of the enclosing class */
@Override
protected Iterable<Attribute.TypeCompound> getRawTypeAttributes() {
return enclosingClass.getRawTypeAttributes();
}
@Override
protected boolean isAccepted() {
return accepts(type, element);
}
}