Search in sources :

Example 16 with TreePath

use of com.sun.source.util.TreePath in project checker-framework by typetools.

the class CFAbstractTransfer method addInformationFromPreconditions.

/**
 * Add the information from all the preconditions of the method {@code method} with
 * corresponding tree {@code methodTree} to the store {@code info}.
 */
protected void addInformationFromPreconditions(S info, AnnotatedTypeFactory factory, CFGMethod method, MethodTree methodTree, ExecutableElement methodElement) {
    ContractsUtils contracts = ContractsUtils.getInstance(analysis.atypeFactory);
    FlowExpressionContext flowExprContext = null;
    Set<Precondition> preconditions = contracts.getPreconditions(methodElement);
    for (Precondition p : preconditions) {
        String expression = p.expression;
        AnnotationMirror annotation = p.annotation;
        if (flowExprContext == null) {
            flowExprContext = FlowExpressionContext.buildContextForMethodDeclaration(methodTree, method.getClassTree(), analysis.checker.getContext());
        }
        TreePath localScope = analysis.atypeFactory.getPath(methodTree);
        annotation = standardizeAnnotationFromContract(annotation, flowExprContext, localScope);
        try {
            // TODO: currently, these expressions are parsed at the
            // declaration (i.e. here) and for every use. this could
            // be optimized to store the result the first time.
            // (same for other annotations)
            FlowExpressions.Receiver expr = FlowExpressionParseUtil.parse(expression, flowExprContext, localScope, false);
            info.insertValue(expr, annotation);
        } catch (FlowExpressionParseException e) {
        // Errors are reported by BaseTypeVisitor.checkContractsAtMethodDeclaration()
        }
    }
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) TreePath(com.sun.source.util.TreePath) FlowExpressionContext(org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext) Precondition(org.checkerframework.framework.util.ContractsUtils.Precondition) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) FlowExpressionParseException(org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionParseException) ContractsUtils(org.checkerframework.framework.util.ContractsUtils) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)

Example 17 with TreePath

use of com.sun.source.util.TreePath in project checker-framework by typetools.

the class CFAbstractTransfer method initialStore.

/**
 * The initial store maps method formal parameters to their currently most refined type.
 */
@Override
public S initialStore(UnderlyingAST underlyingAST, @Nullable List<LocalVariableNode> parameters) {
    if (fixedInitialStore != null && underlyingAST.getKind() != Kind.LAMBDA && underlyingAST.getKind() != Kind.METHOD) {
        return fixedInitialStore;
    }
    S info = analysis.createEmptyStore(sequentialSemantics);
    if (underlyingAST.getKind() == Kind.METHOD) {
        if (fixedInitialStore != null) {
            // copy knowledge
            info = analysis.createCopiedStore(fixedInitialStore);
        }
        AnnotatedTypeFactory factory = analysis.getTypeFactory();
        for (LocalVariableNode p : parameters) {
            AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
            info.initializeMethodParameter(p, analysis.createAbstractValue(anno));
        }
        // add properties known through precondition
        CFGMethod method = (CFGMethod) underlyingAST;
        MethodTree methodTree = method.getMethod();
        ExecutableElement methodElem = TreeUtils.elementFromDeclaration(methodTree);
        addInformationFromPreconditions(info, factory, method, methodTree, methodElem);
        final ClassTree classTree = method.getClassTree();
        addFieldValues(info, factory, classTree, methodTree);
        addFinalLocalValues(info, methodElem);
        if (shouldPerformWholeProgramInference(methodTree, methodElem)) {
            Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods = AnnotatedTypes.overriddenMethods(analysis.atypeFactory.getElementUtils(), analysis.atypeFactory, methodElem);
            for (Map.Entry<AnnotatedDeclaredType, ExecutableElement> pair : overriddenMethods.entrySet()) {
                AnnotatedExecutableType overriddenMethod = AnnotatedTypes.asMemberOf(analysis.atypeFactory.getProcessingEnv().getTypeUtils(), analysis.atypeFactory, pair.getKey(), pair.getValue());
                // Infers parameter and receiver types of the method based
                // on the overridden method.
                analysis.atypeFactory.getWholeProgramInference().updateInferredMethodParameterTypes(methodTree, methodElem, overriddenMethod, analysis.getTypeFactory());
                analysis.atypeFactory.getWholeProgramInference().updateInferredMethodReceiverType(methodTree, methodElem, overriddenMethod, analysis.getTypeFactory());
            }
        }
        return info;
    } else if (underlyingAST.getKind() == Kind.LAMBDA) {
        // Create a copy and keep only the field values (nothing else applies).
        info = analysis.createCopiedStore(fixedInitialStore);
        info.localVariableValues.clear();
        info.classValues.clear();
        info.arrayValues.clear();
        info.methodValues.clear();
        AnnotatedTypeFactory factory = analysis.getTypeFactory();
        for (LocalVariableNode p : parameters) {
            AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
            info.initializeMethodParameter(p, analysis.createAbstractValue(anno));
        }
        CFGLambda lambda = (CFGLambda) underlyingAST;
        Tree enclosingTree = TreeUtils.enclosingOfKind(factory.getPath(lambda.getLambdaTree()), new HashSet<>(Arrays.asList(Tree.Kind.METHOD, // Tree.Kind for which TreeUtils.isClassTree is true
        Tree.Kind.CLASS, Tree.Kind.INTERFACE, Tree.Kind.ANNOTATION_TYPE, Tree.Kind.ENUM)));
        Element enclosingElement = null;
        if (enclosingTree.getKind() == Tree.Kind.METHOD) {
            // If it is in an initializer, we need to use locals from the initializer.
            enclosingElement = TreeUtils.elementFromTree(enclosingTree);
        } else if (TreeUtils.isClassTree(enclosingTree)) {
            // Try to find an enclosing initializer block
            // Would love to know if there was a better way
            // Find any enclosing element of the lambda (using trees)
            // Then go up the elements to find an initializer element (which can't be found with
            // the tree).
            TreePath loopTree = factory.getPath(lambda.getLambdaTree()).getParentPath();
            Element anEnclosingElement = null;
            while (loopTree.getLeaf() != enclosingTree) {
                Element sym = TreeUtils.elementFromTree(loopTree.getLeaf());
                if (sym != null) {
                    anEnclosingElement = sym;
                    break;
                }
                loopTree = loopTree.getParentPath();
            }
            while (anEnclosingElement != null && !anEnclosingElement.equals(TreeUtils.elementFromTree(enclosingTree))) {
                if (anEnclosingElement.getKind() == ElementKind.INSTANCE_INIT || anEnclosingElement.getKind() == ElementKind.STATIC_INIT) {
                    enclosingElement = anEnclosingElement;
                    break;
                }
                anEnclosingElement = anEnclosingElement.getEnclosingElement();
            }
        }
        if (enclosingElement != null) {
            addFinalLocalValues(info, enclosingElement);
        }
        // We want the initialization stuff, but need to throw out any refinements.
        Map<FieldAccess, V> fieldValuesClone = new HashMap<>(info.fieldValues);
        for (Entry<FieldAccess, V> fieldValue : fieldValuesClone.entrySet()) {
            AnnotatedTypeMirror declaredType = factory.getAnnotatedType(fieldValue.getKey().getField());
            V lubbedValue = analysis.createAbstractValue(declaredType).leastUpperBound(fieldValue.getValue());
            info.fieldValues.put(fieldValue.getKey(), lubbedValue);
        }
    }
    return info;
}
Also used : CFGMethod(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod) MethodTree(com.sun.source.tree.MethodTree) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ClassTree(com.sun.source.tree.ClassTree) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) Entry(java.util.Map.Entry) TreePath(com.sun.source.util.TreePath) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) GenericAnnotatedTypeFactory(org.checkerframework.framework.type.GenericAnnotatedTypeFactory) AnnotatedTypeFactory(org.checkerframework.framework.type.AnnotatedTypeFactory) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) CFGLambda(org.checkerframework.dataflow.cfg.UnderlyingAST.CFGLambda) Map(java.util.Map) HashMap(java.util.HashMap) HashSet(java.util.HashSet)

Example 18 with TreePath

use of com.sun.source.util.TreePath in project checker-framework by typetools.

the class SourceChecker method shouldSuppressWarnings.

/**
 * Determines whether all the warnings pertaining to a given tree should be suppressed. Returns
 * true if the tree is within the scope of a @SuppressWarnings annotation, one of whose values
 * suppresses the checker's warnings. The list of keys that suppress a checker's warnings is
 * provided by the {@link SourceChecker#getSuppressWarningsKeys} method.
 *
 * @param tree the tree that might be a source of a warning
 * @param errKey the error key the checker is emitting
 * @return true if no warning should be emitted for the given tree because it is contained by a
 *     declaration with an appropriately-valued {@literal @}SuppressWarnings annotation; false
 *     otherwise
 */
// Public so it can be called from a few places in
// org.checkerframework.framework.flow.CFAbstractTransfer
public boolean shouldSuppressWarnings(Tree tree, String errKey) {
    // Don't suppress warnings if this checker provides no key to do so.
    Collection<String> checkerKeys = this.getSuppressWarningsKeys();
    if (checkerKeys.isEmpty()) {
        return false;
    }
    // trees.getPath might be slow, but this is only used in error reporting
    // TODO: #1586 this might return null within a cloned finally block and
    // then a warning that should be suppressed isn't. Fix this when fixing #1586.
    @Nullable TreePath path = trees.getPath(this.currentRoot, tree);
    if (path == null) {
        return false;
    }
    @Nullable VariableTree var = TreeUtils.enclosingVariable(path);
    if (var != null && shouldSuppressWarnings(TreeUtils.elementFromTree(var), errKey)) {
        return true;
    }
    @Nullable MethodTree method = TreeUtils.enclosingMethod(path);
    if (method != null) {
        @Nullable Element elt = TreeUtils.elementFromTree(method);
        if (shouldSuppressWarnings(elt, errKey)) {
            return true;
        }
        if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
            // @AnnotatedFor.
            return false;
        }
    }
    @Nullable ClassTree cls = TreeUtils.enclosingClass(path);
    if (cls != null) {
        @Nullable Element elt = TreeUtils.elementFromTree(cls);
        if (shouldSuppressWarnings(elt, errKey)) {
            return true;
        }
        if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
            // @AnnotatedFor.
            return false;
        }
    }
    if (useUncheckedCodeDefault("source")) {
        // false, we DO suppress the warning.
        return true;
    }
    return false;
}
Also used : TreePath(com.sun.source.util.TreePath) MethodTree(com.sun.source.tree.MethodTree) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableTree(com.sun.source.tree.VariableTree) ClassTree(com.sun.source.tree.ClassTree) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 19 with TreePath

use of com.sun.source.util.TreePath in project checker-framework by typetools.

the class QualifierDefaults method getTypeVarBoundType.

/**
 * @return the boundType (UPPER or UNBOUNDED) of the declaration of typeParamElem
 */
// Results are cached in {@link elementToBoundType}.
private static BoundType getTypeVarBoundType(final TypeParameterElement typeParamElem, final AnnotatedTypeFactory typeFactory) {
    final BoundType prev = elementToBoundType.get(typeParamElem);
    if (prev != null) {
        return prev;
    }
    TreePath declaredTypeVarEle = typeFactory.getTreeUtils().getPath(typeParamElem);
    Tree typeParamDecl = declaredTypeVarEle == null ? null : declaredTypeVarEle.getLeaf();
    final BoundType boundType;
    if (typeParamDecl == null) {
        // when the compilation unit is no-longer available.
        if (typeParamElem.getBounds().size() == 1 && TypesUtils.isObject(typeParamElem.getBounds().get(0))) {
            // If the bound was Object, then it may or may not have been explicitly written.
            // Assume that it was not.
            boundType = BoundType.UNBOUNDED;
        } else {
            // The bound is not Object, so it must have been explicitly written and thus the
            // type variable has an upper bound.
            boundType = BoundType.UPPER;
        }
    } else {
        if (typeParamDecl.getKind() == Tree.Kind.TYPE_PARAMETER) {
            final TypeParameterTree tptree = (TypeParameterTree) typeParamDecl;
            List<? extends Tree> bnds = tptree.getBounds();
            if (bnds != null && !bnds.isEmpty()) {
                boundType = BoundType.UPPER;
            } else {
                boundType = BoundType.UNBOUNDED;
            }
        } else {
            ErrorReporter.errorAbort("Unexpected tree type for typeVar Element:\n" + "typeParamElem=" + typeParamElem + "\n" + typeParamDecl);
            // dead code
            boundType = null;
        }
    }
    elementToBoundType.put(typeParamElem, boundType);
    return boundType;
}
Also used : TypeParameterTree(com.sun.source.tree.TypeParameterTree) TreePath(com.sun.source.util.TreePath) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) TypeParameterTree(com.sun.source.tree.TypeParameterTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) ExpressionTree(com.sun.source.tree.ExpressionTree)

Example 20 with TreePath

use of com.sun.source.util.TreePath in project checker-framework by typetools.

the class DefaultTypeArgumentInference method inferTypeArgs.

@Override
public Map<TypeVariable, AnnotatedTypeMirror> inferTypeArgs(AnnotatedTypeFactory typeFactory, ExpressionTree expressionTree, ExecutableElement methodElem, AnnotatedExecutableType methodType) {
    final List<AnnotatedTypeMirror> argTypes = TypeArgInferenceUtil.getArgumentTypes(expressionTree, typeFactory);
    final TreePath pathToExpression = typeFactory.getPath(expressionTree);
    assert pathToExpression != null;
    final AnnotatedTypeMirror assignedTo = TypeArgInferenceUtil.assignedTo(typeFactory, pathToExpression);
    SourceChecker checker = typeFactory.getContext().getChecker();
    if (showInferenceSteps) {
        checker.message(Kind.NOTE, "DTAI: expression: %s\n  argTypes: %s\n  assignedTo: %s\n", expressionTree.toString().replace("\n", " "), argTypes, assignedTo);
    }
    final Set<TypeVariable> targets = TypeArgInferenceUtil.methodTypeToTargets(methodType);
    if (assignedTo == null && TreeUtils.getAssignmentContext(pathToExpression) != null) {
        // If the type of the assignment context isn't found, but the expression is assigned,
        // then don't attempt to infere type arguments, because the Java type inferred will be
        // incorrect.  The assignment type is null when it includes uninferred type arguments.
        // For example:
        // <T> T outMethod()
        // <U> void inMethod(U u);
        // inMethod(outMethod())
        // would require solving the constraints for both type argument inferences
        // simultaneously
        Map<TypeVariable, AnnotatedTypeMirror> inferredArgs = new LinkedHashMap<>();
        handleUninferredTypeVariables(typeFactory, methodType, targets, inferredArgs);
        return inferredArgs;
    }
    Map<TypeVariable, AnnotatedTypeMirror> inferredArgs;
    try {
        inferredArgs = infer(typeFactory, argTypes, assignedTo, methodElem, methodType, targets, true);
        if (showInferenceSteps) {
            checker.message(Kind.NOTE, "  after infer: %s\n", inferredArgs);
        }
        handleNullTypeArguments(typeFactory, methodElem, methodType, argTypes, assignedTo, targets, inferredArgs);
        if (showInferenceSteps) {
            checker.message(Kind.NOTE, "  after handleNull: %s\n", inferredArgs);
        }
    } catch (Exception ex) {
        // Catch any errors thrown by inference.
        inferredArgs = new LinkedHashMap<>();
        if (showInferenceSteps) {
            checker.message(Kind.NOTE, "  exception: %s\n", ex.getLocalizedMessage());
        }
    }
    handleUninferredTypeVariables(typeFactory, methodType, targets, inferredArgs);
    if (showInferenceSteps) {
        checker.message(Kind.NOTE, "  results: %s\n", inferredArgs);
    }
    return inferredArgs;
}
Also used : TreePath(com.sun.source.util.TreePath) TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) SourceChecker(org.checkerframework.framework.source.SourceChecker) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) LinkedHashMap(java.util.LinkedHashMap)

Aggregations

TreePath (com.sun.source.util.TreePath)151 ExpressionTree (com.sun.source.tree.ExpressionTree)60 Tree (com.sun.source.tree.Tree)60 VariableTree (com.sun.source.tree.VariableTree)50 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)46 MethodTree (com.sun.source.tree.MethodTree)46 ClassTree (com.sun.source.tree.ClassTree)45 MemberSelectTree (com.sun.source.tree.MemberSelectTree)39 IdentifierTree (com.sun.source.tree.IdentifierTree)37 BlockTree (com.sun.source.tree.BlockTree)36 NewClassTree (com.sun.source.tree.NewClassTree)32 StatementTree (com.sun.source.tree.StatementTree)32 JCTree (com.sun.tools.javac.tree.JCTree)31 AssignmentTree (com.sun.source.tree.AssignmentTree)27 BinaryTree (com.sun.source.tree.BinaryTree)27 TypeCastTree (com.sun.source.tree.TypeCastTree)26 ExpressionStatementTree (com.sun.source.tree.ExpressionStatementTree)25 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)25 LiteralTree (com.sun.source.tree.LiteralTree)25 CompoundAssignmentTree (com.sun.source.tree.CompoundAssignmentTree)23