Search in sources :

Example 46 with TreePath

use of com.sun.source.util.TreePath in project error-prone by google.

the class AbstractMustBeClosedChecker method checkClosed.

private Description checkClosed(ExpressionTree tree, VisitorState state) {
    MethodTree callerMethodTree = enclosingMethod(state);
    TreePath path = state.getPath();
    OUTER: while (true) {
        TreePath prev = path;
        path = path.getParentPath();
        switch(path.getLeaf().getKind()) {
            case RETURN:
                if (callerMethodTree != null) {
                    // expression or anonymous class.
                    if (HAS_MUST_BE_CLOSED_ANNOTATION.matches(callerMethodTree, state)) {
                        // enforced.
                        return NO_MATCH;
                    }
                    // enforced. Suggest fixing this by annotating the caller method.
                    return buildDescription(tree).addFix(SuggestedFix.builder().prefixWith(callerMethodTree, "@MustBeClosed\n").addImport(MustBeClosed.class.getCanonicalName()).build()).build();
                }
                break;
            case CONDITIONAL_EXPRESSION:
                ConditionalExpressionTree conditionalExpressionTree = (ConditionalExpressionTree) path.getLeaf();
                if (conditionalExpressionTree.getTrueExpression().equals(prev.getLeaf()) || conditionalExpressionTree.getFalseExpression().equals(prev.getLeaf())) {
                    continue OUTER;
                }
                break;
            case MEMBER_SELECT:
                MemberSelectTree memberSelectTree = (MemberSelectTree) path.getLeaf();
                if (memberSelectTree.getExpression().equals(prev.getLeaf())) {
                    Type type = getType(memberSelectTree);
                    Symbol sym = getSymbol(memberSelectTree);
                    Type streamType = state.getTypeFromString(Stream.class.getName());
                    if (isSubtype(sym.enclClass().asType(), streamType, state) && isSameType(type.getReturnType(), streamType, state)) {
                        // skip enclosing method invocation
                        path = path.getParentPath();
                        continue OUTER;
                    }
                }
                break;
            case VARIABLE:
                Symbol sym = getSymbol(path.getLeaf());
                if (sym instanceof VarSymbol) {
                    VarSymbol var = (VarSymbol) sym;
                    if (var.getKind() == ElementKind.RESOURCE_VARIABLE || tryFinallyClose(var, path, state)) {
                        return NO_MATCH;
                    }
                }
                break;
            default:
                break;
        }
        // The constructor or method invocation does not occur within the resource variable
        // initializer of a try-with-resources statement.
        Description.Builder description = buildDescription(tree);
        addFix(description, tree, state);
        return description.build();
    }
}
Also used : Matchers.toType(com.google.errorprone.matchers.Matchers.toType) ASTHelpers.getType(com.google.errorprone.util.ASTHelpers.getType) ASTHelpers.isSameType(com.google.errorprone.util.ASTHelpers.isSameType) Type(com.sun.tools.javac.code.Type) TreePath(com.sun.source.util.TreePath) MethodTree(com.sun.source.tree.MethodTree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) ASTHelpers.getSymbol(com.google.errorprone.util.ASTHelpers.getSymbol) Symbol(com.sun.tools.javac.code.Symbol) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MustBeClosed(com.google.errorprone.annotations.MustBeClosed) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol)

Example 47 with TreePath

use of com.sun.source.util.TreePath in project error-prone by google.

the class FindIdentifiers method isVisible.

private static boolean isVisible(VarSymbol var, final TreePath path) {
    switch(var.getKind()) {
        case ENUM_CONSTANT:
        case FIELD:
            // TODO(eaftan): Switch collector to ImmutableList.toImmutableList() when released
            List<ClassSymbol> enclosingClasses = StreamSupport.stream(path.spliterator(), false).filter(tree -> tree instanceof ClassTree).map(ClassTree.class::cast).map(ASTHelpers::getSymbol).collect(Collectors.toCollection(ArrayList::new));
            if (!var.isStatic()) {
                // Instance fields are not visible if we are in a static context...
                if (inStaticContext(path)) {
                    return false;
                }
                // the enclosing static nested class (JLS 8.5.1).
                if (lowerThan(path, (curr, unused) -> curr instanceof ClassTree && ASTHelpers.getSymbol((ClassTree) curr).isStatic(), (curr, unused) -> curr instanceof ClassTree && ASTHelpers.getSymbol((ClassTree) curr).equals(var.owner))) {
                    return false;
                }
            }
            // fields (JLS 6.6.1).
            if (enclosingClasses.contains(ASTHelpers.enclosingClass(var))) {
                return true;
            }
            PackageSymbol enclosingPackage = ((JCCompilationUnit) path.getCompilationUnit()).packge;
            Set<Modifier> modifiers = var.getModifiers();
            // (JLS 6.6.1).
            if (Objects.equals(enclosingPackage, ASTHelpers.enclosingPackage(var))) {
                return !modifiers.contains(Modifier.PRIVATE);
            }
            // in the enclosing class or a superclass).
            return modifiers.contains(Modifier.PUBLIC) || modifiers.contains(Modifier.PROTECTED);
        case PARAMETER:
        case LOCAL_VARIABLE:
            // final or effectively final (JLS 8.1.3).
            if (lowerThan(path, (curr, parent) -> curr.getKind() == Kind.LAMBDA_EXPRESSION || (curr.getKind() == Kind.NEW_CLASS && ((NewClassTree) curr).getClassBody() != null) || (curr.getKind() == Kind.CLASS && parent.getKind() == Kind.BLOCK), (curr, unused) -> Objects.equals(var.owner, ASTHelpers.getSymbol(curr)))) {
                if ((var.flags() & (Flags.FINAL | Flags.EFFECTIVELY_FINAL)) == 0) {
                    return false;
                }
            }
            return true;
        case EXCEPTION_PARAMETER:
        case RESOURCE_VARIABLE:
            return true;
        default:
            throw new IllegalArgumentException("Unexpected variable type: " + var.getKind());
    }
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassType(com.sun.tools.javac.code.Type.ClassType) Modifier(javax.lang.model.element.Modifier) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) ForLoopTree(com.sun.source.tree.ForLoopTree) Method(java.lang.reflect.Method) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) TreePath(com.sun.source.util.TreePath) ImmutableSet(com.google.common.collect.ImmutableSet) Symbol(com.sun.tools.javac.code.Symbol) Set(java.util.Set) MemberSelectTree(com.sun.source.tree.MemberSelectTree) Env(com.sun.tools.javac.comp.Env) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) JCCompilationUnit(com.sun.tools.javac.tree.JCTree.JCCompilationUnit) TreeScanner(com.sun.source.util.TreeScanner) Objects(java.util.Objects) List(java.util.List) WriteableScope(com.sun.tools.javac.code.Scope.WriteableScope) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) Flags(com.sun.tools.javac.code.Flags) Name(com.sun.tools.javac.util.Name) Scope(com.sun.tools.javac.code.Scope) Type(com.sun.tools.javac.code.Type) MethodTree(com.sun.source.tree.MethodTree) MemberEnter(com.sun.tools.javac.comp.MemberEnter) VariableTree(com.sun.source.tree.VariableTree) AttrContext(com.sun.tools.javac.comp.AttrContext) ArrayList(java.util.ArrayList) VisitorState(com.google.errorprone.VisitorState) BiPredicate(java.util.function.BiPredicate) Kind(com.sun.source.tree.Tree.Kind) ImmutableList(com.google.common.collect.ImmutableList) NewClassTree(com.sun.source.tree.NewClassTree) StreamSupport(java.util.stream.StreamSupport) ImportTree(com.sun.source.tree.ImportTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) LinkedHashSet(java.util.LinkedHashSet) Nullable(javax.annotation.Nullable) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) Enter(com.sun.tools.javac.comp.Enter) ElementKind(javax.lang.model.element.ElementKind) KindSelector(com.sun.tools.javac.code.Kinds.KindSelector) TryTree(com.sun.source.tree.TryTree) Collections(java.util.Collections) Resolve(com.sun.tools.javac.comp.Resolve) JCCompilationUnit(com.sun.tools.javac.tree.JCTree.JCCompilationUnit) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) NewClassTree(com.sun.source.tree.NewClassTree) ClassTree(com.sun.source.tree.ClassTree) NewClassTree(com.sun.source.tree.NewClassTree) Modifier(javax.lang.model.element.Modifier)

Example 48 with TreePath

use of com.sun.source.util.TreePath in project error-prone by google.

the class ErrorProneAnalyzer method finished.

@Override
public void finished(TaskEvent taskEvent) {
    if (taskEvent.getKind() != Kind.ANALYZE) {
        return;
    }
    if (JavaCompiler.instance(context).errorCount() > 0) {
        return;
    }
    TreePath path = JavacTrees.instance(context).getPath(taskEvent.getTypeElement());
    if (path == null) {
        path = new TreePath(taskEvent.getCompilationUnit());
    }
    // Assert that the event is unique and scan the current tree.
    verify(seen.add(path.getLeaf()), "Duplicate FLOW event for: %s", taskEvent.getTypeElement());
    Context subContext = new SubContext(context);
    subContext.put(ErrorProneOptions.class, errorProneOptions);
    Log log = Log.instance(context);
    JCCompilationUnit compilation = (JCCompilationUnit) path.getCompilationUnit();
    DescriptionListener descriptionListener = descriptionListenerFactory.getDescriptionListener(log, compilation);
    JavaFileObject originalSource = log.useSource(compilation.getSourceFile());
    try {
        if (shouldExcludeSourceFile(compilation.getSourceFile())) {
            return;
        }
        if (path.getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) {
            // We only get TaskEvents for compilation units if they contain no package declarations
            // (e.g. package-info.java files).  In this case it's safe to analyze the
            // CompilationUnitTree immediately.
            transformer.get().apply(path, subContext, descriptionListener);
        } else if (finishedCompilation(path.getCompilationUnit())) {
            // Otherwise this TaskEvent is for a ClassTree, and we can scan the whole
            // CompilationUnitTree once we've seen all the enclosed classes.
            transformer.get().apply(new TreePath(compilation), subContext, descriptionListener);
        }
    } catch (ErrorProneError e) {
        e.logFatalError(log);
        // terminate with Result.ABNORMAL
        throw e;
    } catch (CompletionFailure e) {
        // A CompletionFailure can be triggered when error-prone tries to complete a symbol
        // that isn't on the compilation classpath. This can occur when a check performs an
        // instanceof test on a symbol, which requires inspecting the transitive closure of the
        // symbol's supertypes. If javac didn't need to check the symbol's assignability
        // then a normal compilation would have succeeded, and no diagnostics will have been
        // reported yet, but we don't want to crash javac.
        log.error("proc.cant.access", e.sym, e.getDetailValue(), Throwables.getStackTraceAsString(e));
    } finally {
        log.useSource(originalSource);
    }
}
Also used : Context(com.sun.tools.javac.util.Context) JCCompilationUnit(com.sun.tools.javac.tree.JCTree.JCCompilationUnit) JavaFileObject(javax.tools.JavaFileObject) TreePath(com.sun.source.util.TreePath) Log(com.sun.tools.javac.util.Log) CompletionFailure(com.sun.tools.javac.code.Symbol.CompletionFailure)

Example 49 with TreePath

use of com.sun.source.util.TreePath in project error-prone by google.

the class NullnessPropagationTransfer method fieldInitializerNullnessIfAvailable.

@Nullable
private Nullness fieldInitializerNullnessIfAvailable(ClassAndField accessed) {
    if (!traversed.add(accessed.symbol)) {
        // TODO(kmb): Try to recognize problems with initialization order
        return NULL;
    }
    try {
        JavacProcessingEnvironment javacEnv = JavacProcessingEnvironment.instance(context);
        TreePath fieldDeclPath = Trees.instance(javacEnv).getPath(accessed.symbol);
        // missing types.
        if (fieldDeclPath == null || fieldDeclPath.getCompilationUnit() != compilationUnit || !(fieldDeclPath.getLeaf() instanceof VariableTree)) {
            return null;
        }
        ExpressionTree initializer = ((VariableTree) fieldDeclPath.getLeaf()).getInitializer();
        if (initializer == null) {
            return null;
        }
        ClassTree classTree = (ClassTree) fieldDeclPath.getParentPath().getLeaf();
        // Run flow analysis on field initializer.  This is inefficient compared to just walking
        // the initializer expression tree but it avoids duplicating the logic from this transfer
        // function into a method that operates on Javac Nodes.
        TreePath initializerPath = TreePath.getPath(fieldDeclPath, initializer);
        UnderlyingAST ast = new UnderlyingAST.CFGStatement(initializerPath.getLeaf(), classTree);
        ControlFlowGraph cfg = CFGBuilder.build(initializerPath, javacEnv, ast, /* assumeAssertionsEnabled */
        false, /* assumeAssertionsDisabled */
        false);
        Analysis<Nullness, LocalStore<Nullness>, NullnessPropagationTransfer> analysis = new Analysis<>(javacEnv, this);
        analysis.performAnalysis(cfg);
        return analysis.getValue(initializerPath.getLeaf());
    } finally {
        traversed.remove(accessed.symbol);
    }
}
Also used : VariableTree(com.sun.source.tree.VariableTree) ClassTree(com.sun.source.tree.ClassTree) LocalStore(com.google.errorprone.dataflow.LocalStore) TreePath(com.sun.source.util.TreePath) Analysis(org.checkerframework.dataflow.analysis.Analysis) ControlFlowGraph(org.checkerframework.dataflow.cfg.ControlFlowGraph) JavacProcessingEnvironment(com.sun.tools.javac.processing.JavacProcessingEnvironment) ExpressionTree(com.sun.source.tree.ExpressionTree) UnderlyingAST(org.checkerframework.dataflow.cfg.UnderlyingAST) Nullable(javax.annotation.Nullable)

Example 50 with TreePath

use of com.sun.source.util.TreePath in project error-prone by google.

the class TrustingNullnessAnalysis method getFieldInitializerNullness.

/**
 * Returns {@link Nullness} of the initializer of the {@link VariableTree} at the leaf of the
 * given {@code fieldDeclPath}. Returns {@link Nullness#NULL} should there be no initializer.
 */
// TODO(kmb): Fold this functionality into Dataflow.expressionDataflow
public Nullness getFieldInitializerNullness(TreePath fieldDeclPath, Context context) {
    Tree decl = fieldDeclPath.getLeaf();
    checkArgument(decl instanceof VariableTree && ((JCVariableDecl) decl).sym.getKind() == ElementKind.FIELD, "Leaf of fieldDeclPath must be a field declaration: %s", decl);
    ExpressionTree initializer = ((VariableTree) decl).getInitializer();
    if (initializer == null) {
        // An uninitialized field is null or 0 to start :)
        return ((JCVariableDecl) decl).type.isPrimitive() ? Nullness.NONNULL : Nullness.NULL;
    }
    TreePath initializerPath = TreePath.getPath(fieldDeclPath, initializer);
    ClassTree classTree = (ClassTree) fieldDeclPath.getParentPath().getLeaf();
    JavacProcessingEnvironment javacEnv = JavacProcessingEnvironment.instance(context);
    UnderlyingAST ast = new UnderlyingAST.CFGStatement(decl, classTree);
    ControlFlowGraph cfg = CFGBuilder.build(initializerPath, javacEnv, ast, /* assumeAssertionsEnabled */
    false, /* assumeAssertionsDisabled */
    false);
    try {
        nullnessPropagation.setContext(context).setCompilationUnit(fieldDeclPath.getCompilationUnit());
        Analysis<Nullness, LocalStore<Nullness>, TrustingNullnessPropagation> analysis = new Analysis<>(javacEnv, nullnessPropagation);
        analysis.performAnalysis(cfg);
        return analysis.getValue(initializer);
    } finally {
        nullnessPropagation.setContext(null).setCompilationUnit(null);
    }
}
Also used : VariableTree(com.sun.source.tree.VariableTree) ClassTree(com.sun.source.tree.ClassTree) LocalStore(com.google.errorprone.dataflow.LocalStore) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) TreePath(com.sun.source.util.TreePath) Analysis(org.checkerframework.dataflow.analysis.Analysis) ControlFlowGraph(org.checkerframework.dataflow.cfg.ControlFlowGraph) JavacProcessingEnvironment(com.sun.tools.javac.processing.JavacProcessingEnvironment) ExpressionTree(com.sun.source.tree.ExpressionTree) VariableTree(com.sun.source.tree.VariableTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) ExpressionTree(com.sun.source.tree.ExpressionTree) UnderlyingAST(org.checkerframework.dataflow.cfg.UnderlyingAST)

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