Search in sources :

Example 16 with AnnotatedDeclaredType

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

the class AnnotatedTypes method addTypeVarMappings.

private static void addTypeVarMappings(Types types, AnnotatedTypeFactory atypeFactory, AnnotatedTypeMirror t, TypeElement enclosingClassOfElem, Map<TypeVariable, AnnotatedTypeMirror> mappings) {
    if (enclosingClassOfElem.getTypeParameters().isEmpty()) {
        return;
    }
    AnnotatedDeclaredType enclosingType = atypeFactory.getAnnotatedType(enclosingClassOfElem);
    AnnotatedDeclaredType base = (AnnotatedDeclaredType) asOuterSuper(types, atypeFactory, t, enclosingType);
    final List<AnnotatedTypeVariable> ownerParams = new ArrayList<>(enclosingType.getTypeArguments().size());
    for (final AnnotatedTypeMirror typeParam : enclosingType.getTypeArguments()) {
        if (typeParam.getKind() != TypeKind.TYPEVAR) {
            ErrorReporter.errorAbort("Type arguments of a declaration should be type variables\n" + "enclosingClassOfElem=" + enclosingClassOfElem + "\n" + "enclosingType=" + enclosingType + "\n" + "typeMirror=" + t);
        }
        ownerParams.add((AnnotatedTypeVariable) typeParam);
    }
    List<AnnotatedTypeMirror> baseParams = base.getTypeArguments();
    if (ownerParams.size() != baseParams.size() && !base.wasRaw()) {
        ErrorReporter.errorAbort("Unexpected number of parameters.\n" + "enclosingType=" + enclosingType + "\n" + "baseType=" + base);
    }
    if (!ownerParams.isEmpty() && baseParams.isEmpty() && base.wasRaw()) {
        List<AnnotatedTypeMirror> newBaseParams = new ArrayList<>();
        for (AnnotatedTypeVariable arg : ownerParams) {
            // If base type was raw and the type arguments are missing,
            // set them to the erased type of the type variable.
            // (which is the erased type of the upper bound.)
            newBaseParams.add(arg.getErased());
        }
        baseParams = newBaseParams;
    }
    for (int i = 0; i < ownerParams.size(); ++i) {
        mappings.put(ownerParams.get(i).getUnderlyingType(), baseParams.get(i));
    }
}
Also used : AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) ArrayList(java.util.ArrayList) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 17 with AnnotatedDeclaredType

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

the class AnnotatedTypes method getSuperTypes.

/**
 * Returns all the super types of the given declared type.
 *
 * @param type a declared type
 * @return all the supertypes of the given type
 */
public static Set<AnnotatedDeclaredType> getSuperTypes(AnnotatedDeclaredType type) {
    Set<AnnotatedDeclaredType> supertypes = new LinkedHashSet<>();
    if (type == null) {
        return supertypes;
    }
    // Set up a stack containing the type mirror of subtype, which
    // is our starting point.
    Deque<AnnotatedDeclaredType> stack = new ArrayDeque<>();
    stack.push(type);
    while (!stack.isEmpty()) {
        AnnotatedDeclaredType current = stack.pop();
        // add it to our supertypes set.
        for (AnnotatedDeclaredType supertype : current.directSuperTypes()) {
            if (!supertypes.contains(supertype)) {
                stack.push(supertype);
                supertypes.add(supertype);
            }
        }
    }
    return Collections.unmodifiableSet(supertypes);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) ArrayDeque(java.util.ArrayDeque)

Example 18 with AnnotatedDeclaredType

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

the class AliasingTransfer method processPostconditions.

/**
 * Handling pseudo-assignments. Called by {@code CFAbstractTransfer.visitMethodInvocation()}.
 *
 * <p>Case 2: Given a method call, traverses all formal parameters of the method declaration,
 * and if it doesn't have the {@literal @}NonLeaked or {@literal @}LeakedToResult annotations,
 * we remove the node of the respective argument in the method call from the store. If parameter
 * has {@literal @}LeakedToResult, {@code visitMethodInvocation()} handles it.
 */
@Override
protected void processPostconditions(MethodInvocationNode n, CFStore store, ExecutableElement methodElement, Tree tree) {
    super.processPostconditions(n, store, methodElement, tree);
    if (TreeUtils.isEnumSuper(n.getTree())) {
        // Skipping the init() method for enums.
        return;
    }
    List<Node> args = n.getArguments();
    List<? extends VariableElement> params = methodElement.getParameters();
    assert (args.size() == params.size()) : "Number of arguments in " + "the method call " + n.toString() + " is different from the" + " number of parameters for the method declaration: " + methodElement.getSimpleName().toString();
    AnnotatedExecutableType annotatedType = factory.getAnnotatedType(methodElement);
    List<AnnotatedTypeMirror> paramTypes = annotatedType.getParameterTypes();
    for (int i = 0; i < args.size(); i++) {
        Node arg = args.get(i);
        AnnotatedTypeMirror paramType = paramTypes.get(i);
        if (!paramType.hasAnnotation(NonLeaked.class) && !paramType.hasAnnotation(LeakedToResult.class)) {
            store.clearValue(FlowExpressions.internalReprOf(factory, arg));
        }
    }
    // Now, doing the same as above for the receiver parameter
    Node receiver = n.getTarget().getReceiver();
    AnnotatedDeclaredType receiverType = annotatedType.getReceiverType();
    if (receiverType != null && !receiverType.hasAnnotation(LeakedToResult.class) && !receiverType.hasAnnotation(NonLeaked.class)) {
        store.clearValue(FlowExpressions.internalReprOf(factory, receiver));
    }
}
Also used : AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) Node(org.checkerframework.dataflow.cfg.node.Node) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) LeakedToResult(org.checkerframework.common.aliasing.qual.LeakedToResult) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 19 with AnnotatedDeclaredType

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

the class BaseTypeValidator method visitDeclared.

@Override
public Void visitDeclared(AnnotatedDeclaredType type, Tree tree) {
    if (visitedNodes.containsKey(type)) {
        return visitedNodes.get(type);
    }
    final boolean skipChecks = checker.shouldSkipUses(type.getUnderlyingType().asElement());
    if (!skipChecks) {
        // Ensure that type use is a subtype of the element type
        // isValidUse determines the erasure of the types.
        AnnotatedDeclaredType elemType = (AnnotatedDeclaredType) atypeFactory.getAnnotatedType(type.getUnderlyingType().asElement());
        if (!visitor.isValidUse(elemType, type, tree)) {
            reportInvalidAnnotationsOnUse(type, tree);
        }
    }
    /*
         * Try to reconstruct the ParameterizedTypeTree from the given tree.
         * TODO: there has to be a nicer way to do this...
         */
    Pair<ParameterizedTypeTree, AnnotatedDeclaredType> p = extractParameterizedTypeTree(tree, type);
    ParameterizedTypeTree typeArgTree = p.first;
    type = p.second;
    if (typeArgTree == null) {
        return super.visitDeclared(type, tree);
    }
    // else
    // We put this here because we don't want to put it in visitedNodes before calling
    // super (in the else branch) because that would cause the super implementation
    // to detect that we've already visited type and to immediately return
    visitedNodes.put(type, null);
    // We have a ParameterizedTypeTree -> visit it.
    visitParameterizedType(type, typeArgTree);
    /*
         * Instead of calling super with the unchanged "tree", adapt the
         * second argument to be the corresponding type argument tree. This
         * ensures that the first and second parameter to this method always
         * correspond. visitDeclared is the only method that had this
         * problem.
         */
    List<? extends AnnotatedTypeMirror> tatypes = type.getTypeArguments();
    if (tatypes == null) {
        return null;
    }
    // May be zero for a "diamond" (inferred type args in constructor
    // invocation).
    int numTypeArgs = typeArgTree.getTypeArguments().size();
    if (numTypeArgs != 0) {
        // but I didn't manage to reduce it to a test case.
        assert tatypes.size() <= numTypeArgs || skipChecks : "size mismatch for type arguments: " + type + " and " + typeArgTree;
        for (int i = 0; i < tatypes.size(); ++i) {
            scan(tatypes.get(i), typeArgTree.getTypeArguments().get(i));
        }
    }
    return null;
}
Also used : ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType)

Example 20 with AnnotatedDeclaredType

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

the class BaseTypeVisitor method visitMethod.

/**
 * Performs pseudo-assignment check: checks that the method obeys override and subtype rules to
 * all overridden methods.
 *
 * <p>The override rule specifies that a method, m1, may override a method m2 only if:
 *
 * <ul>
 *   <li>m1 return type is a subtype of m2
 *   <li>m1 receiver type is a supertype of m2
 *   <li>m1 parameters are supertypes of corresponding m2 parameters
 * </ul>
 *
 * Also, it issues a "missing.this" error for static method annotated receivers.
 */
@Override
public Void visitMethod(MethodTree node, Void p) {
    // We copy the result from getAnnotatedType to ensure that
    // circular types (e.g. K extends Comparable<K>) are represented
    // by circular AnnotatedTypeMirrors, which avoids problems with
    // later checks.
    // TODO: Find a cleaner way to ensure circular AnnotatedTypeMirrors.
    AnnotatedExecutableType methodType = atypeFactory.getAnnotatedType(node).deepCopy();
    AnnotatedDeclaredType preMRT = visitorState.getMethodReceiver();
    MethodTree preMT = visitorState.getMethodTree();
    visitorState.setMethodReceiver(methodType.getReceiverType());
    visitorState.setMethodTree(node);
    ExecutableElement methodElement = TreeUtils.elementFromDeclaration(node);
    try {
        if (TreeUtils.isAnonymousConstructor(node)) {
            // We shouldn't dig deeper
            return null;
        }
        // check method purity if needed
        {
            boolean anyPurityAnnotation = PurityUtils.hasPurityAnnotation(atypeFactory, node);
            boolean checkPurityAlways = checker.hasOption("suggestPureMethods");
            boolean checkPurityAnnotations = checker.hasOption("checkPurityAnnotations");
            if (checkPurityAnnotations && (anyPurityAnnotation || checkPurityAlways)) {
                // check "no" purity
                List<Pure.Kind> kinds = PurityUtils.getPurityKinds(atypeFactory, node);
                // @Deterministic makes no sense for a void method or constructor
                boolean isDeterministic = kinds.contains(Pure.Kind.DETERMINISTIC);
                if (isDeterministic) {
                    if (TreeUtils.isConstructor(node)) {
                        checker.report(Result.warning("purity.deterministic.constructor"), node);
                    } else if (TreeUtils.typeOf(node.getReturnType()).getKind() == TypeKind.VOID) {
                        checker.report(Result.warning("purity.deterministic.void.method"), node);
                    }
                }
                // Report errors if necessary.
                PurityResult r = PurityChecker.checkPurity(atypeFactory.getPath(node.getBody()), atypeFactory, checker.hasOption("assumeSideEffectFree"));
                if (!r.isPure(kinds)) {
                    reportPurityErrors(r, node, kinds);
                }
                // as such (if the feature is activated).
                if (checkPurityAlways) {
                    Collection<Pure.Kind> additionalKinds = new HashSet<>(r.getTypes());
                    additionalKinds.removeAll(kinds);
                    if (TreeUtils.isConstructor(node)) {
                        additionalKinds.remove(Pure.Kind.DETERMINISTIC);
                    }
                    if (!additionalKinds.isEmpty()) {
                        if (additionalKinds.size() == 2) {
                            checker.report(Result.warning("purity.more.pure", node.getName()), node);
                        } else if (additionalKinds.contains(Pure.Kind.SIDE_EFFECT_FREE)) {
                            checker.report(Result.warning("purity.more.sideeffectfree", node.getName()), node);
                        } else if (additionalKinds.contains(Pure.Kind.DETERMINISTIC)) {
                            checker.report(Result.warning("purity.more.deterministic", node.getName()), node);
                        } else {
                            assert false : "BaseTypeVisitor reached undesirable state";
                        }
                    }
                }
            }
        }
        // Passing the whole method/constructor validates the return type
        validateTypeOf(node);
        // Validate types in throws clauses
        for (ExpressionTree thr : node.getThrows()) {
            validateTypeOf(thr);
        }
        if (atypeFactory.getDependentTypesHelper() != null) {
            atypeFactory.getDependentTypesHelper().checkMethod(node, methodType);
        }
        AnnotatedDeclaredType enclosingType = (AnnotatedDeclaredType) atypeFactory.getAnnotatedType(methodElement.getEnclosingElement());
        // Find which method this overrides!
        Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods = AnnotatedTypes.overriddenMethods(elements, atypeFactory, methodElement);
        for (Map.Entry<AnnotatedDeclaredType, ExecutableElement> pair : overriddenMethods.entrySet()) {
            AnnotatedDeclaredType overriddenType = pair.getKey();
            AnnotatedExecutableType overriddenMethod = AnnotatedTypes.asMemberOf(types, atypeFactory, overriddenType, pair.getValue());
            if (!checkOverride(node, enclosingType, overriddenMethod, overriddenType)) {
                // the same method, not adding any value. See Issue 373.
                break;
            }
        }
        return super.visitMethod(node, p);
    } finally {
        boolean abstractMethod = methodElement.getModifiers().contains(Modifier.ABSTRACT) || methodElement.getModifiers().contains(Modifier.NATIVE);
        // check well-formedness of pre/postcondition
        List<String> formalParamNames = new ArrayList<>();
        for (VariableTree param : node.getParameters()) {
            formalParamNames.add(param.getName().toString());
        }
        checkContractsAtMethodDeclaration(node, methodElement, formalParamNames, abstractMethod);
        visitorState.setMethodReceiver(preMRT);
        visitorState.setMethodTree(preMT);
    }
}
Also used : PurityResult(org.checkerframework.dataflow.util.PurityChecker.PurityResult) MethodTree(com.sun.source.tree.MethodTree) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) VariableTree(com.sun.source.tree.VariableTree) AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) Collection(java.util.Collection) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) ArrayList(java.util.ArrayList) List(java.util.List) Map(java.util.Map) HashMap(java.util.HashMap) Pure(org.checkerframework.dataflow.qual.Pure)

Aggregations

AnnotatedDeclaredType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType)72 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)26 ArrayList (java.util.ArrayList)19 ExpressionTree (com.sun.source.tree.ExpressionTree)18 AnnotatedExecutableType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType)18 MethodTree (com.sun.source.tree.MethodTree)17 Tree (com.sun.source.tree.Tree)16 ClassTree (com.sun.source.tree.ClassTree)14 VariableTree (com.sun.source.tree.VariableTree)14 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)13 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)12 NewClassTree (com.sun.source.tree.NewClassTree)12 ExecutableElement (javax.lang.model.element.ExecutableElement)11 IdentifierTree (com.sun.source.tree.IdentifierTree)10 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)10 NewArrayTree (com.sun.source.tree.NewArrayTree)9 ReturnTree (com.sun.source.tree.ReturnTree)9 AnnotatedTypeVariable (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)9 AnnotatedWildcardType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType)9 AssignmentTree (com.sun.source.tree.AssignmentTree)8