package org.checkerframework.framework.type.treeannotator;
import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.util.SimpleTreeVisitor;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
/**
* {@link TreeAnnotator} is an abstract SimpleTreeVisitor to be used with {@link ListTreeAnnotator}
*
* @see ListTreeAnnotator
* @see PropagationTreeAnnotator
* @see ImplicitsTreeAnnotator
*/
public abstract class TreeAnnotator extends SimpleTreeVisitor<Void, AnnotatedTypeMirror> {
protected final AnnotatedTypeFactory atypeFactory;
public TreeAnnotator(AnnotatedTypeFactory atypeFactory) {
this.atypeFactory = atypeFactory;
}
/**
* This method is not called when checking a method invocation against its declaration. So,
* instead of overriding this method, override TypeAnnotator.visitExecutable.
* TypeAnnotator.visitExecutable is called both when checking method declarations and method
* invocations.
*
* @see org.checkerframework.framework.type.typeannotator.TypeAnnotator
*/
@Override
public Void visitMethod(MethodTree node, AnnotatedTypeMirror p) {
return super.visitMethod(node, p);
}
/**
* When overriding this method, getAnnotatedType on the left and right operands should only be
* called when absolutely necessary. Otherwise, the checker will be very slow on heavily nested
* binary trees. (For example, a + b + c + d + e + f + g + h.)
*
* <p>If a checker's performance is still too slow, the types of binary trees could be computed
* in a subclass of {@link org.checkerframework.framework.flow.CFTransfer}. When computing the
* types in a transfer, look up the value in the store rather than the AnnotatedTypeFactory.
* Then this method should annotate binary trees with top so that the type applied in the
* transfer is always a subtype of the type the AnnotatedTypeFactory computes.
*/
@Override
public Void visitBinary(BinaryTree node, AnnotatedTypeMirror mirror) {
return super.visitBinary(node, mirror);
}
}