Search in sources :

Example 1 with FieldInvariants

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);
}
Also used : FieldInvariants(org.checkerframework.framework.util.FieldInvariants) AnnotationMirror(javax.lang.model.element.AnnotationMirror)

Example 2 with FieldInvariants

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);
}
Also used : FieldInvariants(org.checkerframework.framework.util.FieldInvariants) AnnotationMirror(javax.lang.model.element.AnnotationMirror) TypeMirror(javax.lang.model.type.TypeMirror) TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) TypeElement(javax.lang.model.element.TypeElement) ATypeElement(scenelib.annotations.el.ATypeElement)

Example 3 with FieldInvariants

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);
}
Also used : FieldInvariants(org.checkerframework.framework.util.FieldInvariants) AnnotationMirror(javax.lang.model.element.AnnotationMirror) ArrayList(java.util.ArrayList) CanonicalName(org.checkerframework.checker.signature.qual.CanonicalName) FullyQualifiedName(org.checkerframework.checker.signature.qual.FullyQualifiedName) Name(javax.lang.model.element.Name)

Example 4 with FieldInvariants

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);
    }
}
Also used : FieldInvariants(org.checkerframework.framework.util.FieldInvariants) TypeElement(javax.lang.model.element.TypeElement) ArrayList(java.util.ArrayList) VariableElement(javax.lang.model.element.VariableElement) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) DiagMessage(org.checkerframework.framework.source.DiagMessage) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) TypeCastTree(com.sun.source.tree.TypeCastTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) InstanceOfTree(com.sun.source.tree.InstanceOfTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ThrowTree(com.sun.source.tree.ThrowTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ReturnTree(com.sun.source.tree.ReturnTree) ArrayTypeTree(com.sun.source.tree.ArrayTypeTree) UnaryTree(com.sun.source.tree.UnaryTree) VariableTree(com.sun.source.tree.VariableTree) TypeParameterTree(com.sun.source.tree.TypeParameterTree) NewClassTree(com.sun.source.tree.NewClassTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) IntersectionTypeTree(com.sun.source.tree.IntersectionTypeTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) NewArrayTree(com.sun.source.tree.NewArrayTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) ModifiersTree(com.sun.source.tree.ModifiersTree) AnnotationTree(com.sun.source.tree.AnnotationTree) MethodTree(com.sun.source.tree.MethodTree) ClassTree(com.sun.source.tree.ClassTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) JCTree(com.sun.tools.javac.tree.JCTree)

Aggregations

AnnotationMirror (javax.lang.model.element.AnnotationMirror)4 FieldInvariants (org.checkerframework.framework.util.FieldInvariants)4 ArrayList (java.util.ArrayList)2 TypeElement (javax.lang.model.element.TypeElement)2 TypeMirror (javax.lang.model.type.TypeMirror)2 AnnotatedTypeTree (com.sun.source.tree.AnnotatedTypeTree)1 AnnotationTree (com.sun.source.tree.AnnotationTree)1 ArrayTypeTree (com.sun.source.tree.ArrayTypeTree)1 AssignmentTree (com.sun.source.tree.AssignmentTree)1 CatchTree (com.sun.source.tree.CatchTree)1 ClassTree (com.sun.source.tree.ClassTree)1 CompilationUnitTree (com.sun.source.tree.CompilationUnitTree)1 CompoundAssignmentTree (com.sun.source.tree.CompoundAssignmentTree)1 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)1 EnhancedForLoopTree (com.sun.source.tree.EnhancedForLoopTree)1 ExpressionTree (com.sun.source.tree.ExpressionTree)1 IdentifierTree (com.sun.source.tree.IdentifierTree)1 InstanceOfTree (com.sun.source.tree.InstanceOfTree)1 IntersectionTypeTree (com.sun.source.tree.IntersectionTypeTree)1 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)1