Search in sources :

Example 51 with MethodTree

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

the class BaseTypeVisitor method visitReturn.

/**
 * Checks that the type of the return expression is a subtype of the enclosing method required
 * return type. If not, it issues a "return" error.
 */
@Override
public Void visitReturn(ReturnTree node, Void p) {
    // Don't try to check return expressions for void methods.
    if (node.getExpression() == null) {
        return super.visitReturn(node, p);
    }
    Tree enclosing = TreePathUtil.enclosingOfKind(getCurrentPath(), new HashSet<>(Arrays.asList(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION)));
    AnnotatedTypeMirror ret = null;
    if (enclosing.getKind() == Tree.Kind.METHOD) {
        MethodTree enclosingMethod = TreePathUtil.enclosingMethod(getCurrentPath());
        boolean valid = validateTypeOf(enclosing);
        if (valid) {
            ret = atypeFactory.getMethodReturnType(enclosingMethod, node);
        }
    } else {
        AnnotatedExecutableType result = atypeFactory.getFunctionTypeFromTree((LambdaExpressionTree) enclosing);
        ret = result.getReturnType();
    }
    if (ret != null) {
        commonAssignmentCheck(ret, node.getExpression(), "return");
    }
    return super.visitReturn(node, p);
}
Also used : AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) MethodTree(com.sun.source.tree.MethodTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) TypeCastTree(com.sun.source.tree.TypeCastTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) InstanceOfTree(com.sun.source.tree.InstanceOfTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ThrowTree(com.sun.source.tree.ThrowTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ReturnTree(com.sun.source.tree.ReturnTree) ArrayTypeTree(com.sun.source.tree.ArrayTypeTree) UnaryTree(com.sun.source.tree.UnaryTree) VariableTree(com.sun.source.tree.VariableTree) TypeParameterTree(com.sun.source.tree.TypeParameterTree) NewClassTree(com.sun.source.tree.NewClassTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) IntersectionTypeTree(com.sun.source.tree.IntersectionTypeTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) NewArrayTree(com.sun.source.tree.NewArrayTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) ModifiersTree(com.sun.source.tree.ModifiersTree) AnnotationTree(com.sun.source.tree.AnnotationTree) MethodTree(com.sun.source.tree.MethodTree) ClassTree(com.sun.source.tree.ClassTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) JCTree(com.sun.tools.javac.tree.JCTree) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 52 with MethodTree

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

the class InitializationVisitor method checkFieldsInitialized.

/**
 * Checks that all fields (all static fields if {@code staticFields} is true) are initialized in
 * the given store.
 *
 * @param node a {@link ClassTree} if {@code staticFields} is true; a {@link MethodTree} for a
 *     constructor if {@code staticFields} is false. This is where errors are reported, if they
 *     are not reported at the fields themselves
 * @param staticFields whether to check static fields or instance fields
 * @param store the store
 * @param receiverAnnotations the annotations on the receiver
 */
// TODO: the code for checking if fields are initialized should be re-written,
// as the current version contains quite a few ugly parts, is hard to understand,
// and it is likely that it does not take full advantage of the information
// about initialization we compute in
// GenericAnnotatedTypeFactory.initializationStaticStore and
// GenericAnnotatedTypeFactory.initializationStore.
protected void checkFieldsInitialized(Tree node, boolean staticFields, Store store, List<? extends AnnotationMirror> receiverAnnotations) {
    // If the store is null, then the constructor cannot terminate successfully
    if (store == null) {
        return;
    }
    // check for uninitialized fields in them:
    if (node.getKind() == Tree.Kind.METHOD && TreeUtils.isCompactCanonicalRecordConstructor((MethodTree) node)) {
        return;
    }
    Pair<List<VariableTree>, List<VariableTree>> uninitializedFields = atypeFactory.getUninitializedFields(store, getCurrentPath(), staticFields, receiverAnnotations);
    List<VariableTree> violatingFields = uninitializedFields.first;
    List<VariableTree> nonviolatingFields = uninitializedFields.second;
    // Remove fields that have already been initialized by an initializer block.
    if (staticFields) {
        violatingFields.removeAll(initializedFields);
        nonviolatingFields.removeAll(initializedFields);
    } else {
        violatingFields.removeAll(initializedFields);
        nonviolatingFields.removeAll(initializedFields);
    }
    // Errors are issued at the field declaration if the field is static or if the constructor
    // is the default constructor.
    // Errors are issued at the constructor declaration if the field is non-static and the
    // constructor is non-default.
    boolean errorAtField = staticFields || TreeUtils.isSynthetic((MethodTree) node);
    String FIELDS_UNINITIALIZED_KEY = (staticFields ? "initialization.static.field.uninitialized" : errorAtField ? "initialization.field.uninitialized" : "initialization.fields.uninitialized");
    // Remove fields with a relevant @SuppressWarnings annotation.
    violatingFields.removeIf(f -> checker.shouldSuppressWarnings(TreeUtils.elementFromTree(f), FIELDS_UNINITIALIZED_KEY));
    nonviolatingFields.removeIf(f -> checker.shouldSuppressWarnings(TreeUtils.elementFromTree(f), FIELDS_UNINITIALIZED_KEY));
    if (!violatingFields.isEmpty()) {
        if (errorAtField) {
            // Issue each error at the relevant field
            for (VariableTree f : violatingFields) {
                checker.reportError(f, FIELDS_UNINITIALIZED_KEY, f.getName());
            }
        } else {
            // Issue all the errors at the relevant constructor
            StringJoiner fieldsString = new StringJoiner(", ");
            for (VariableTree f : violatingFields) {
                fieldsString.add(f.getName());
            }
            checker.reportError(node, FIELDS_UNINITIALIZED_KEY, fieldsString);
        }
    }
    // Support -Ainfer command-line argument.
    WholeProgramInference wpi = atypeFactory.getWholeProgramInference();
    if (wpi != null) {
        // For each uninitialized field, treat it as if the default value is assigned to it.
        List<VariableTree> uninitFields = new ArrayList<>(violatingFields);
        uninitFields.addAll(nonviolatingFields);
        for (VariableTree fieldTree : uninitFields) {
            Element elt = TreeUtils.elementFromTree(fieldTree);
            wpi.updateFieldFromType(fieldTree, elt, fieldTree.getName().toString(), atypeFactory.getDefaultValueAnnotatedType(elt.asType()));
        }
    }
}
Also used : MethodTree(com.sun.source.tree.MethodTree) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) VariableTree(com.sun.source.tree.VariableTree) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) WholeProgramInference(org.checkerframework.common.wholeprograminference.WholeProgramInference) StringJoiner(java.util.StringJoiner)

Example 53 with MethodTree

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

the class InterningVisitor method processClassTree.

/**
 * Method to implement the @UsesObjectEquals functionality. If a class is annotated
 * with @UsesObjectEquals, it must:
 *
 * <ul>
 *   <li>not override .equals(Object) and be a subclass of a class annotated
 *       with @UsesObjectEquals, or
 *   <li>override equals(Object) with body "this == arg"
 * </ul>
 *
 * If a class is not annotated with @UsesObjectEquals, it must:
 *
 * <ul>
 *   <li>not have a superclass annotated with @UsesObjectEquals
 * </ul>
 *
 * @see
 *     org.checkerframework.common.basetype.BaseTypeVisitor#visitClass(com.sun.source.tree.ClassTree,
 *     java.lang.Object)
 */
@Override
public void processClassTree(ClassTree classTree) {
    TypeElement elt = TreeUtils.elementFromDeclaration(classTree);
    AnnotationMirror annotation = atypeFactory.getDeclAnnotation(elt, UsesObjectEquals.class);
    // and its supertype is Object or is annotated with @UsesObjectEquals.
    if (annotation != null) {
        MethodTree equalsMethod = equalsImplementation(classTree);
        if (equalsMethod != null) {
            if (!isReferenceEqualityImplementation(equalsMethod)) {
                checker.reportError(classTree, "overrides.equals");
            }
        } else {
            // Does not override equals()
            TypeMirror superClass = elt.getSuperclass();
            if (superClass != null && // The super class of an interface is "none" rather than null.
            superClass.getKind() == TypeKind.DECLARED) {
                TypeElement superClassElement = TypesUtils.getTypeElement(superClass);
                if (superClassElement != null && !ElementUtils.isObject(superClassElement) && atypeFactory.getDeclAnnotation(superClassElement, UsesObjectEquals.class) == null) {
                    checker.reportError(classTree, "superclass.notannotated");
                }
            }
        }
    }
    super.processClassTree(classTree);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) MethodTree(com.sun.source.tree.MethodTree) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement)

Example 54 with MethodTree

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

the class InterningVisitor method equalsImplementation.

// **********************************************************************
// Helper methods
// **********************************************************************
/**
 * Returns the method that overrides Object.equals, or null.
 *
 * @param node a class
 * @return the class's implementation of equals, or null
 */
private MethodTree equalsImplementation(ClassTree node) {
    List<? extends Tree> members = node.getMembers();
    for (Tree member : members) {
        if (member instanceof MethodTree) {
            MethodTree mTree = (MethodTree) member;
            ExecutableElement enclosing = TreeUtils.elementFromDeclaration(mTree);
            if (overrides(enclosing, Object.class, "equals")) {
                return mTree;
            }
        }
    }
    return null;
}
Also used : MethodTree(com.sun.source.tree.MethodTree) ExecutableElement(javax.lang.model.element.ExecutableElement) ReturnTree(com.sun.source.tree.ReturnTree) LiteralTree(com.sun.source.tree.LiteralTree) MethodTree(com.sun.source.tree.MethodTree) BinaryTree(com.sun.source.tree.BinaryTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) NewClassTree(com.sun.source.tree.NewClassTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) IfTree(com.sun.source.tree.IfTree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree)

Example 55 with MethodTree

use of com.sun.source.tree.MethodTree 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. Also, returns true if the {@code errKey} matches a string in
 * {@code -AsuppressWarnings}.
 *
 * @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 boolean shouldSuppressWarnings(Tree tree, String errKey) {
    Collection<String> prefixes = getSuppressWarningsPrefixes();
    if (prefixes.isEmpty() || (prefixes.contains(SUPPRESS_ALL_PREFIX) && prefixes.size() == 1)) {
        throw new BugInCF("Checker must provide a SuppressWarnings prefix." + " SourceChecker#getSuppressWarningsPrefixes was not overridden correctly.");
    }
    if (shouldSuppress(getSuppressWarningsStringsFromOption(), errKey)) {
        return true;
    }
    if (shouldSuppress(getSuppressWarningsStringsFromOption(), errKey)) {
        // the warning.
        return true;
    }
    // trees.getPath might be slow, but this is only used in error reporting
    @Nullable TreePath path = trees.getPath(this.currentRoot, tree);
    @Nullable VariableTree var = TreePathUtil.enclosingVariable(path);
    if (var != null && shouldSuppressWarnings(TreeUtils.elementFromTree(var), errKey)) {
        return true;
    }
    @Nullable MethodTree method = TreePathUtil.enclosingMethod(path);
    if (method != null) {
        @Nullable Element elt = TreeUtils.elementFromTree(method);
        if (shouldSuppressWarnings(elt, errKey)) {
            return true;
        }
        if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
            // because they may not have an @AnnotatedFor.
            return false;
        }
    }
    @Nullable ClassTree cls = TreePathUtil.enclosingClass(path);
    if (cls != null) {
        @Nullable Element elt = TreeUtils.elementFromTree(cls);
        if (shouldSuppressWarnings(elt, errKey)) {
            return true;
        }
        if (isAnnotatedForThisCheckerOrUpstreamChecker(elt)) {
            // because they may not have an @AnnotatedFor.
            return false;
        }
    }
    if (useConservativeDefault("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) BugInCF(org.checkerframework.javacutil.BugInCF) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Aggregations

MethodTree (com.sun.source.tree.MethodTree)127 ClassTree (com.sun.source.tree.ClassTree)66 Tree (com.sun.source.tree.Tree)65 VariableTree (com.sun.source.tree.VariableTree)58 ExpressionTree (com.sun.source.tree.ExpressionTree)54 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)43 ExecutableElement (javax.lang.model.element.ExecutableElement)39 NewClassTree (com.sun.source.tree.NewClassTree)38 TreePath (com.sun.source.util.TreePath)33 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)32 MemberSelectTree (com.sun.source.tree.MemberSelectTree)28 AnnotationTree (com.sun.source.tree.AnnotationTree)25 IdentifierTree (com.sun.source.tree.IdentifierTree)25 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)23 ReturnTree (com.sun.source.tree.ReturnTree)22 MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)22 ArrayList (java.util.ArrayList)22 TypeElement (javax.lang.model.element.TypeElement)21 AssignmentTree (com.sun.source.tree.AssignmentTree)20 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)20