package testlib.flowexpression; import java.util.List; import javax.lang.model.element.AnnotationMirror; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.type.QualifierHierarchy; import org.checkerframework.framework.util.GraphQualifierHierarchy; import org.checkerframework.framework.util.MultiGraphQualifierHierarchy.MultiGraphFactory; import org.checkerframework.framework.util.dependenttypes.DependentTypesHelper; import org.checkerframework.javacutil.AnnotationUtils; import testlib.flowexpression.qual.FEBot; import testlib.flowexpression.qual.FETop; public class FlowExpressionAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { private AnnotationMirror TOP, BOTTOM; public FlowExpressionAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); TOP = AnnotationUtils.fromClass(elements, FETop.class); BOTTOM = AnnotationUtils.fromClass(elements, FEBot.class); postInit(); } @Override protected DependentTypesHelper createDependentTypesHelper() { return new DependentTypesHelper(this); } @Override public QualifierHierarchy createQualifierHierarchy(MultiGraphFactory factory) { return new FlowExpressionQualifierHierarchy(factory); } private class FlowExpressionQualifierHierarchy extends GraphQualifierHierarchy { public FlowExpressionQualifierHierarchy(MultiGraphFactory f) { super(f, BOTTOM); } @Override public boolean isSubtype(AnnotationMirror subtype, AnnotationMirror supertype) { if (AnnotationUtils.areSameByClass(supertype, FETop.class) || AnnotationUtils.areSameByClass(subtype, FEBot.class)) { return true; } if (AnnotationUtils.areSameByClass(subtype, FETop.class) || AnnotationUtils.areSameByClass(supertype, FEBot.class)) { return false; } List<String> subtypeExpressions = AnnotationUtils.getElementValueArray(subtype, "value", String.class, true); List<String> supertypeExpressions = AnnotationUtils.getElementValueArray(supertype, "value", String.class, true); return subtypeExpressions.containsAll(supertypeExpressions) && supertypeExpressions.containsAll(subtypeExpressions); } @Override public AnnotationMirror leastUpperBound(AnnotationMirror a1, AnnotationMirror a2) { if (isSubtype(a1, a2)) { return a2; } if (isSubtype(a2, a1)) { return a1; } List<String> a1Expressions = AnnotationUtils.getElementValueArray(a1, "value", String.class, true); List<String> a2Expressions = AnnotationUtils.getElementValueArray(a2, "value", String.class, true); if (a1Expressions.containsAll(a2Expressions) && a2Expressions.containsAll(a1Expressions)) { return a1; } return TOP; } } }