Search in sources :

Example 1 with AnnotatedDeclaredType

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

the class WholeProgramInferenceScenes method updateInferredMethodReceiverType.

/**
 * Updates the receiver type of the method {@code methodElt} in the Scene of the method's
 * enclosing class based on the overridden method {@code overriddenMethod} receiver type.
 *
 * <p>For the receiver in methodElt:
 *
 * <ul>
 *   <li>If the Scene does not contain an annotated type for the receiver, then the type of the
 *       receiver on the overridden method will be added to the receiver in the Scene.
 *   <li>If the Scene previously contained an annotated type for the receiver, then its new type
 *       will be the LUB between the previous type and the type of the receiver on the
 *       overridden method.
 * </ul>
 *
 * <p>
 *
 * @param methodTree the tree of the method that contains the receiver
 * @param methodElt the element of the method
 * @param overriddenMethod the overridden method
 * @param atf the annotated type factory of a given type system, whose type hierarchy will be
 *     used to update the receiver type
 */
@Override
public void updateInferredMethodReceiverType(MethodTree methodTree, ExecutableElement methodElt, AnnotatedExecutableType overriddenMethod, AnnotatedTypeFactory atf) {
    ClassSymbol classSymbol = getEnclosingClassSymbol(methodTree);
    String className = classSymbol.flatname.toString();
    String jaifPath = helper.getJaifPath(className);
    AClass clazz = helper.getAClass(className, jaifPath);
    String methodName = JVMNames.getJVMMethodName(methodElt);
    AMethod method = clazz.methods.vivify(methodName);
    AnnotatedDeclaredType argADT = overriddenMethod.getReceiverType();
    if (argADT != null) {
        AnnotatedTypeMirror paramATM = atf.getAnnotatedType(methodTree).getReceiverType();
        if (paramATM != null) {
            AField receiver = method.receiver;
            helper.updateAnnotationSetInScene(receiver.type, atf, jaifPath, argADT, paramATM, TypeUseLocation.RECEIVER);
        }
    }
}
Also used : ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) AClass(scenelib.annotations.el.AClass) AMethod(scenelib.annotations.el.AMethod) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AField(scenelib.annotations.el.AField)

Example 2 with AnnotatedDeclaredType

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

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

the class StubParser method processEnum.

/**
 * Gathers and returns a list of AnnotatedTypeVariable of the enum's type parameter
 * declarations.
 *
 * @param decl actual enum declaration
 * @param elt element representing enum
 * @param atypes map of annotated types
 * @param declAnnos map of declarations annotations
 * @return list of AnnotatedTypeVariable of the enum's type parameter declarations
 */
private List<AnnotatedTypeVariable> processEnum(EnumDeclaration decl, TypeElement elt) {
    annotateDecl(declAnnos, elt, decl.getAnnotations());
    AnnotatedDeclaredType type = atypeFactory.fromElement(elt);
    annotate(type, decl.getAnnotations());
    putNew(atypes, elt, type);
    List<AnnotatedTypeVariable> typeVariables = new ArrayList<>();
    for (AnnotatedTypeMirror typeV : type.getTypeArguments()) {
        if (typeV.getKind() != TypeKind.TYPEVAR) {
            stubWarn("expected an AnnotatedTypeVariable but found type kind " + typeV.getKind() + ": " + typeV);
        } else {
            typeVariables.add((AnnotatedTypeVariable) typeV);
        }
    }
    return typeVariables;
}
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 4 with AnnotatedDeclaredType

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

the class ElementAnnotationUtil method getLocationTypeADT.

/**
 * Given a TypePath into a declared type, return the component type that is located at the end
 * of the TypePath
 *
 * @param type a type containing the type specified by location
 * @param location a type path into type
 * @return the type specified by location
 */
private static AnnotatedTypeMirror getLocationTypeADT(AnnotatedDeclaredType type, List<TypeAnnotationPosition.TypePathEntry> location) {
    // List order by outer most type to inner most type.
    ArrayDeque<AnnotatedDeclaredType> outerToInner = new ArrayDeque<>();
    AnnotatedDeclaredType enclosing = type;
    while (enclosing != null) {
        outerToInner.addFirst(enclosing);
        enclosing = enclosing.getEnclosingType();
    }
    // Create a linked list of the location, so removing the first element is easier.
    // Also, the `tail` operation wouldn't work with a Deque.
    @SuppressWarnings("JdkObsolete") LinkedList<TypePathEntry> tailOfLocations = new LinkedList<>(location);
    boolean error = false;
    while (!tailOfLocations.isEmpty()) {
        TypePathEntry currentLocation = tailOfLocations.removeFirst();
        switch(currentLocation.tag) {
            case INNER_TYPE:
                outerToInner.removeFirst();
                break;
            case TYPE_ARGUMENT:
                AnnotatedDeclaredType innerType = outerToInner.getFirst();
                if (currentLocation.arg < innerType.getTypeArguments().size()) {
                    AnnotatedTypeMirror typeArg = innerType.getTypeArguments().get(currentLocation.arg);
                    return getTypeAtLocation(typeArg, tailOfLocations);
                } else {
                    error = true;
                    break;
                }
            default:
                error = true;
        }
        if (error) {
            break;
        }
    }
    if (outerToInner.isEmpty() || error) {
        ErrorReporter.errorAbort("ElementAnnotationUtil.getLocationTypeADT: invalid location %s for type: %s", location, type);
    }
    return outerToInner.getFirst();
}
Also used : AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) ArrayDeque(java.util.ArrayDeque) LinkedList(java.util.LinkedList) TypePathEntry(com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry)

Example 5 with AnnotatedDeclaredType

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

the class AnnotatedTypeFactory method adaptGetClassReturnTypeToReceiver.

/**
 * Java special-cases the return type of {@link java.lang.Class#getClass() getClass()}. Though
 * the method has a return type of {@code Class<?>}, the compiler special cases this return-type
 * and changes the bound of the type argument to the erasure of the receiver type. For example:
 *
 * <ul>
 *   <li>{@code x.getClass()} has the type {@code Class< ? extends erasure_of_x >}
 *   <li>{@code someInteger.getClass()} has the type {@code Class< ? extends Integer >}
 * </ul>
 *
 * @param getClassType this must be a type representing a call to Object.getClass otherwise a
 *     runtime exception will be thrown. It is modified by side effect.
 * @param receiverType the receiver type of the method invocation (not the declared receiver
 *     type)
 */
protected void adaptGetClassReturnTypeToReceiver(final AnnotatedExecutableType getClassType, final AnnotatedTypeMirror receiverType) {
    // TODO: should the receiver type ever be a declaration??
    // Work on removing the asUse() call.
    final AnnotatedTypeMirror newBound = receiverType.getErased().asUse();
    final AnnotatedTypeMirror returnType = getClassType.getReturnType();
    if (returnType == null || !(returnType.getKind() == TypeKind.DECLARED) || ((AnnotatedDeclaredType) returnType).getTypeArguments().size() != 1) {
        ErrorReporter.errorAbort("Unexpected type passed to AnnotatedTypes.adaptGetClassReturnTypeToReceiver\n" + "getClassType=" + getClassType + "\n" + "receiverType=" + receiverType);
    }
    final AnnotatedDeclaredType returnAdt = (AnnotatedDeclaredType) getClassType.getReturnType();
    final List<AnnotatedTypeMirror> typeArgs = returnAdt.getTypeArguments();
    // Usually, the only locations that will add annotations to the return type are getClass in
    // stub files defaults and propagation tree annotator.  Since getClass is final they cannot
    // come from source code.  Also, since the newBound is an erased type we have no type
    // arguments.  So, we just copy the annotations from the bound of the declared type to the
    // new bound.
    final AnnotatedWildcardType classWildcardArg = (AnnotatedWildcardType) typeArgs.get(0);
    newBound.replaceAnnotations(classWildcardArg.getExtendsBound().getAnnotations());
    classWildcardArg.setExtendsBound(newBound);
}
Also used : AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) AnnotatedWildcardType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType)

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