package org.checkerframework.checker.signature;
import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.CompoundAssignmentTree;
import java.lang.annotation.Annotation;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import org.checkerframework.checker.signature.qual.SignatureBottom;
import org.checkerframework.checker.signature.qual.SignatureUnknown;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TreeUtils;
// TODO: Does not yet handle method signature annotations, such as
// @MethodDescriptor.
public class SignatureAnnotatedTypeFactory extends BaseAnnotatedTypeFactory {
protected final AnnotationMirror SIGNATURE_UNKNOWN;
public SignatureAnnotatedTypeFactory(BaseTypeChecker checker) {
super(checker);
SIGNATURE_UNKNOWN = AnnotationUtils.fromClass(elements, SignatureUnknown.class);
this.postInit();
}
@Override
protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers() {
return getBundledTypeQualifiersWithPolyAll(SignatureUnknown.class, SignatureBottom.class);
}
@Override
public TreeAnnotator createTreeAnnotator() {
return new ListTreeAnnotator(new SignatureTreeAnnotator(this), super.createTreeAnnotator());
}
private class SignatureTreeAnnotator extends TreeAnnotator {
public SignatureTreeAnnotator(AnnotatedTypeFactory atypeFactory) {
super(atypeFactory);
}
@Override
public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) {
if (TreeUtils.isStringConcatenation(tree)) {
type.removeAnnotationInHierarchy(SIGNATURE_UNKNOWN);
// This could be made more precise, when desired.
type.addAnnotation(SignatureUnknown.class);
}
return null; // super.visitBinary(tree, type);
}
@Override
public Void visitCompoundAssignment(CompoundAssignmentTree node, AnnotatedTypeMirror type) {
if (TreeUtils.isStringCompoundConcatenation(node)) {
type.removeAnnotationInHierarchy(SIGNATURE_UNKNOWN);
// This could be made more precise, when desired.
type.addAnnotation(SignatureUnknown.class);
}
return null; // super.visitCompoundAssignment(node, type);
}
}
}