blob: 43c6515e80543646fe87b1094ccc1fe6da132a9a [file] [log] [blame]
package org.checkerframework.framework.testchecker.flowexpression;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.util.Elements;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.framework.testchecker.flowexpression.qual.FEBottom;
import org.checkerframework.framework.testchecker.flowexpression.qual.FETop;
import org.checkerframework.framework.testchecker.flowexpression.qual.FlowExp;
import org.checkerframework.framework.type.MostlyNoElementQualifierHierarchy;
import org.checkerframework.framework.util.QualifierKind;
import org.checkerframework.framework.util.dependenttypes.DependentTypesHelper;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TreeUtils;
public class FlowExpressionAnnotatedTypeFactory extends BaseAnnotatedTypeFactory {
private AnnotationMirror TOP, BOTTOM;
/** The FlowExp.value field/element. */
ExecutableElement flowExpValueElement =
TreeUtils.getMethod(FlowExp.class, "value", 0, processingEnv);
public FlowExpressionAnnotatedTypeFactory(BaseTypeChecker checker) {
super(checker);
TOP = AnnotationBuilder.fromClass(elements, FETop.class);
BOTTOM = AnnotationBuilder.fromClass(elements, FEBottom.class);
postInit();
}
@Override
protected DependentTypesHelper createDependentTypesHelper() {
return new DependentTypesHelper(this);
}
@Override
protected FlowExpressionQualifierHierarchy createQualifierHierarchy() {
return new FlowExpressionQualifierHierarchy(this.getSupportedTypeQualifiers(), elements);
}
private class FlowExpressionQualifierHierarchy extends MostlyNoElementQualifierHierarchy {
/**
* Create a {@code FlowExpressionQualifierHierarchy}.
*
* @param qualifierClasses classes of annotations that are the qualifiers
* @param elements element utils
*/
public FlowExpressionQualifierHierarchy(
Set<Class<? extends Annotation>> qualifierClasses, Elements elements) {
super(qualifierClasses, elements);
}
@Override
protected boolean isSubtypeWithElements(
AnnotationMirror subAnno,
QualifierKind subKind,
AnnotationMirror superAnno,
QualifierKind superKind) {
List<String> subtypeExpressions =
AnnotationUtils.getElementValueArray(subAnno, flowExpValueElement, String.class);
List<String> supertypeExpressions =
AnnotationUtils.getElementValueArray(superAnno, flowExpValueElement, String.class);
return subtypeExpressions.containsAll(supertypeExpressions)
&& supertypeExpressions.containsAll(subtypeExpressions);
}
@Override
protected AnnotationMirror leastUpperBoundWithElements(
AnnotationMirror a1,
QualifierKind qualifierKind1,
AnnotationMirror a2,
QualifierKind qualifierKind2,
QualifierKind lubKind) {
if (qualifierKind1.getName() == FEBottom.class.getCanonicalName()) {
return a2;
} else if (qualifierKind2.getName() == FEBottom.class.getCanonicalName()) {
return a1;
}
List<String> a1Expressions =
AnnotationUtils.getElementValueArray(a1, flowExpValueElement, String.class);
List<String> a2Expressions =
AnnotationUtils.getElementValueArray(a2, flowExpValueElement, String.class);
if (a1Expressions.containsAll(a2Expressions) && a2Expressions.containsAll(a1Expressions)) {
return a1;
}
return TOP;
}
@Override
protected AnnotationMirror greatestLowerBoundWithElements(
AnnotationMirror a1,
QualifierKind qualifierKind1,
AnnotationMirror a2,
QualifierKind qualifierKind2,
QualifierKind glbKind) {
if (qualifierKind1.getName() == FETop.class.getCanonicalName()) {
return a2;
} else if (qualifierKind2.getName() == FETop.class.getCanonicalName()) {
return a1;
}
List<String> a1Expressions =
AnnotationUtils.getElementValueArray(a1, flowExpValueElement, String.class);
List<String> a2Expressions =
AnnotationUtils.getElementValueArray(a2, flowExpValueElement, String.class);
if (a1Expressions.containsAll(a2Expressions) && a2Expressions.containsAll(a1Expressions)) {
return a1;
}
return BOTTOM;
}
}
}