Search in sources :

Example 26 with StatementTree

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

the class UnnecessaryDefaultInEnumSwitch method matchSwitch.

@Override
public Description matchSwitch(SwitchTree tree, VisitorState state) {
    TypeSymbol switchType = ((JCSwitch) tree).getExpression().type.tsym;
    if (switchType.getKind() != ElementKind.ENUM) {
        return NO_MATCH;
    }
    CaseTree caseBeforeDefault = null;
    CaseTree defaultCase = null;
    for (CaseTree caseTree : tree.getCases()) {
        if (caseTree.getExpression() == null) {
            defaultCase = caseTree;
            break;
        } else {
            caseBeforeDefault = caseTree;
        }
    }
    if (defaultCase == null) {
        return NO_MATCH;
    }
    Set<String> handledCases = tree.getCases().stream().map(CaseTree::getExpression).filter(IdentifierTree.class::isInstance).map(p -> ((IdentifierTree) p).getName().toString()).collect(toImmutableSet());
    if (!ASTHelpers.enumValues(switchType).equals(handledCases)) {
        return NO_MATCH;
    }
    Fix fix;
    List<? extends StatementTree> defaultStatements = defaultCase.getStatements();
    if (trivialDefault(defaultStatements)) {
        // deleting `default:` or `default: break;` is a no-op
        fix = SuggestedFix.delete(defaultCase);
    } else {
        String defaultSource = state.getSourceCode().subSequence(((JCTree) defaultStatements.get(0)).getStartPosition(), state.getEndPosition(getLast(defaultStatements))).toString();
        String initialComments = comments(state, defaultCase, defaultStatements);
        if (!canCompleteNormally(tree)) {
            // if the switch statement cannot complete normally, then deleting the default
            // and moving its statements to after the switch statement is a no-op
            fix = SuggestedFix.builder().delete(defaultCase).postfixWith(tree, initialComments + defaultSource).build();
        } else {
            // and the code is unreachable -- so use (2) as the strategy.  Otherwise, use (1).
            if (!SuggestedFixes.compilesWithFix(SuggestedFix.delete(defaultCase), state)) {
                // case (3)
                return NO_MATCH;
            }
            if (!canCompleteNormally(caseBeforeDefault)) {
                // case (2) -- If the case before the default can't complete normally,
                // it's OK to to delete the default.
                fix = SuggestedFix.delete(defaultCase);
            } else {
                // case (1) -- If it can complete, we need to merge the default into it.
                fix = SuggestedFix.builder().delete(defaultCase).postfixWith(caseBeforeDefault, initialComments + defaultSource).build();
            }
        }
    }
    return describeMatch(defaultCase, fix);
}
Also used : SuggestedFixes(com.google.errorprone.fixes.SuggestedFixes) SwitchTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.SwitchTreeMatcher) VisitorState(com.google.errorprone.VisitorState) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) IdentifierTree(com.sun.source.tree.IdentifierTree) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) BugPattern(com.google.errorprone.BugPattern) JDK(com.google.errorprone.BugPattern.Category.JDK) Fix(com.google.errorprone.fixes.Fix) Tree(com.sun.source.tree.Tree) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) ElementKind(javax.lang.model.element.ElementKind) Set(java.util.Set) Iterables.getLast(com.google.common.collect.Iterables.getLast) Iterables.getOnlyElement(com.google.common.collect.Iterables.getOnlyElement) NO_MATCH(com.google.errorprone.matchers.Description.NO_MATCH) CaseTree(com.sun.source.tree.CaseTree) JCTree(com.sun.tools.javac.tree.JCTree) SwitchTree(com.sun.source.tree.SwitchTree) List(java.util.List) Description(com.google.errorprone.matchers.Description) StatementTree(com.sun.source.tree.StatementTree) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Reachability.canCompleteNormally(com.google.errorprone.util.Reachability.canCompleteNormally) ASTHelpers(com.google.errorprone.util.ASTHelpers) CaseTree(com.sun.source.tree.CaseTree) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) Fix(com.google.errorprone.fixes.Fix) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) IdentifierTree(com.sun.source.tree.IdentifierTree) JCTree(com.sun.tools.javac.tree.JCTree) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol)

Example 27 with StatementTree

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

Example 28 with StatementTree

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

the class TryFailThrowable method fixWithReturnOrBoolean.

private static Fix fixWithReturnOrBoolean(TryTree tryTree, StatementTree failStatement, VisitorState state) {
    Tree parent = state.getPath().getParentPath().getLeaf();
    Tree grandparent = state.getPath().getParentPath().getParentPath().getLeaf();
    if (parent.getKind() == BLOCK && grandparent.getKind() == METHOD && tryTree == getLastStatement((BlockTree) parent)) {
        return fixWithReturn(tryTree, failStatement, state);
    } else {
        return fixWithBoolean(tryTree, failStatement, state);
    }
}
Also used : VariableTree(com.sun.source.tree.VariableTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) CatchTree(com.sun.source.tree.CatchTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) TryTree(com.sun.source.tree.TryTree)

Example 29 with StatementTree

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

the class UBlank method apply.

@Override
public Choice<UnifierWithUnconsumedStatements> apply(final UnifierWithUnconsumedStatements state) {
    int goodIndex = 0;
    while (goodIndex < state.unconsumedStatements().size()) {
        StatementTree stmt = state.unconsumedStatements().get(goodIndex);
        if (firstNonNull(FORBIDDEN_REFERENCE_SCANNER.scan(stmt, state.unifier()), false) && ControlFlowVisitor.INSTANCE.visitStatement(stmt) == ControlFlowVisitor.Result.NEVER_EXITS) {
            break;
        } else {
            goodIndex++;
        }
    }
    Collection<Integer> breakPoints = ContiguousSet.create(Range.closed(0, goodIndex), DiscreteDomain.integers());
    return Choice.from(breakPoints).transform((Integer k) -> {
        Unifier unifier = state.unifier().fork();
        unifier.putBinding(key(), state.unconsumedStatements().subList(0, k));
        List<? extends StatementTree> remaining = state.unconsumedStatements().subList(k, state.unconsumedStatements().size());
        return UnifierWithUnconsumedStatements.create(unifier, remaining);
    });
}
Also used : StatementTree(com.sun.source.tree.StatementTree)

Example 30 with StatementTree

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

the class CatchFail method rethrowFix.

private Optional<Fix> rethrowFix(ImmutableList<CatchTree> catchBlocks, VisitorState state) {
    SuggestedFix.Builder fix = SuggestedFix.builder();
    catchBlocks.forEach(c -> {
        // e.g.
        // fail("message") -> throw new AssertionError("message", cause);
        // assertWithMessage("message format %s", 42) ->
        // throw new AssertionError(String.format("message format %s", 42), cause);
        StatementTree statementTree = getOnlyElement(c.getBlock().getStatements());
        MethodInvocationTree methodInvocationTree = (MethodInvocationTree) ((ExpressionStatementTree) statementTree).getExpression();
        String message = null;
        if (message == null && !methodInvocationTree.getArguments().isEmpty()) {
            message = getMessageOrFormat(methodInvocationTree, state);
        }
        if (message != null) {
            // only catch and rethrow to add additional context, not for raw `fail()` calls
            fix.replace(statementTree, String.format("throw new AssertionError(%s, %s);", message, c.getParameter().getName()));
        }
    });
    return fix.isEmpty() ? Optional.empty() : Optional.of(fix.build());
}
Also used : ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) StatementTree(com.sun.source.tree.StatementTree) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree)

Aggregations

StatementTree (com.sun.source.tree.StatementTree)37 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)19 ExpressionStatementTree (com.sun.source.tree.ExpressionStatementTree)18 BlockTree (com.sun.source.tree.BlockTree)16 Tree (com.sun.source.tree.Tree)16 ExpressionTree (com.sun.source.tree.ExpressionTree)12 TreePath (com.sun.source.util.TreePath)9 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)8 MethodTree (com.sun.source.tree.MethodTree)8 MemberSelectTree (com.sun.source.tree.MemberSelectTree)7 TryTree (com.sun.source.tree.TryTree)7 VariableTree (com.sun.source.tree.VariableTree)7 CatchTree (com.sun.source.tree.CatchTree)6 JCTree (com.sun.tools.javac.tree.JCTree)6 ClassTree (com.sun.source.tree.ClassTree)5 IdentifierTree (com.sun.source.tree.IdentifierTree)5 MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)5 VisitorState (com.google.errorprone.VisitorState)4 Description (com.google.errorprone.matchers.Description)4 EnhancedForLoopTree (com.sun.source.tree.EnhancedForLoopTree)4