org.checkerframework.framework.ajava.AnnotationTransferVisitor Maven / Gradle / Ivy
Show all versions of checker Show documentation
package org.checkerframework.framework.ajava;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
import com.github.javaparser.ast.type.ArrayType;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.github.javaparser.ast.type.PrimitiveType;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.ast.type.TypeParameter;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.TypeKind;
/**
* A visitor that adds all annotations from a {@code AnnotatedTypeMirror} to the corresponding
* JavaParser type, including nested types like array components.
*
* The {@code AnnotatedTypeMirror} is passed as the secondary parameter to the visit methods.
*/
public class AnnotationTransferVisitor extends VoidVisitorAdapter {
@Override
public void visit(ArrayType target, AnnotatedTypeMirror type) {
// type can also be a wildcard, in which case don't try to transfer component
// annotations (there can't be any)
if (type.getKind() == TypeKind.ARRAY) {
target.getComponentType().accept(this, ((AnnotatedArrayType) type).getComponentType());
}
transferAnnotations(type, target);
}
@Override
public void visit(ClassOrInterfaceType target, AnnotatedTypeMirror type) {
if (type.getKind() == TypeKind.DECLARED) {
AnnotatedDeclaredType declaredType = (AnnotatedDeclaredType) type;
if (target.getTypeArguments().isPresent()) {
NodeList types = target.getTypeArguments().get();
for (int i = 0; i < types.size(); i++) {
types.get(i).accept(this, declaredType.getTypeArguments().get(i));
}
}
}
transferAnnotations(type, target);
}
@Override
public void visit(PrimitiveType target, AnnotatedTypeMirror type) {
transferAnnotations(type, target);
}
@Override
public void visit(TypeParameter target, AnnotatedTypeMirror type) {
AnnotatedTypeVariable annotatedTypeVar = (AnnotatedTypeVariable) type;
NodeList bounds = target.getTypeBound();
if (bounds.size() == 1) {
bounds.get(0).accept(this, annotatedTypeVar.getUpperBound());
}
}
/**
* Transfers annotations from {@code annotatedType} to {@code target}. Does nothing if {@code
* annotatedType} is null.
*
* @param annotatedType type with annotations to transfer
* @param target a JavaParser node representing the type to transfer annotations to
*/
private void transferAnnotations(
@Nullable AnnotatedTypeMirror annotatedType, NodeWithAnnotations> target) {
if (annotatedType == null) {
return;
}
for (AnnotationMirror annotation : annotatedType.getAnnotations()) {
AnnotationExpr convertedAnnotation =
AnnotationMirrorToAnnotationExprConversion.annotationMirrorToAnnotationExpr(
annotation);
target.addAnnotation(convertedAnnotation);
}
}
}