Search in sources :

Example 11 with VariableTree

use of com.sun.source.tree.VariableTree in project checker-framework by typetools.

the class CFAbstractTransfer method addFieldValues.

private void addFieldValues(S info, AnnotatedTypeFactory factory, ClassTree classTree, MethodTree methodTree) {
    // Add knowledge about final fields, or values of non-final fields
    // if we are inside a constructor (information about initializers)
    TypeMirror classType = TreeUtils.typeOf(classTree);
    List<Pair<VariableElement, V>> fieldValues = analysis.getFieldValues();
    for (Pair<VariableElement, V> p : fieldValues) {
        VariableElement element = p.first;
        V value = p.second;
        if (ElementUtils.isFinal(element) || TreeUtils.isConstructor(methodTree)) {
            Receiver receiver;
            if (ElementUtils.isStatic(element)) {
                receiver = new ClassName(classType);
            } else {
                receiver = new ThisReference(classType);
            }
            TypeMirror fieldType = ElementUtils.getType(element);
            Receiver field = new FieldAccess(receiver, fieldType, element);
            info.insertValue(field, value);
        }
    }
    // add properties about fields (static information from type)
    boolean isNotFullyInitializedReceiver = isNotFullyInitializedReceiver(methodTree);
    if (isNotFullyInitializedReceiver && !TreeUtils.isConstructor(methodTree)) {
        // and the method isn't a constructor
        return;
    }
    for (Tree member : classTree.getMembers()) {
        if (member instanceof VariableTree) {
            VariableTree vt = (VariableTree) member;
            final VariableElement element = TreeUtils.elementFromDeclaration(vt);
            AnnotatedTypeMirror type = ((GenericAnnotatedTypeFactory<?, ?, ?, ?>) factory).getAnnotatedTypeLhs(vt);
            TypeMirror fieldType = ElementUtils.getType(element);
            Receiver receiver;
            if (ElementUtils.isStatic(element)) {
                receiver = new ClassName(classType);
            } else {
                receiver = new ThisReference(classType);
            }
            V value = analysis.createAbstractValue(type);
            if (value == null)
                continue;
            if (TreeUtils.isConstructor(methodTree)) {
                // if we are in a constructor,
                // then we can still use the static type, but only
                // if there is also an initializer that already does
                // some initialization.
                boolean found = false;
                for (Pair<VariableElement, V> fieldValue : fieldValues) {
                    if (fieldValue.first.equals(element)) {
                        value = value.leastUpperBound(fieldValue.second);
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    // no initializer found, cannot use static type
                    continue;
                }
            }
            Receiver field = new FieldAccess(receiver, fieldType, element);
            info.insertValue(field, value);
        }
    }
}
Also used : GenericAnnotatedTypeFactory(org.checkerframework.framework.type.GenericAnnotatedTypeFactory) VariableTree(com.sun.source.tree.VariableTree) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver) VariableElement(javax.lang.model.element.VariableElement) ThisReference(org.checkerframework.dataflow.analysis.FlowExpressions.ThisReference) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) ClassName(org.checkerframework.dataflow.analysis.FlowExpressions.ClassName) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) FieldAccess(org.checkerframework.dataflow.analysis.FlowExpressions.FieldAccess) Pair(org.checkerframework.javacutil.Pair)

Example 12 with VariableTree

use of com.sun.source.tree.VariableTree 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 13 with VariableTree

use of com.sun.source.tree.VariableTree in project checker-framework by typetools.

the class DependentTypesHelper method checkType.

/**
 * Checks all expression in the given annotated type to see if the expression string is an error
 * string as specified by {@link DependentTypesError#isExpressionError}. If the annotated type
 * has any errors, a flowexpr.parse.error is issued at the errorTree.
 *
 * @param atm annotated type to check for expression errors
 * @param errorTree the tree at which to report any found errors
 */
public void checkType(AnnotatedTypeMirror atm, Tree errorTree) {
    List<DependentTypesError> errors = new ExpressionErrorChecker().visit(atm);
    if (errors == null || errors.isEmpty()) {
        return;
    }
    if (errorTree.getKind() == Kind.VARIABLE) {
        ModifiersTree modifiers = ((VariableTree) errorTree).getModifiers();
        errorTree = ((VariableTree) errorTree).getType();
        for (AnnotationTree annoTree : modifiers.getAnnotations()) {
            for (Class<?> annoClazz : annoToElements.keySet()) {
                if (annoTree.toString().contains(annoClazz.getSimpleName())) {
                    errorTree = annoTree;
                    break;
                }
            }
        }
    }
    reportErrors(errorTree, errors);
}
Also used : ModifiersTree(com.sun.source.tree.ModifiersTree) VariableTree(com.sun.source.tree.VariableTree) AnnotationTree(com.sun.source.tree.AnnotationTree)

Example 14 with VariableTree

use of com.sun.source.tree.VariableTree in project checker-framework by typetools.

the class TypesIntoElements method store.

/**
 * The entry point.
 *
 * @param processingEnv the environment
 * @param atypeFactory the type factory
 * @param tree the ClassTree to process
 */
public static void store(ProcessingEnvironment processingEnv, AnnotatedTypeFactory atypeFactory, ClassTree tree) {
    Symbol.ClassSymbol csym = (Symbol.ClassSymbol) TreeUtils.elementFromDeclaration(tree);
    Types types = processingEnv.getTypeUtils();
    storeTypeParameters(processingEnv, types, atypeFactory, tree.getTypeParameters(), csym);
    for (Tree mem : tree.getMembers()) {
        if (mem.getKind() == Tree.Kind.METHOD) {
            storeMethod(processingEnv, types, atypeFactory, (MethodTree) mem);
        } else if (mem.getKind() == Tree.Kind.VARIABLE) {
            storeVariable(processingEnv, types, atypeFactory, (VariableTree) mem);
        } else {
        // System.out.println("Unhandled member tree: " + mem);
        }
    }
}
Also used : Types(javax.lang.model.util.Types) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) Symbol(com.sun.tools.javac.code.Symbol) VariableTree(com.sun.source.tree.VariableTree) 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) JCTree(com.sun.tools.javac.tree.JCTree)

Example 15 with VariableTree

use of com.sun.source.tree.VariableTree 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

VariableTree (com.sun.source.tree.VariableTree)86 Tree (com.sun.source.tree.Tree)43 ClassTree (com.sun.source.tree.ClassTree)37 MethodTree (com.sun.source.tree.MethodTree)37 ExpressionTree (com.sun.source.tree.ExpressionTree)34 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)25 NewClassTree (com.sun.source.tree.NewClassTree)23 TreePath (com.sun.source.util.TreePath)23 IdentifierTree (com.sun.source.tree.IdentifierTree)22 JCTree (com.sun.tools.javac.tree.JCTree)21 MemberSelectTree (com.sun.source.tree.MemberSelectTree)19 AssignmentTree (com.sun.source.tree.AssignmentTree)17 ArrayList (java.util.ArrayList)17 BlockTree (com.sun.source.tree.BlockTree)16 CompilationUnitTree (com.sun.source.tree.CompilationUnitTree)13 Type (com.sun.tools.javac.code.Type)13 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)12 ReturnTree (com.sun.source.tree.ReturnTree)12 StatementTree (com.sun.source.tree.StatementTree)12 VarSymbol (com.sun.tools.javac.code.Symbol.VarSymbol)12