| package org.checkerframework.framework.util.element; |
| |
| import com.sun.tools.javac.code.Attribute; |
| import com.sun.tools.javac.code.Attribute.TypeCompound; |
| import com.sun.tools.javac.code.Symbol; |
| import com.sun.tools.javac.code.TargetType; |
| import java.util.List; |
| import javax.lang.model.element.Element; |
| import javax.lang.model.element.ElementKind; |
| import javax.lang.model.type.TypeKind; |
| import org.checkerframework.framework.type.AnnotatedTypeMirror; |
| import org.checkerframework.framework.util.element.ElementAnnotationUtil.UnexpectedAnnotationLocationException; |
| import org.checkerframework.javacutil.BugInCF; |
| |
| /** |
| * Applies annotations to variable declaration (providing they are not the use of a TYPE_PARAMETER). |
| */ |
| public class VariableApplier extends TargetedElementAnnotationApplier { |
| |
| /** Apply annotations from {@code element} to {@code type}. */ |
| public static void apply(final AnnotatedTypeMirror type, final Element element) |
| throws UnexpectedAnnotationLocationException { |
| new VariableApplier(type, element).extractAndApply(); |
| } |
| |
| private static final ElementKind[] acceptedKinds = { |
| ElementKind.LOCAL_VARIABLE, ElementKind.RESOURCE_VARIABLE, ElementKind.EXCEPTION_PARAMETER |
| }; |
| |
| /** |
| * Returns true if this is a variable declaration including fields an enum constants. |
| * |
| * @param typeMirror ignored |
| * @return true if this is a variable declaration including fields an enum constants |
| */ |
| public static boolean accepts(final AnnotatedTypeMirror typeMirror, final Element element) { |
| return ElementAnnotationUtil.contains(element.getKind(), acceptedKinds) |
| || element.getKind().isField(); |
| } |
| |
| private final Symbol.VarSymbol varSymbol; |
| |
| VariableApplier(final AnnotatedTypeMirror type, final Element element) { |
| super(type, element); |
| varSymbol = (Symbol.VarSymbol) element; |
| |
| if (type.getKind() == TypeKind.UNION && element.getKind() != ElementKind.EXCEPTION_PARAMETER) { |
| throw new BugInCF( |
| "Union types only allowed for exception parameters. " |
| + "Type: " |
| + type |
| + " for element: " |
| + element); |
| } |
| // TODO: need a way to split the union types into the right alternative |
| // to use for the annotation. The exception_index is probably what we |
| // need to look at, but it might not be set at this point. |
| } |
| |
| @Override |
| protected TargetType[] annotatedTargets() { |
| return new TargetType[] { |
| TargetType.LOCAL_VARIABLE, |
| TargetType.RESOURCE_VARIABLE, |
| TargetType.EXCEPTION_PARAMETER, |
| TargetType.FIELD |
| }; |
| } |
| |
| @Override |
| protected TargetType[] validTargets() { |
| return new TargetType[] { |
| TargetType.NEW, |
| TargetType.CAST, |
| TargetType.INSTANCEOF, |
| TargetType.METHOD_INVOCATION_TYPE_ARGUMENT, |
| TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT, |
| TargetType.METHOD_REFERENCE, |
| TargetType.CONSTRUCTOR_REFERENCE, |
| TargetType.METHOD_REFERENCE_TYPE_ARGUMENT, |
| TargetType.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT |
| }; |
| } |
| |
| @Override |
| protected Iterable<Attribute.TypeCompound> getRawTypeAttributes() { |
| return varSymbol.getRawTypeAttributes(); |
| } |
| |
| @Override |
| protected boolean isAccepted() { |
| return accepts(type, element); |
| } |
| |
| @Override |
| protected void handleTargeted(final List<TypeCompound> targeted) |
| throws UnexpectedAnnotationLocationException { |
| ElementAnnotationUtil.annotateViaTypeAnnoPosition(type, targeted); |
| } |
| |
| @Override |
| public void extractAndApply() throws UnexpectedAnnotationLocationException { |
| // Add declaration annotations to the local variable type |
| ElementAnnotationUtil.addDeclarationAnnotationsFromElement( |
| type, varSymbol.getAnnotationMirrors()); |
| super.extractAndApply(); |
| } |
| } |