Search in sources :

Example 56 with AnnotatedTypeMirror

use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.

the class BaseTypeVisitor method checkVarargs.

/**
 * A helper method to check that the array type of actual varargs is a subtype of the
 * corresponding required varargs, and issues "argument.invalid" error if it's not a subtype of
 * the required one.
 *
 * <p>Note it's required that type checking for each element in varargs is executed by the
 * caller before or after calling this method.
 *
 * @see #checkArguments(List, List)
 * @param invokedMethod the method type to be invoked
 * @param tree method or constructor invocation tree
 */
protected void checkVarargs(AnnotatedExecutableType invokedMethod, Tree tree) {
    if (!invokedMethod.isVarArgs()) {
        return;
    }
    List<AnnotatedTypeMirror> formals = invokedMethod.getParameterTypes();
    int numFormals = formals.size();
    int lastArgIndex = numFormals - 1;
    AnnotatedArrayType lastParamAnnotatedType = (AnnotatedArrayType) formals.get(lastArgIndex);
    // We will skip type checking so that we avoid duplicating error message
    // if the last argument is same depth with the depth of formal varargs
    // because type checking is already done in checkArguments.
    List<? extends ExpressionTree> args;
    switch(tree.getKind()) {
        case METHOD_INVOCATION:
            args = ((MethodInvocationTree) tree).getArguments();
            break;
        case NEW_CLASS:
            args = ((NewClassTree) tree).getArguments();
            break;
        default:
            throw new AssertionError("Unexpected kind of tree: " + tree);
    }
    if (numFormals == args.size()) {
        AnnotatedTypeMirror lastArgType = atypeFactory.getAnnotatedType(args.get(args.size() - 1));
        if (lastArgType.getKind() == TypeKind.ARRAY && AnnotatedTypes.getArrayDepth(lastParamAnnotatedType) == AnnotatedTypes.getArrayDepth((AnnotatedArrayType) lastArgType)) {
            return;
        }
    }
    AnnotatedTypeMirror wrappedVarargsType = atypeFactory.getAnnotatedTypeVarargsArray(tree);
    // annotation to be checked for generated varargs array.
    if (wrappedVarargsType == null) {
        return;
    }
    // is also needed to avoid duplicating error message caused by elements in varargs
    if (wrappedVarargsType.getKind() == TypeKind.ARRAY) {
        ((AnnotatedArrayType) wrappedVarargsType).setComponentType(lastParamAnnotatedType.getComponentType());
    }
    commonAssignmentCheck(lastParamAnnotatedType, wrappedVarargsType, tree, "varargs.type.incompatible");
}
Also used : AnnotatedArrayType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 57 with AnnotatedTypeMirror

use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.

the class BaseTypeVisitor method visitAnnotation.

/* TODO: something similar to visitReturn should be done.
     * public Void visitThrow(ThrowTree node, Void p) {
     * return super.visitThrow(node, p);
     * }
     */
/**
 * Ensure that the annotation arguments comply to their declarations. This needs some special
 * casing, as annotation arguments form special trees.
 */
@Override
public Void visitAnnotation(AnnotationTree node, Void p) {
    List<? extends ExpressionTree> args = node.getArguments();
    if (args.isEmpty()) {
        // Nothing to do if there are no annotation arguments.
        return null;
    }
    TypeElement anno = (TypeElement) TreeInfo.symbol((JCTree) node.getAnnotationType());
    Name annoName = anno.getQualifiedName();
    if (annoName.contentEquals(DefaultQualifier.class.getName()) || annoName.contentEquals(SuppressWarnings.class.getName())) {
        // Skip these two annotations, as we don't care about the arguments to them.
        return null;
    }
    // Mapping from argument simple name to its annotated type.
    Map<String, AnnotatedTypeMirror> annoTypes = new HashMap<>();
    for (Element encl : ElementFilter.methodsIn(anno.getEnclosedElements())) {
        AnnotatedExecutableType exeatm = (AnnotatedExecutableType) atypeFactory.getAnnotatedType(encl);
        AnnotatedTypeMirror retty = exeatm.getReturnType();
        annoTypes.put(encl.getSimpleName().toString(), retty);
    }
    for (ExpressionTree arg : args) {
        if (!(arg instanceof AssignmentTree)) {
            // TODO: when can this happen?
            continue;
        }
        AssignmentTree at = (AssignmentTree) arg;
        // we don't have a type for annotations.
        if (at.getExpression().getKind() == Tree.Kind.ANNOTATION) {
            visitAnnotation((AnnotationTree) at.getExpression(), p);
            continue;
        }
        if (at.getExpression().getKind() == Tree.Kind.NEW_ARRAY) {
            NewArrayTree nat = (NewArrayTree) at.getExpression();
            boolean isAnno = false;
            for (ExpressionTree init : nat.getInitializers()) {
                if (init.getKind() == Tree.Kind.ANNOTATION) {
                    visitAnnotation((AnnotationTree) init, p);
                    isAnno = true;
                }
            }
            if (isAnno) {
                continue;
            }
        }
        AnnotatedTypeMirror expected = annoTypes.get(at.getVariable().toString());
        Pair<Tree, AnnotatedTypeMirror> preAssCtxt = visitorState.getAssignmentContext();
        {
            // Determine and set the new assignment context.
            ExpressionTree var = at.getVariable();
            assert var instanceof IdentifierTree : "Expected IdentifierTree as context. Found: " + var;
            AnnotatedTypeMirror meth = atypeFactory.getAnnotatedType(var);
            assert meth instanceof AnnotatedExecutableType : "Expected AnnotatedExecutableType as context. Found: " + meth;
            AnnotatedTypeMirror newctx = ((AnnotatedExecutableType) meth).getReturnType();
            visitorState.setAssignmentContext(Pair.of((Tree) null, newctx));
        }
        try {
            AnnotatedTypeMirror actual = atypeFactory.getAnnotatedType(at.getExpression());
            if (expected.getKind() != TypeKind.ARRAY) {
                // Expected is not an array -> direct comparison.
                commonAssignmentCheck(expected, actual, at.getExpression(), "annotation.type.incompatible");
            } else {
                if (actual.getKind() == TypeKind.ARRAY) {
                    // Both actual and expected are arrays.
                    commonAssignmentCheck(expected, actual, at.getExpression(), "annotation.type.incompatible");
                } else {
                    // The declaration is an array type, but just a single
                    // element is given.
                    commonAssignmentCheck(((AnnotatedArrayType) expected).getComponentType(), actual, at.getExpression(), "annotation.type.incompatible");
                }
            }
        } finally {
            visitorState.setAssignmentContext(preAssCtxt);
        }
    }
    return null;
}
Also used : HashMap(java.util.HashMap) 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) JCTree(com.sun.tools.javac.tree.JCTree) IdentifierTree(com.sun.source.tree.IdentifierTree) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) Name(javax.lang.model.element.Name) AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) NewArrayTree(com.sun.source.tree.NewArrayTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) 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) 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) ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) NewArrayTree(com.sun.source.tree.NewArrayTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) 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) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) AssignmentTree(com.sun.source.tree.AssignmentTree)

Example 58 with AnnotatedTypeMirror

use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.

the class BaseTypeVisitor method visitMethodInvocation.

/**
 * Performs a method invocation check.
 *
 * <p>An invocation of a method, m, on the receiver, r is valid only if:
 *
 * <ul>
 *   <li>passed arguments are subtypes of corresponding m parameters
 *   <li>r is a subtype of m receiver type
 *   <li>if m is generic, passed type arguments are subtypes of m type variables
 * </ul>
 */
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
    // hard to check), also see CFGBuilder.visitMethodInvocation.
    if (TreeUtils.elementFromUse(node) == null || TreeUtils.isEnumSuper(node)) {
        return super.visitMethodInvocation(node, p);
    }
    if (shouldSkipUses(node)) {
        return super.visitMethodInvocation(node, p);
    }
    Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> mfuPair = atypeFactory.methodFromUse(node);
    AnnotatedExecutableType invokedMethod = mfuPair.first;
    List<AnnotatedTypeMirror> typeargs = mfuPair.second;
    if (!atypeFactory.ignoreUninferredTypeArguments) {
        for (AnnotatedTypeMirror typearg : typeargs) {
            if (typearg.getKind() == TypeKind.WILDCARD && ((AnnotatedWildcardType) typearg).isUninferredTypeArgument()) {
                checker.report(Result.failure("type.arguments.not.inferred", invokedMethod.getElement().getSimpleName()), node);
                // only issue error once per method
                break;
            }
        }
    }
    List<AnnotatedTypeParameterBounds> paramBounds = new ArrayList<>();
    for (AnnotatedTypeVariable param : invokedMethod.getTypeVariables()) {
        paramBounds.add(param.getBounds());
    }
    checkTypeArguments(node, paramBounds, typeargs, node.getTypeArguments());
    List<AnnotatedTypeMirror> params = AnnotatedTypes.expandVarArgs(atypeFactory, invokedMethod, node.getArguments());
    checkArguments(params, node.getArguments());
    checkVarargs(invokedMethod, node);
    if (isVectorCopyInto(invokedMethod)) {
        typeCheckVectorCopyIntoArgument(node, params);
    }
    ExecutableElement invokedMethodElement = invokedMethod.getElement();
    if (!ElementUtils.isStatic(invokedMethodElement) && !TreeUtils.isSuperCall(node)) {
        checkMethodInvocability(invokedMethod, node);
    }
    // check precondition annotations
    checkPreconditions(node, contractsUtils.getPreconditions(invokedMethodElement));
    // Do not call super, as that would observe the arguments without
    // a set assignment context.
    scan(node.getMethodSelect(), p);
    // super.visitMethodInvocation(node, p);
    return null;
}
Also used : AnnotatedTypeParameterBounds(org.checkerframework.framework.type.AnnotatedTypeParameterBounds) AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)

Example 59 with AnnotatedTypeMirror

use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.

the class BaseTypeVisitor method visitEnhancedForLoop.

/**
 * Performs a subtype check, to test whether the node expression iterable type is a subtype of
 * the variable type in the enhanced for loop.
 *
 * <p>If the subtype check fails, it issues a "enhancedfor.type.incompatible" error.
 */
@Override
public Void visitEnhancedForLoop(EnhancedForLoopTree node, Void p) {
    AnnotatedTypeMirror var = atypeFactory.getAnnotatedTypeLhs(node.getVariable());
    AnnotatedTypeMirror iterableType = atypeFactory.getAnnotatedType(node.getExpression());
    AnnotatedTypeMirror iteratedType = AnnotatedTypes.getIteratedType(checker.getProcessingEnvironment(), atypeFactory, iterableType);
    boolean valid = validateTypeOf(node.getVariable());
    if (valid) {
        commonAssignmentCheck(var, iteratedType, node.getExpression(), "enhancedfor.type.incompatible");
    }
    return super.visitEnhancedForLoop(node, p);
}
Also used : AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 60 with AnnotatedTypeMirror

use of org.checkerframework.framework.type.AnnotatedTypeMirror in project checker-framework by typetools.

the class BaseTypeVisitor method checkExceptionParameter.

// **********************************************************************
// Helper methods to provide a single overriding point
// **********************************************************************
/**
 * Issue error if the exception parameter is not a supertype of the annotation specified by
 * {@link #getExceptionParameterLowerBoundAnnotations()}, which is top by default.
 *
 * <p>Subclasses may override this method to change the behavior of this check. Subclasses
 * wishing to enforce that exception parameter be annotated with other annotations can just
 * override {@link #getExceptionParameterLowerBoundAnnotations()}.
 *
 * @param node CatchTree to check
 */
protected void checkExceptionParameter(CatchTree node) {
    Set<? extends AnnotationMirror> requiredAnnotations = getExceptionParameterLowerBoundAnnotations();
    AnnotatedTypeMirror exPar = atypeFactory.getAnnotatedType(node.getParameter());
    for (AnnotationMirror required : requiredAnnotations) {
        AnnotationMirror found = exPar.getAnnotationInHierarchy(required);
        assert found != null;
        if (!atypeFactory.getQualifierHierarchy().isSubtype(required, found)) {
            checker.report(Result.failure("exception.parameter.invalid", found, required), node.getParameter());
        }
        if (exPar.getKind() == TypeKind.UNION) {
            AnnotatedUnionType aut = (AnnotatedUnionType) exPar;
            for (AnnotatedTypeMirror alterntive : aut.getAlternatives()) {
                AnnotationMirror foundAltern = alterntive.getAnnotationInHierarchy(required);
                if (!atypeFactory.getQualifierHierarchy().isSubtype(required, foundAltern)) {
                    checker.report(Result.failure("exception.parameter.invalid", foundAltern, required), node.getParameter());
                }
            }
        }
    }
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotatedUnionType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedUnionType)

Aggregations

AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)188 AnnotationMirror (javax.lang.model.element.AnnotationMirror)42 ExpressionTree (com.sun.source.tree.ExpressionTree)32 AnnotatedDeclaredType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType)27 Tree (com.sun.source.tree.Tree)25 AnnotatedTypeVariable (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)25 VariableTree (com.sun.source.tree.VariableTree)22 ArrayList (java.util.ArrayList)22 AnnotatedExecutableType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType)21 MethodTree (com.sun.source.tree.MethodTree)20 TypeVariable (javax.lang.model.type.TypeVariable)19 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)18 AnnotatedArrayType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType)17 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)16 TypeMirror (javax.lang.model.type.TypeMirror)16 VariableElement (javax.lang.model.element.VariableElement)15 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)13 MemberSelectTree (com.sun.source.tree.MemberSelectTree)13 NewClassTree (com.sun.source.tree.NewClassTree)13 Element (javax.lang.model.element.Element)13