blob: 0b687f39a0ced017d4ef42ee9ea60614c138c602 [file] [log] [blame]
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.framework.util.element.ElementAnnotationUtil.UnexpectedAnnotationLocationException;
import org.checkerframework.javacutil.BugInCF;
/**
* Applies the annotations present for a class type parameter onto an AnnotatedTypeVariable. See
* {@link TypeParamElementAnnotationApplier} for details.
*/
public class ClassTypeParamApplier extends TypeParamElementAnnotationApplier {
/** Apply annotations from {@code element} to {@code type}. */
public static void apply(
AnnotatedTypeVariable type, Element element, AnnotatedTypeFactory typeFactory)
throws UnexpectedAnnotationLocationException {
new ClassTypeParamApplier(type, element, typeFactory).extractAndApply();
}
/**
* Returns true if element represents a type parameter for a class.
*
* @param type ignored
* @param element the element that might be a type parameter
* @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)) {
throw new BugInCF(
"TypeParameter not enclosed by class? Type( "
+ type
+ " ) "
+ "Element ( "
+ element
+ " ) ");
}
enclosingClass = (Symbol.ClassSymbol) element.getEnclosingElement();
}
/**
* Returns TargetType.CLASS_TYPE_PARAMETER.
*
* @return TargetType.CLASS_TYPE_PARAMETER
*/
@Override
protected TargetType lowerBoundTarget() {
return TargetType.CLASS_TYPE_PARAMETER;
}
/**
* Returns TargetType.CLASS_TYPE_PARAMETER_BOUND.
*
* @return TargetType.CLASS_TYPE_PARAMETER_BOUND
*/
@Override
protected TargetType upperBoundTarget() {
return TargetType.CLASS_TYPE_PARAMETER_BOUND;
}
/**
* Returns the index of element in the type parameter list of its enclosing class.
*
* @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};
}
/**
* Returns the raw type attributes of the enclosing class.
*
* @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);
}
}