Search in sources :

Example 1 with AnnotatedExecutableType

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType 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 2 with AnnotatedExecutableType

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

the class AnnotatedTypeFactory method methodFromUse.

public Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> methodFromUse(ExpressionTree tree, ExecutableElement methodElt, AnnotatedTypeMirror receiverType) {
    AnnotatedExecutableType methodType = AnnotatedTypes.asMemberOf(types, this, receiverType, methodElt);
    List<AnnotatedTypeMirror> typeargs = new ArrayList<>(methodType.getTypeVariables().size());
    Map<TypeVariable, AnnotatedTypeMirror> typeVarMapping = AnnotatedTypes.findTypeArguments(processingEnv, this, tree, methodElt, methodType);
    if (!typeVarMapping.isEmpty()) {
        for (AnnotatedTypeVariable tv : methodType.getTypeVariables()) {
            if (typeVarMapping.get(tv.getUnderlyingType()) == null) {
                ErrorReporter.errorAbort("AnnotatedTypeFactory.methodFromUse:" + "mismatch between declared method type variables and the inferred method type arguments! " + "Method type variables: " + methodType.getTypeVariables() + "; " + "Inferred method type arguments: " + typeVarMapping);
            }
            typeargs.add(typeVarMapping.get(tv.getUnderlyingType()));
        }
        methodType = (AnnotatedExecutableType) typeVarSubstitutor.substitute(typeVarMapping, methodType);
    }
    if (tree.getKind() == Tree.Kind.METHOD_INVOCATION && TreeUtils.isGetClassInvocation((MethodInvocationTree) tree)) {
        adaptGetClassReturnTypeToReceiver(methodType, receiverType);
    }
    return Pair.of(methodType, typeargs);
}
Also used : AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) ArrayList(java.util.ArrayList) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)

Example 3 with AnnotatedExecutableType

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

the class AnnotatedTypeFactory method getMethodReturnType.

/**
 * Returns the return type of the method {@code m} at the return statement {@code r}.
 */
public AnnotatedTypeMirror getMethodReturnType(MethodTree m, ReturnTree r) {
    AnnotatedExecutableType methodType = getAnnotatedType(m);
    AnnotatedTypeMirror ret = methodType.getReturnType();
    return ret;
}
Also used : AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType)

Example 4 with AnnotatedExecutableType

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

the class AnnotatedTypeFactory method constructorFromUse.

/**
 * Determines the type of the invoked constructor based on the passed new class tree.
 *
 * <p>The returned method type has all type variables resolved, whether based on receiver type,
 * passed type parameters if any, and constructor invocation parameter.
 *
 * <p>Subclasses may override this method to customize inference of types or qualifiers based on
 * constructor invocation parameters.
 *
 * <p>As an implementation detail, this method depends on {@link
 * AnnotatedTypes#asMemberOf(Types, AnnotatedTypeFactory, AnnotatedTypeMirror, Element)}, and
 * customization based on receiver type should be in accordance with its specification.
 *
 * <p>The return type is a pair of the type of the invoked constructor and the (inferred) type
 * arguments. Note that neither the explicitly passed nor the inferred type arguments are
 * guaranteed to be subtypes of the corresponding upper bounds. See method {@link
 * org.checkerframework.common.basetype.BaseTypeVisitor#checkTypeArguments(Tree, List, List,
 * List)} for the checks of type argument well-formedness.
 *
 * <p>Note that "this" and "super" constructor invocations are handled by method {@link
 * #methodFromUse}. This method only handles constructor invocations in a "new" expression.
 *
 * @param tree the constructor invocation tree
 * @return the annotated type of the invoked constructor (as an executable type) and the
 *     (inferred) type arguments
 */
public Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> constructorFromUse(NewClassTree tree) {
    ExecutableElement ctor = TreeUtils.constructor(tree);
    AnnotatedTypeMirror type = fromNewClass(tree);
    addComputedTypeAnnotations(tree.getIdentifier(), type);
    AnnotatedExecutableType con = AnnotatedTypes.asMemberOf(types, this, type, ctor);
    if (tree.getArguments().size() == con.getParameterTypes().size() + 1 && isSyntheticArgument(tree.getArguments().get(0))) {
        // happens for anonymous constructors of inner classes
        List<AnnotatedTypeMirror> actualParams = new ArrayList<>();
        actualParams.add(getAnnotatedType(tree.getArguments().get(0)));
        actualParams.addAll(con.getParameterTypes());
        con.setParameterTypes(actualParams);
    }
    List<AnnotatedTypeMirror> typeargs = new ArrayList<>(con.getTypeVariables().size());
    Map<TypeVariable, AnnotatedTypeMirror> typeVarMapping = AnnotatedTypes.findTypeArguments(processingEnv, this, tree, ctor, con);
    if (!typeVarMapping.isEmpty()) {
        for (AnnotatedTypeVariable tv : con.getTypeVariables()) {
            typeargs.add(typeVarMapping.get(tv.getUnderlyingType()));
        }
        con = (AnnotatedExecutableType) typeVarSubstitutor.substitute(typeVarMapping, con);
    }
    return Pair.of(con, typeargs);
}
Also used : AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)

Example 5 with AnnotatedExecutableType

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

the class AnnotatedTypeFactory method getMethodReturnType.

/**
 * Returns the return type of the method {@code m}.
 */
public AnnotatedTypeMirror getMethodReturnType(MethodTree m) {
    AnnotatedExecutableType methodType = getAnnotatedType(m);
    AnnotatedTypeMirror ret = methodType.getReturnType();
    return ret;
}
Also used : AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType)

Aggregations

AnnotatedExecutableType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType)42 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)19 ExecutableElement (javax.lang.model.element.ExecutableElement)17 ArrayList (java.util.ArrayList)15 AnnotatedDeclaredType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType)15 ExpressionTree (com.sun.source.tree.ExpressionTree)13 MethodTree (com.sun.source.tree.MethodTree)13 List (java.util.List)13 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)12 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)12 Tree (com.sun.source.tree.Tree)12 VariableTree (com.sun.source.tree.VariableTree)12 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)9 AssignmentTree (com.sun.source.tree.AssignmentTree)7 ClassTree (com.sun.source.tree.ClassTree)7 NewArrayTree (com.sun.source.tree.NewArrayTree)7 ReturnTree (com.sun.source.tree.ReturnTree)7 NewClassTree (com.sun.source.tree.NewClassTree)6 VariableElement (javax.lang.model.element.VariableElement)6 AnnotationTree (com.sun.source.tree.AnnotationTree)5