use of org.checkerframework.framework.util.FieldInvariants in project checker-framework by typetools.
the class ValueAnnotatedTypeFactory method getFieldInvariants.
@Override
public FieldInvariants getFieldInvariants(TypeElement element) {
AnnotationMirror fieldInvarAnno = getDeclAnnotation(element, MinLenFieldInvariant.class);
if (fieldInvarAnno == null) {
return null;
}
List<String> fields = AnnotationUtils.getElementValueArray(fieldInvarAnno, minLenFieldInvariantFieldElement, String.class);
List<Integer> minlens = AnnotationUtils.getElementValueArray(fieldInvarAnno, minLenFieldInvariantMinLenElement, Integer.class);
List<AnnotationMirror> qualifiers = CollectionsPlume.mapList((Integer minlen) -> createArrayLenRangeAnnotation(minlen, Integer.MAX_VALUE), minlens);
FieldInvariants superInvariants = super.getFieldInvariants(element);
return new FieldInvariants(superInvariants, fields, qualifiers);
}
use of org.checkerframework.framework.util.FieldInvariants in project checker-framework by typetools.
the class AnnotatedTypeFactory method addAnnotationFromFieldInvariant.
/**
* Adds the qualifier specified by a field invariant for {@code field} to {@code type}.
*
* @param type annotated type to which the annotation is added
* @param accessedVia the annotated type of the receiver of the accessing tree. (Only used to get
* the type element of the underling type.)
* @param field element representing the field
*/
protected void addAnnotationFromFieldInvariant(AnnotatedTypeMirror type, AnnotatedTypeMirror accessedVia, VariableElement field) {
TypeMirror declaringType = accessedVia.getUnderlyingType();
// Find the first upper bound that isn't a wildcard or type variable
while (declaringType.getKind() == TypeKind.WILDCARD || declaringType.getKind() == TypeKind.TYPEVAR) {
if (declaringType.getKind() == TypeKind.WILDCARD) {
declaringType = TypesUtils.wildUpperBound(declaringType, processingEnv);
} else if (declaringType.getKind() == TypeKind.TYPEVAR) {
declaringType = ((TypeVariable) declaringType).getUpperBound();
}
}
TypeElement typeElement = TypesUtils.getTypeElement(declaringType);
if (ElementUtils.enclosingTypeElement(field).equals(typeElement)) {
// cannot be this field, even if the field has the same name.
return;
}
FieldInvariants invariants = getFieldInvariants(typeElement);
if (invariants == null) {
return;
}
List<AnnotationMirror> invariantAnnos = invariants.getQualifiersFor(field.getSimpleName());
type.replaceAnnotations(invariantAnnos);
}
use of org.checkerframework.framework.util.FieldInvariants in project checker-framework by typetools.
the class AnnotatedTypeFactory method getFieldInvariants.
/**
* Returns the field invariants for the given class, as expressed by the user in {@link
* FieldInvariant @FieldInvariant} method annotations.
*
* <p>Subclasses may implement their own field invariant annotations if {@link
* FieldInvariant @FieldInvariant} is not expressive enough. They must override this method to
* properly create AnnotationMirror and also override {@link
* #getFieldInvariantDeclarationAnnotations()} to return their field invariants.
*
* @param element class for which to get invariants
* @return field invariants for {@code element}
*/
public FieldInvariants getFieldInvariants(TypeElement element) {
if (element == null) {
return null;
}
AnnotationMirror fieldInvarAnno = getDeclAnnotation(element, FieldInvariant.class);
if (fieldInvarAnno == null) {
return null;
}
List<String> fields = AnnotationUtils.getElementValueArray(fieldInvarAnno, fieldInvariantFieldElement, String.class);
List<@CanonicalName Name> classes = AnnotationUtils.getElementValueClassNames(fieldInvarAnno, fieldInvariantQualifierElement);
List<AnnotationMirror> qualifiers = CollectionsPlume.mapList((Name name) -> AnnotationBuilder.fromName(elements, name), classes);
if (qualifiers.size() == 1) {
while (fields.size() > qualifiers.size()) {
qualifiers.add(qualifiers.get(0));
}
}
if (fields.size() != qualifiers.size()) {
// FieldInvariants object. The BaseTypeVisitor will issue an error.
return new FieldInvariants(fields, qualifiers);
}
// Only keep qualifiers that are supported by this checker. (The other qualifiers cannot
// be checked by this checker, so they must be ignored.)
List<String> annotatedFields = new ArrayList<>();
List<AnnotationMirror> supportedQualifiers = new ArrayList<>();
for (int i = 0; i < fields.size(); i++) {
if (isSupportedQualifier(qualifiers.get(i))) {
annotatedFields.add(fields.get(i));
supportedQualifiers.add(qualifiers.get(i));
}
}
if (annotatedFields.isEmpty()) {
return null;
}
return new FieldInvariants(annotatedFields, supportedQualifiers);
}
use of org.checkerframework.framework.util.FieldInvariants in project checker-framework by typetools.
the class BaseTypeVisitor method checkFieldInvariantDeclarations.
/**
* Check that the field invariant declaration annotations meet the following requirements:
*
* <ol>
* <!-- The item numbering is referred to in the body of the method.-->
* <li value="1">If the superclass of {@code classTree} has a field invariant, then the field
* invariant for {@code classTree} must include all the fields in the superclass invariant
* and those fields' annotations must be a subtype (or equal) to the annotations for those
* fields in the superclass.
* <li value="2">The fields in the invariant must be a.) final and b.) declared in a superclass
* of {@code classTree}.
* <li value="3">The qualifier for each field must be a subtype of the annotation on the
* declaration of that field.
* <li value="4">The field invariant has an equal number of fields and qualifiers, or it has one
* qualifier and at least one field.
* </ol>
*
* @param classTree class that might have a field invariant
* @checker_framework.manual #field-invariants Field invariants
*/
protected void checkFieldInvariantDeclarations(ClassTree classTree) {
TypeElement elt = TreeUtils.elementFromDeclaration(classTree);
FieldInvariants invariants = atypeFactory.getFieldInvariants(elt);
if (invariants == null) {
// No invariants to check
return;
}
// Where to issue an error, if any.
Tree errorTree = atypeFactory.getFieldInvariantAnnotationTree(classTree.getModifiers().getAnnotations());
if (errorTree == null) {
// If the annotation was inherited, then there is no annotation tree, so issue the
// error on the class.
errorTree = classTree;
}
// Checks #4 (see method Javadoc)
if (!invariants.isWellFormed()) {
checker.reportError(errorTree, "field.invariant.not.wellformed");
return;
}
TypeMirror superClass = elt.getSuperclass();
List<String> fieldsNotFound = new ArrayList<>(invariants.getFields());
Set<VariableElement> fieldElts = ElementUtils.findFieldsInTypeOrSuperType(superClass, fieldsNotFound);
// Checks that fields are declared in super class. (#2b)
if (!fieldsNotFound.isEmpty()) {
String notFoundString = String.join(", ", fieldsNotFound);
checker.reportError(errorTree, "field.invariant.not.found", notFoundString);
}
FieldInvariants superInvar = atypeFactory.getFieldInvariants(TypesUtils.getTypeElement(superClass));
if (superInvar != null) {
// Checks #3 (see method Javadoc)
DiagMessage superError = invariants.isSuperInvariant(superInvar, atypeFactory);
if (superError != null) {
checker.report(errorTree, superError);
}
}
List<String> notFinal = new ArrayList<>();
for (VariableElement field : fieldElts) {
String fieldName = field.getSimpleName().toString();
if (!ElementUtils.isFinal(field)) {
notFinal.add(fieldName);
}
AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(field);
List<AnnotationMirror> annos = invariants.getQualifiersFor(field.getSimpleName());
for (AnnotationMirror invariantAnno : annos) {
AnnotationMirror declaredAnno = type.getEffectiveAnnotationInHierarchy(invariantAnno);
if (declaredAnno == null) {
// invariant anno isn't in this hierarchy
continue;
}
if (!atypeFactory.getQualifierHierarchy().isSubtype(invariantAnno, declaredAnno)) {
// Checks #3
checker.reportError(errorTree, "field.invariant.not.subtype", fieldName, invariantAnno, declaredAnno);
}
}
}
// Checks #2a
if (!notFinal.isEmpty()) {
String notFinalString = String.join(", ", notFinal);
checker.reportError(errorTree, "field.invariant.not.final", notFinalString);
}
}
Aggregations