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 java.util.List; import javax.lang.model.element.TypeElement; import org.checkerframework.framework.type.AnnotatedTypeMirror; /** * When discovering supertypes of an AnnotatedTypeMirror we want to annotate each supertype with the * annotations of the subtypes class declaration. This class provides static methods to do this for * a list of supertypes. An instance of this class handles ONE supertype. */ public class SuperTypeApplier extends IndexedElementAnnotationApplier { /** * Annotates each supertype with annotations from subtypeElement's extends/implements clauses. * * @param supertypes supertypes to annotate * @param subtypeElement element that may have annotations to apply to supertypes */ public static void annotateSupers( List<AnnotatedTypeMirror.AnnotatedDeclaredType> supertypes, TypeElement subtypeElement) { for (int i = 0; i < supertypes.size(); i++) { final AnnotatedTypeMirror supertype = supertypes.get(i); // Offset i by -1 since typeIndex should start from -1. // -1 represents the (implicit) extends clause class. // 0 and greater represent the implements clause interfaces. // For details see the JSR 308 specification: // http://types.cs.washington.edu/jsr308/specification/java-annotation-design.html#class-file%3Aext%3Ari%3Aextends final int typeIndex = i - 1; new SuperTypeApplier(supertype, subtypeElement, typeIndex).extractAndApply(); } } private final Symbol.ClassSymbol subclassSymbol; /** * The type_index of the supertype being annotated. * * <p>Note: Due to the semantics of TypeAnnotationPosition, type_index/index numbering works as * follows: * * <p>If subtypeElement represents a class and not an interface: * * <p>then the first member of supertypes represents the object and the relevant type_index = * -1; interface indices are offset by 1. * * <p>else all members of supertypes represent interfaces and their indices == their index in * the supertypes list */ private final int index; /** * Note: This is not meant to be used in apply explicitly unlike all other AnnotationAppliers it * is intended to be used for annotate super types via the static annotateSuper method, hence * the private constructor */ SuperTypeApplier( final AnnotatedTypeMirror supertype, final TypeElement subclassElement, final int index) { super(supertype, subclassElement); this.subclassSymbol = (Symbol.ClassSymbol) subclassElement; this.index = index; } /** @return the type_index that should represent supertype */ @Override public int getElementIndex() { return index; } /** @return the type_index of anno's TypeAnnotationPosition */ @Override public int getTypeCompoundIndex(Attribute.TypeCompound anno) { return anno.getPosition().type_index; } /** @return TargetType.CLASS_EXTENDS */ @Override protected TargetType[] annotatedTargets() { return new TargetType[] {TargetType.CLASS_EXTENDS}; } /** @return TargetType.CLASS_TYPE_PARAMETER, TargetType.CLASS_TYPE_PARAMETER_BOUND */ @Override protected TargetType[] validTargets() { return new TargetType[] { TargetType.CLASS_TYPE_PARAMETER, TargetType.CLASS_TYPE_PARAMETER_BOUND }; } /** @return the TypeCompounds (annotations) of the subclass */ @Override protected Iterable<Attribute.TypeCompound> getRawTypeAttributes() { return subclassSymbol.getRawTypeAttributes(); } @Override protected void handleTargeted(List<Attribute.TypeCompound> targeted) { ElementAnnotationUtil.annotateViaTypeAnnoPosition(type, targeted); } @Override protected boolean isAccepted() { return true; } }