Search in sources :

Example 6 with TryTree

use of com.sun.source.tree.TryTree in project st-js by st-js.

the class TryWriter method visit.

@Override
public JS visit(WriterVisitor<JS> visitor, TryTree tree, GenerationContext<JS> context) {
    JS tryBlock = visitor.scan(tree.getBlock(), context);
    List<JS> catchClauses = new ArrayList<JS>();
    for (Tree c : tree.getCatches()) {
        catchClauses.add(visitor.scan(c, context));
    }
    JS finallyBlock = null;
    if (tree.getFinallyBlock() != null) {
        finallyBlock = visitor.scan(tree.getFinallyBlock(), context);
    }
    return context.withPosition(tree, context.js().tryStatement(tryBlock, catchClauses, finallyBlock));
}
Also used : ArrayList(java.util.ArrayList) TryTree(com.sun.source.tree.TryTree) Tree(com.sun.source.tree.Tree)

Example 7 with TryTree

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

the class CFGTranslationPhaseOne method visitTry.

@Override
public Node visitTry(TryTree tree, Void p) {
    List<? extends CatchTree> catches = tree.getCatches();
    BlockTree finallyBlock = tree.getFinallyBlock();
    extendWithNode(new MarkerNode(tree, "start of try statement #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
    List<Pair<TypeMirror, Label>> catchLabels = CollectionsPlume.mapList((CatchTree c) -> {
        return Pair.of(TreeUtils.typeOf(c.getParameter().getType()), new Label());
    }, catches);
    // Store return/break/continue labels, just in case we need them for a finally block.
    TryFinallyScopeCell oldReturnTargetL = returnTargetL;
    TryFinallyScopeCell oldBreakTargetL = breakTargetL;
    Map<Name, Label> oldBreakLabels = breakLabels;
    TryFinallyScopeCell oldContinueTargetL = continueTargetL;
    Map<Name, Label> oldContinueLabels = continueLabels;
    Label finallyLabel = null;
    Label exceptionalFinallyLabel = null;
    if (finallyBlock != null) {
        finallyLabel = new Label();
        exceptionalFinallyLabel = new Label();
        tryStack.pushFrame(new TryFinallyFrame(exceptionalFinallyLabel));
        returnTargetL = new TryFinallyScopeCell();
        breakTargetL = new TryFinallyScopeCell();
        breakLabels = new TryFinallyScopeMap();
        continueTargetL = new TryFinallyScopeCell();
        continueLabels = new TryFinallyScopeMap();
    }
    Label doneLabel = new Label();
    tryStack.pushFrame(new TryCatchFrame(types, catchLabels));
    // Must scan the resources *after* we push frame to tryStack. Otherwise we can lose catch
    // blocks.
    // TODO: Should we handle try-with-resources blocks by also generating code for automatically
    // closing the resources?
    List<? extends Tree> resources = tree.getResources();
    for (Tree resource : resources) {
        scan(resource, p);
    }
    extendWithNode(new MarkerNode(tree, "start of try block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
    scan(tree.getBlock(), p);
    extendWithNode(new MarkerNode(tree, "end of try block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
    extendWithExtendedNode(new UnconditionalJump(CFGBuilder.firstNonNull(finallyLabel, doneLabel)));
    tryStack.popFrame();
    int catchIndex = 0;
    for (CatchTree c : catches) {
        addLabelForNextNode(catchLabels.get(catchIndex).second);
        extendWithNode(new MarkerNode(tree, "start of catch block for " + c.getParameter().getType() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
        scan(c, p);
        extendWithNode(new MarkerNode(tree, "end of catch block for " + c.getParameter().getType() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
        catchIndex++;
        extendWithExtendedNode(new UnconditionalJump(CFGBuilder.firstNonNull(finallyLabel, doneLabel)));
    }
    if (finallyLabel != null) {
        // Reset values before analyzing the finally block!
        tryStack.popFrame();
        {
            // Scan 'finallyBlock' for only 'finallyLabel' (a successful path)
            addLabelForNextNode(finallyLabel);
            extendWithNode(new MarkerNode(tree, "start of finally block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            scan(finallyBlock, p);
            extendWithNode(new MarkerNode(tree, "end of finally block #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            extendWithExtendedNode(new UnconditionalJump(doneLabel));
        }
        if (hasExceptionalPath(exceptionalFinallyLabel)) {
            // If an exceptional path exists, scan 'finallyBlock' for 'exceptionalFinallyLabel', and
            // scan copied 'finallyBlock' for 'finallyLabel' (a successful path). If there is no
            // successful path, it will be removed in later phase.
            // TODO: Don't we need a separate finally block for each kind of exception?
            addLabelForNextNode(exceptionalFinallyLabel);
            extendWithNode(new MarkerNode(tree, "start of finally block for Throwable #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            scan(finallyBlock, p);
            NodeWithExceptionsHolder throwing = extendWithNodeWithException(new MarkerNode(tree, "end of finally block for Throwable #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()), throwableType);
            throwing.setTerminatesExecution(true);
        }
        if (returnTargetL.wasAccessed()) {
            addLabelForNextNode(returnTargetL.peekLabel());
            returnTargetL = oldReturnTargetL;
            extendWithNode(new MarkerNode(tree, "start of finally block for return #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            scan(finallyBlock, p);
            extendWithNode(new MarkerNode(tree, "end of finally block for return #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            extendWithExtendedNode(new UnconditionalJump(returnTargetL.accessLabel()));
        } else {
            returnTargetL = oldReturnTargetL;
        }
        if (breakTargetL.wasAccessed()) {
            addLabelForNextNode(breakTargetL.peekLabel());
            breakTargetL = oldBreakTargetL;
            extendWithNode(new MarkerNode(tree, "start of finally block for break #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            scan(finallyBlock, p);
            extendWithNode(new MarkerNode(tree, "end of finally block for break #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            extendWithExtendedNode(new UnconditionalJump(breakTargetL.accessLabel()));
        } else {
            breakTargetL = oldBreakTargetL;
        }
        Map<Name, Label> accessedBreakLabels = ((TryFinallyScopeMap) breakLabels).getAccessedNames();
        if (!accessedBreakLabels.isEmpty()) {
            breakLabels = oldBreakLabels;
            for (Map.Entry<Name, Label> access : accessedBreakLabels.entrySet()) {
                addLabelForNextNode(access.getValue());
                extendWithNode(new MarkerNode(tree, "start of finally block for break label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
                scan(finallyBlock, p);
                extendWithNode(new MarkerNode(tree, "end of finally block for break label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
                extendWithExtendedNode(new UnconditionalJump(breakLabels.get(access.getKey())));
            }
        } else {
            breakLabels = oldBreakLabels;
        }
        if (continueTargetL.wasAccessed()) {
            addLabelForNextNode(continueTargetL.peekLabel());
            continueTargetL = oldContinueTargetL;
            extendWithNode(new MarkerNode(tree, "start of finally block for continue #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            scan(finallyBlock, p);
            extendWithNode(new MarkerNode(tree, "end of finally block for continue #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
            extendWithExtendedNode(new UnconditionalJump(continueTargetL.accessLabel()));
        } else {
            continueTargetL = oldContinueTargetL;
        }
        Map<Name, Label> accessedContinueLabels = ((TryFinallyScopeMap) continueLabels).getAccessedNames();
        if (!accessedContinueLabels.isEmpty()) {
            continueLabels = oldContinueLabels;
            for (Map.Entry<Name, Label> access : accessedContinueLabels.entrySet()) {
                addLabelForNextNode(access.getValue());
                extendWithNode(new MarkerNode(tree, "start of finally block for continue label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
                scan(finallyBlock, p);
                extendWithNode(new MarkerNode(tree, "end of finally block for continue label " + access.getKey() + " #" + TreeUtils.treeUids.get(tree), env.getTypeUtils()));
                extendWithExtendedNode(new UnconditionalJump(continueLabels.get(access.getKey())));
            }
        } else {
            continueLabels = oldContinueLabels;
        }
    }
    addLabelForNextNode(doneLabel);
    return null;
}
Also used : CatchTree(com.sun.source.tree.CatchTree) Name(javax.lang.model.element.Name) MarkerNode(org.checkerframework.dataflow.cfg.node.MarkerNode) BlockTree(com.sun.source.tree.BlockTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) LiteralTree(com.sun.source.tree.LiteralTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) TypeCastTree(com.sun.source.tree.TypeCastTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ForLoopTree(com.sun.source.tree.ForLoopTree) InstanceOfTree(com.sun.source.tree.InstanceOfTree) ParenthesizedTree(com.sun.source.tree.ParenthesizedTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) ThrowTree(com.sun.source.tree.ThrowTree) BlockTree(com.sun.source.tree.BlockTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ReturnTree(com.sun.source.tree.ReturnTree) ArrayTypeTree(com.sun.source.tree.ArrayTypeTree) LabeledStatementTree(com.sun.source.tree.LabeledStatementTree) 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) BreakTree(com.sun.source.tree.BreakTree) ImportTree(com.sun.source.tree.ImportTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) WildcardTree(com.sun.source.tree.WildcardTree) UnionTypeTree(com.sun.source.tree.UnionTypeTree) ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) NewArrayTree(com.sun.source.tree.NewArrayTree) ContinueTree(com.sun.source.tree.ContinueTree) CaseTree(com.sun.source.tree.CaseTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) SwitchTree(com.sun.source.tree.SwitchTree) PrimitiveTypeTree(com.sun.source.tree.PrimitiveTypeTree) SynchronizedTree(com.sun.source.tree.SynchronizedTree) AssertTree(com.sun.source.tree.AssertTree) StatementTree(com.sun.source.tree.StatementTree) ModifiersTree(com.sun.source.tree.ModifiersTree) WhileLoopTree(com.sun.source.tree.WhileLoopTree) AnnotationTree(com.sun.source.tree.AnnotationTree) MethodTree(com.sun.source.tree.MethodTree) BinaryTree(com.sun.source.tree.BinaryTree) EmptyStatementTree(com.sun.source.tree.EmptyStatementTree) ClassTree(com.sun.source.tree.ClassTree) IfTree(com.sun.source.tree.IfTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) ErroneousTree(com.sun.source.tree.ErroneousTree) DoWhileLoopTree(com.sun.source.tree.DoWhileLoopTree) TryTree(com.sun.source.tree.TryTree) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) Pair(org.checkerframework.javacutil.Pair)

Example 8 with TryTree

use of com.sun.source.tree.TryTree in project error-prone by google.

the class FindIdentifiers method findAllIdents.

/**
 * Finds the set of all bare variable identifiers in scope at the current location. Identifiers
 * are ordered by ascending distance/scope count from the current location to match shadowing
 * rules. That is, if two variables with the same simple names appear in the set, the one that
 * appears first in iteration order is the one you get if you use the bare name in the source
 * code.
 *
 * <p>We do not report variables that would require a qualfied access. We also do not handle
 * wildcard imports.
 */
public static LinkedHashSet<VarSymbol> findAllIdents(VisitorState state) {
    ImmutableSet.Builder<VarSymbol> result = new ImmutableSet.Builder<>();
    Tree prev = state.getPath().getLeaf();
    for (Tree curr : state.getPath().getParentPath()) {
        switch(curr.getKind()) {
            case BLOCK:
                for (StatementTree stmt : ((BlockTree) curr).getStatements()) {
                    if (stmt.equals(prev)) {
                        break;
                    }
                    addIfVariable(stmt, result);
                }
                break;
            case METHOD:
                for (VariableTree param : ((MethodTree) curr).getParameters()) {
                    result.add(ASTHelpers.getSymbol(param));
                }
                break;
            case CATCH:
                result.add(ASTHelpers.getSymbol(((CatchTree) curr).getParameter()));
                break;
            case CLASS:
            case INTERFACE:
            case ENUM:
            case ANNOTATION_TYPE:
                // field is referred to by qualified name, but we don't support that.
                for (Tree member : ((ClassTree) curr).getMembers()) {
                    if (member.equals(prev)) {
                        break;
                    }
                    addIfVariable(member, result);
                }
                // Collect inherited fields.
                Type classType = ASTHelpers.getType(curr);
                List<Type> classTypeClosure = state.getTypes().closure(classType);
                List<Type> superTypes = classTypeClosure.size() <= 1 ? Collections.emptyList() : classTypeClosure.subList(1, classTypeClosure.size());
                for (Type type : superTypes) {
                    Scope scope = type.tsym.members();
                    ImmutableList.Builder<VarSymbol> varsList = ImmutableList.builder();
                    for (Symbol var : scope.getSymbols(VarSymbol.class::isInstance)) {
                        varsList.add((VarSymbol) var);
                    }
                    result.addAll(varsList.build().reverse());
                }
                break;
            case FOR_LOOP:
                addAllIfVariable(((ForLoopTree) curr).getInitializer(), result);
                break;
            case ENHANCED_FOR_LOOP:
                result.add(ASTHelpers.getSymbol(((EnhancedForLoopTree) curr).getVariable()));
                break;
            case TRY:
                TryTree tryTree = (TryTree) curr;
                boolean inResources = false;
                for (Tree resource : tryTree.getResources()) {
                    if (resource.equals(prev)) {
                        inResources = true;
                        break;
                    }
                }
                if (inResources) {
                    // Case 1: we're in one of the resource declarations
                    for (Tree resource : tryTree.getResources()) {
                        if (resource.equals(prev)) {
                            break;
                        }
                        addIfVariable(resource, result);
                    }
                } else if (tryTree.getBlock().equals(prev)) {
                    // Case 2: We're in the block (not a catch or finally)
                    addAllIfVariable(tryTree.getResources(), result);
                }
                break;
            case COMPILATION_UNIT:
                for (ImportTree importTree : ((CompilationUnitTree) curr).getImports()) {
                    if (importTree.isStatic() && importTree.getQualifiedIdentifier().getKind() == Kind.MEMBER_SELECT) {
                        MemberSelectTree memberSelectTree = (MemberSelectTree) importTree.getQualifiedIdentifier();
                        Scope scope = state.getTypes().membersClosure(ASTHelpers.getType(memberSelectTree.getExpression()), /* skipInterface= */
                        false);
                        for (Symbol var : scope.getSymbols(sym -> sym instanceof VarSymbol && sym.getSimpleName().equals(memberSelectTree.getIdentifier()))) {
                            result.add((VarSymbol) var);
                        }
                    }
                }
                break;
            default:
                // other node types don't introduce variables
                break;
        }
        prev = curr;
    }
    // TODO(eaftan): switch out collector for ImmutableSet.toImmutableSet()
    return result.build().stream().filter(var -> isVisible(var, state.getPath())).collect(Collectors.toCollection(LinkedHashSet::new));
}
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) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) MethodTree(com.sun.source.tree.MethodTree) CatchTree(com.sun.source.tree.CatchTree) ImmutableList(com.google.common.collect.ImmutableList) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) Symbol(com.sun.tools.javac.code.Symbol) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) MemberSelectTree(com.sun.source.tree.MemberSelectTree) VariableTree(com.sun.source.tree.VariableTree) NewClassTree(com.sun.source.tree.NewClassTree) ClassTree(com.sun.source.tree.ClassTree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) StatementTree(com.sun.source.tree.StatementTree) ClassType(com.sun.tools.javac.code.Type.ClassType) Type(com.sun.tools.javac.code.Type) ImmutableSet(com.google.common.collect.ImmutableSet) WriteableScope(com.sun.tools.javac.code.Scope.WriteableScope) Scope(com.sun.tools.javac.code.Scope) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) ForLoopTree(com.sun.source.tree.ForLoopTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) NewClassTree(com.sun.source.tree.NewClassTree) ImportTree(com.sun.source.tree.ImportTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) TryTree(com.sun.source.tree.TryTree) BlockTree(com.sun.source.tree.BlockTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) TryTree(com.sun.source.tree.TryTree) ImportTree(com.sun.source.tree.ImportTree)

Example 9 with TryTree

use of com.sun.source.tree.TryTree in project error-prone by google.

the class WakelockReleasedDangerously method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
    // Match on calls to any override of WakeLock.release().
    if (!RELEASE.matches(tree, state)) {
        return NO_MATCH;
    }
    // Ok if surrounded in try/catch block that catches RuntimeException.
    TryTree enclosingTry = findEnclosingNode(state.getPath(), TryTree.class);
    if (enclosingTry != null && tryCatchesException(enclosingTry, state.getSymtab().runtimeExceptionType, state)) {
        return NO_MATCH;
    }
    // Ok if WakeLock not in danger of unexpected exception.
    // Also, can't perform analysis if WakeLock symbol not found.
    Symbol wakelockSymbol = getSymbol(getReceiver(tree));
    if (wakelockSymbol == null || !wakelockMayThrow(wakelockSymbol, state)) {
        return NO_MATCH;
    }
    Tree releaseStatement = state.getPath().getParentPath().getLeaf();
    return describeMatch(releaseStatement, getFix(releaseStatement, wakelockSymbol, state));
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ASTHelpers.getSymbol(com.google.errorprone.util.ASTHelpers.getSymbol) Symbol(com.sun.tools.javac.code.Symbol) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) CatchTree(com.sun.source.tree.CatchTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) IfTree(com.sun.source.tree.IfTree) ExpressionTree(com.sun.source.tree.ExpressionTree) TryTree(com.sun.source.tree.TryTree) TryTree(com.sun.source.tree.TryTree)

Example 10 with TryTree

use of com.sun.source.tree.TryTree in project error-prone by google.

the class ThreadJoinLoop method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree methodInvocationTree, VisitorState visitorState) {
    String threadString;
    if (methodInvocationTree.getMethodSelect() instanceof MemberSelectTree) {
        threadString = ((MemberSelectTree) methodInvocationTree.getMethodSelect()).getExpression().toString();
    } else {
        threadString = "this";
    }
    // with calculating time with declared variables)
    if (!methodInvocationTree.getArguments().isEmpty()) {
        return Description.NO_MATCH;
    }
    if (MATCH_THREAD_JOIN.matches(methodInvocationTree, visitorState)) {
        TreePath treePath = ASTHelpers.findPathFromEnclosingNodeToTopLevel(visitorState.getPath(), TryTree.class);
        if (treePath == null) {
            return Description.NO_MATCH;
        }
        TreePath pathToLoop = ASTHelpers.findPathFromEnclosingNodeToTopLevel(treePath, WhileLoopTree.class);
        // checks to make sure that if there is a while loop with only one statement (the try catch
        // block)
        boolean hasWhileLoopOneStatement = false;
        if (pathToLoop != null) {
            Tree statements = ((WhileLoopTree) pathToLoop.getLeaf()).getStatement();
            if (statements instanceof BlockTree) {
                if (((BlockTree) statements).getStatements().size() == 1) {
                    hasWhileLoopOneStatement = true;
                }
            }
        }
        Type interruptedType = visitorState.getSymtab().interruptedExceptionType;
        Type exceptionType = visitorState.getSymtab().exceptionType;
        TryTree tryTree = (TryTree) treePath.getLeaf();
        // scans the try tree block for any other actions so that we do not accidentally delete
        // important actions when replacing
        TreeScannerMethodInvocations treeScanner = new TreeScannerMethodInvocations();
        treeScanner.scan(tryTree.getBlock(), methodInvocationTree.toString());
        if (treeScanner.count > 0) {
            return Description.NO_MATCH;
        }
        if (tryTree.getFinallyBlock() != null) {
            return Description.NO_MATCH;
        }
        List<? extends CatchTree> catches = tryTree.getCatches();
        for (CatchTree tree : catches) {
            Type typeSym = ASTHelpers.getType(tree.getParameter().getType());
            if (Objects.equals(interruptedType, typeSym) || Objects.equals(exceptionType, typeSym)) {
                List<? extends StatementTree> statementTrees = tree.getBlock().getStatements();
                // replaces the while loop with the try block or replaces just the try block
                if (statementTrees.isEmpty() || (statementTrees.size() == 1 && statementTrees.get(0).toString().equals(";"))) {
                    SuggestedFix.Builder builder = SuggestedFix.builder();
                    builder.replace(hasWhileLoopOneStatement ? pathToLoop.getLeaf() : tryTree, "Uninterruptibles.joinUninterruptibly(" + threadString + ");");
                    builder.addImport("com.google.common.util.concurrent.Uninterruptibles");
                    return describeMatch(methodInvocationTree, builder.build());
                }
            }
        }
    }
    return Description.NO_MATCH;
}
Also used : CatchTree(com.sun.source.tree.CatchTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) Type(com.sun.tools.javac.code.Type) TreePath(com.sun.source.util.TreePath) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) WhileLoopTree(com.sun.source.tree.WhileLoopTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) CatchTree(com.sun.source.tree.CatchTree) Tree(com.sun.source.tree.Tree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) TryTree(com.sun.source.tree.TryTree) WhileLoopTree(com.sun.source.tree.WhileLoopTree) BlockTree(com.sun.source.tree.BlockTree) TryTree(com.sun.source.tree.TryTree)

Aggregations

Tree (com.sun.source.tree.Tree)12 TryTree (com.sun.source.tree.TryTree)12 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)11 CatchTree (com.sun.source.tree.CatchTree)9 BlockTree (com.sun.source.tree.BlockTree)8 ExpressionTree (com.sun.source.tree.ExpressionTree)8 StatementTree (com.sun.source.tree.StatementTree)8 ExpressionStatementTree (com.sun.source.tree.ExpressionStatementTree)6 MemberSelectTree (com.sun.source.tree.MemberSelectTree)6 MethodTree (com.sun.source.tree.MethodTree)6 VariableTree (com.sun.source.tree.VariableTree)6 ClassTree (com.sun.source.tree.ClassTree)5 IdentifierTree (com.sun.source.tree.IdentifierTree)5 AssignmentTree (com.sun.source.tree.AssignmentTree)4 CompilationUnitTree (com.sun.source.tree.CompilationUnitTree)4 EnhancedForLoopTree (com.sun.source.tree.EnhancedForLoopTree)4 ForLoopTree (com.sun.source.tree.ForLoopTree)4 IfTree (com.sun.source.tree.IfTree)4 NewClassTree (com.sun.source.tree.NewClassTree)4 WhileLoopTree (com.sun.source.tree.WhileLoopTree)4