Search in sources :

Example 1 with DiagMessage

use of org.checkerframework.framework.source.DiagMessage in project checker-framework by typetools.

the class FieldInvariants method isSuperInvariant.

/**
 * Returns null if {@code superInvar} is a super invariant, otherwise returns the error message.
 *
 * @param superInvar the value to check for being a super invariant
 * @param factory the type factory
 * @return null if {@code superInvar} is a super invariant, otherwise returns the error message
 */
public DiagMessage isSuperInvariant(FieldInvariants superInvar, AnnotatedTypeFactory factory) {
    QualifierHierarchy qualifierHierarchy = factory.getQualifierHierarchy();
    if (!this.fields.containsAll(superInvar.fields)) {
        List<String> missingFields = new ArrayList<>(superInvar.fields);
        missingFields.removeAll(fields);
        return new DiagMessage(Kind.ERROR, "field.invariant.not.found.superclass", String.join(", ", missingFields));
    }
    for (String field : superInvar.fields) {
        List<AnnotationMirror> superQualifiers = superInvar.getQualifiersFor(field);
        List<AnnotationMirror> subQualifiers = this.getQualifiersFor(field);
        for (AnnotationMirror superA : superQualifiers) {
            AnnotationMirror sub = qualifierHierarchy.findAnnotationInSameHierarchy(subQualifiers, superA);
            if (sub == null || !qualifierHierarchy.isSubtype(sub, superA)) {
                return new DiagMessage(Kind.ERROR, "field.invariant.not.subtype.superclass", field, sub, superA);
            }
        }
    }
    return null;
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) DiagMessage(org.checkerframework.framework.source.DiagMessage) QualifierHierarchy(org.checkerframework.framework.type.QualifierHierarchy) ArrayList(java.util.ArrayList)

Example 2 with DiagMessage

use of org.checkerframework.framework.source.DiagMessage 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)

Example 3 with DiagMessage

use of org.checkerframework.framework.source.DiagMessage in project checker-framework by typetools.

the class BaseTypeVisitor method checkQualifierParameter.

/**
 * Issues an error if {@code classTree} has polymorphic fields but is not annotated with
 * {@code @HasQualifierParameter}. Always issue a warning if the type of a static field is
 * annotated with a polymorphic qualifier.
 *
 * <p>Issues an error if {@code classTree} extends or implements a class/interface that has a
 * qualifier parameter, but this class does not.
 *
 * @param classTree the ClassTree to check for polymorphic fields
 */
protected void checkQualifierParameter(ClassTree classTree) {
    // Set of polymorphic qualifiers for hierarchies that do not have a qualifier parameter and
    // therefor cannot appear on a field.
    Set<AnnotationMirror> illegalOnFieldsPolyQual = AnnotationUtils.createAnnotationSet();
    // Set of polymorphic annotations for all hierarchies
    Set<AnnotationMirror> polys = AnnotationUtils.createAnnotationSet();
    TypeElement classElement = TreeUtils.elementFromDeclaration(classTree);
    for (AnnotationMirror top : atypeFactory.getQualifierHierarchy().getTopAnnotations()) {
        AnnotationMirror poly = atypeFactory.getQualifierHierarchy().getPolymorphicAnnotation(top);
        if (poly != null) {
            polys.add(poly);
        }
        if (atypeFactory.hasExplicitQualifierParameterInHierarchy(classElement, top) && atypeFactory.hasExplicitNoQualifierParameterInHierarchy(classElement, top)) {
            checker.reportError(classTree, "conflicting.qual.param", top);
        }
        if (atypeFactory.hasQualifierParameterInHierarchy(classElement, top)) {
            continue;
        }
        if (poly != null) {
            illegalOnFieldsPolyQual.add(poly);
        }
        Element extendsEle = TypesUtils.getTypeElement(classElement.getSuperclass());
        if (extendsEle != null && atypeFactory.hasQualifierParameterInHierarchy(extendsEle, top)) {
            checker.reportError(classTree, "missing.has.qual.param", top);
        } else {
            for (TypeMirror interfaceType : classElement.getInterfaces()) {
                Element interfaceEle = TypesUtils.getTypeElement(interfaceType);
                if (atypeFactory.hasQualifierParameterInHierarchy(interfaceEle, top)) {
                    checker.reportError(classTree, "missing.has.qual.param", top);
                    // only issue error once
                    break;
                }
            }
        }
    }
    for (Tree mem : classTree.getMembers()) {
        if (mem.getKind() == Tree.Kind.VARIABLE) {
            AnnotatedTypeMirror fieldType = atypeFactory.getAnnotatedType(mem);
            List<DiagMessage> hasIllegalPoly;
            if (ElementUtils.isStatic(TreeUtils.elementFromDeclaration((VariableTree) mem))) {
                // A polymorphic qualifier is not allowed on a static field even if the class
                // has a qualifier parameter.
                hasIllegalPoly = polyScanner.visit(fieldType, polys);
            } else {
                hasIllegalPoly = polyScanner.visit(fieldType, illegalOnFieldsPolyQual);
            }
            for (DiagMessage dm : hasIllegalPoly) {
                checker.report(mem, dm);
            }
        }
    }
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) DiagMessage(org.checkerframework.framework.source.DiagMessage) TypeElement(javax.lang.model.element.TypeElement) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) VariableTree(com.sun.source.tree.VariableTree) 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) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 4 with DiagMessage

use of org.checkerframework.framework.source.DiagMessage in project checker-framework by typetools.

the class BaseTypeValidator method isValid.

/**
 * Validate the type against the given tree. This method both issues error messages and also
 * returns a boolean value.
 *
 * <p>This is the entry point to the type validator. Neither this method nor visit should be
 * called directly by a visitor, only use {@link BaseTypeVisitor#validateTypeOf(Tree)}.
 *
 * <p>This method is only called on top-level types, but it validates the entire type including
 * components of a compound type. Subclasses should override this only if there is special-case
 * behavior that should be performed only on top-level types.
 *
 * @param type the type to validate
 * @param tree the tree from which the type originated. If the tree is a method tree, {@code type}
 *     is its return type. If the tree is a variable tree, {@code type} is the variable's type.
 * @return true if the type is valid
 */
@Override
public boolean isValid(AnnotatedTypeMirror type, Tree tree) {
    List<DiagMessage> diagMessages = isValidStructurally(atypeFactory.getQualifierHierarchy(), type);
    if (!diagMessages.isEmpty()) {
        for (DiagMessage d : diagMessages) {
            checker.report(tree, d);
        }
        return false;
    }
    this.isValid = true;
    this.checkTopLevelDeclaredOrPrimitiveType = shouldCheckTopLevelDeclaredOrPrimitiveType(type, tree);
    visit(type, tree);
    return this.isValid;
}
Also used : DiagMessage(org.checkerframework.framework.source.DiagMessage)

Example 5 with DiagMessage

use of org.checkerframework.framework.source.DiagMessage in project checker-framework by typetools.

the class CalledMethodsVisitor method visitMethod.

@Override
public Void visitMethod(MethodTree node, Void p) {
    ExecutableElement elt = TreeUtils.elementFromDeclaration(node);
    AnnotationMirror ecmva = atypeFactory.getDeclAnnotation(elt, EnsuresCalledMethodsVarArgs.class);
    if (ecmva != null) {
        if (!elt.isVarArgs()) {
            checker.report(node, new DiagMessage(Diagnostic.Kind.ERROR, "ensuresvarargs.invalid"));
        }
    }
    return super.visitMethod(node, p);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) DiagMessage(org.checkerframework.framework.source.DiagMessage) ExecutableElement(javax.lang.model.element.ExecutableElement)

Aggregations

DiagMessage (org.checkerframework.framework.source.DiagMessage)7 AnnotationMirror (javax.lang.model.element.AnnotationMirror)6 AnnotatedTypeTree (com.sun.source.tree.AnnotatedTypeTree)3 AnnotationTree (com.sun.source.tree.AnnotationTree)3 ArrayTypeTree (com.sun.source.tree.ArrayTypeTree)3 AssignmentTree (com.sun.source.tree.AssignmentTree)3 CatchTree (com.sun.source.tree.CatchTree)3 ClassTree (com.sun.source.tree.ClassTree)3 CompilationUnitTree (com.sun.source.tree.CompilationUnitTree)3 CompoundAssignmentTree (com.sun.source.tree.CompoundAssignmentTree)3 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)3 EnhancedForLoopTree (com.sun.source.tree.EnhancedForLoopTree)3 ExpressionTree (com.sun.source.tree.ExpressionTree)3 IdentifierTree (com.sun.source.tree.IdentifierTree)3 InstanceOfTree (com.sun.source.tree.InstanceOfTree)3 IntersectionTypeTree (com.sun.source.tree.IntersectionTypeTree)3 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)3 MemberReferenceTree (com.sun.source.tree.MemberReferenceTree)3 MemberSelectTree (com.sun.source.tree.MemberSelectTree)3 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)3