package checkers.util;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import com.sun.source.tree.*;
import checkers.quals.Dependent;
import checkers.types.AnnotatedTypeFactory;
import checkers.types.AnnotatedTypeMirror;
import checkers.types.AnnotatedTypeMirror.AnnotatedExecutableType;
public class DependentTypes {
private final AnnotatedTypeFactory factory;
private final AnnotationUtils annoUtils;
public DependentTypes(ProcessingEnvironment env, CompilationUnitTree root) {
this.factory = new AnnotatedTypeFactory(env, null, root, null);
this.annoUtils = AnnotationUtils.getInstance(env);
}
AnnotationMirror getResult(Dependent anno) {
try {
anno.result();
} catch (MirroredTypeException exp) {
Name valName = TypesUtils.getQualifiedName((DeclaredType)exp.getTypeMirror());
return annoUtils.fromName(valName);
}
assert false : "shouldn't be here";
return null;
}
AnnotationMirror getWhen(Dependent anno) {
try {
anno.when();
} catch (MirroredTypeException exp) {
Name valName = TypesUtils.getQualifiedName((DeclaredType)exp.getTypeMirror());
return annoUtils.fromName(valName);
}
assert false : "shouldn't be here";
return null;
}
public void doSubsitution(Element symbol, AnnotatedTypeMirror type, AnnotatedTypeMirror receiver) {
Dependent dependentInfo = symbol.getAnnotation(Dependent.class);
if (dependentInfo == null)
return;
if (receiver == null)
return;
AnnotationMirror ifpresent = getWhen(dependentInfo);
if (receiver.hasAnnotation(ifpresent)) {
type.clearAnnotations();
AnnotationMirror then = getResult(dependentInfo);
type.addAnnotation(then);
}
}
public void handle(Tree tree, AnnotatedTypeMirror type) {
if (!(tree instanceof ExpressionTree))
return;
ExpressionTree expr = (ExpressionTree)tree;
Element symbol = null;
if (expr instanceof IdentifierTree)
symbol = TreeUtils.elementFromUse((IdentifierTree)expr);
else if (expr instanceof MemberSelectTree)
symbol = TreeUtils.elementFromUse((MemberSelectTree)expr);
if (symbol == null
|| (!symbol.getKind().isField()
&& symbol.getKind() != ElementKind.LOCAL_VARIABLE))
return;
// FIXME: handle this case
AnnotatedTypeMirror receiver = factory.getReceiver(expr);
if (receiver != null)
doSubsitution(symbol, type, receiver);
}
public void handleConstructor(NewClassTree tree, AnnotatedExecutableType type) {
if (!(tree.getIdentifier() instanceof AnnotatedTypeTree))
return;
AnnotatedTypeMirror dt = factory.getAnnotatedType(tree);
ExecutableElement constructorElt = InternalUtils.constructor(tree);
for (int i = 0; i < constructorElt.getParameters().size(); ++i) {
Element parameter = constructorElt.getParameters().get(i);
AnnotatedTypeMirror paramType = type.getParameterTypes().get(i);
doSubsitution(parameter, paramType, dt);
}
}
}