package org.checkerframework.framework.util.element;
import static com.sun.tools.javac.code.TargetType.CAST;
import static com.sun.tools.javac.code.TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT;
import static com.sun.tools.javac.code.TargetType.CONSTRUCTOR_REFERENCE;
import static com.sun.tools.javac.code.TargetType.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT;
import static com.sun.tools.javac.code.TargetType.EXCEPTION_PARAMETER;
import static com.sun.tools.javac.code.TargetType.INSTANCEOF;
import static com.sun.tools.javac.code.TargetType.LOCAL_VARIABLE;
import static com.sun.tools.javac.code.TargetType.METHOD_FORMAL_PARAMETER;
import static com.sun.tools.javac.code.TargetType.METHOD_INVOCATION_TYPE_ARGUMENT;
import static com.sun.tools.javac.code.TargetType.METHOD_RECEIVER;
import static com.sun.tools.javac.code.TargetType.METHOD_REFERENCE;
import static com.sun.tools.javac.code.TargetType.METHOD_REFERENCE_TYPE_ARGUMENT;
import static com.sun.tools.javac.code.TargetType.METHOD_RETURN;
import static com.sun.tools.javac.code.TargetType.NEW;
import static com.sun.tools.javac.code.TargetType.RESOURCE_VARIABLE;
import static com.sun.tools.javac.code.TargetType.THROWS;
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 method type parameter onto an AnnotatedTypeVariable. */
public class MethodTypeParamApplier extends TypeParamElementAnnotationApplier {
public static void apply(
AnnotatedTypeVariable type, Element element, AnnotatedTypeFactory typeFactory) {
new MethodTypeParamApplier(type, element, typeFactory).extractAndApply();
}
/** @return true if element represents a type parameter for a method */
public static boolean accepts(final AnnotatedTypeMirror type, final Element element) {
return element.getKind() == ElementKind.TYPE_PARAMETER
&& element.getEnclosingElement() instanceof Symbol.MethodSymbol;
}
private final Symbol.MethodSymbol enclosingMethod;
MethodTypeParamApplier(
AnnotatedTypeVariable type, Element element, AnnotatedTypeFactory typeFactory) {
super(type, element, typeFactory);
if (!(element.getEnclosingElement() instanceof Symbol.MethodSymbol)) {
ErrorReporter.errorAbort(
"TypeParameter not enclosed by method? Type( "
+ type
+ " ) "
+ "Element ( "
+ element
+ " ) ");
}
enclosingMethod = (Symbol.MethodSymbol) element.getEnclosingElement();
}
/** @return TargetType.METHOD_TYPE_PARAMETER */
@Override
protected TargetType lowerBoundTarget() {
return TargetType.METHOD_TYPE_PARAMETER;
}
/** @return TargetType.METHOD_TYPE_PARAMETER_BOUND */
@Override
protected TargetType upperBoundTarget() {
return TargetType.METHOD_TYPE_PARAMETER_BOUND;
}
/** @return the index of element in the type parameter list of its enclosing method */
@Override
public int getElementIndex() {
return enclosingMethod.getTypeParameters().indexOf(element);
}
@Override
protected TargetType[] validTargets() {
return new TargetType[] {
METHOD_RETURN,
METHOD_FORMAL_PARAMETER,
METHOD_RECEIVER,
THROWS,
LOCAL_VARIABLE,
RESOURCE_VARIABLE,
EXCEPTION_PARAMETER,
NEW,
CAST,
INSTANCEOF,
METHOD_INVOCATION_TYPE_ARGUMENT,
CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT,
METHOD_REFERENCE,
CONSTRUCTOR_REFERENCE,
METHOD_REFERENCE_TYPE_ARGUMENT,
CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT,
};
}
/** @return the TypeCompounds (annotations) of the declaring element */
@Override
protected Iterable<Attribute.TypeCompound> getRawTypeAttributes() {
return enclosingMethod.getRawTypeAttributes();
}
@Override
protected boolean isAccepted() {
return accepts(type, element);
}
}