Search in sources :

Example 11 with CaseTree

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

the class TreeUtils method switchExpressionTreeGetCases.

/**
 * Returns the cases of {@code switchExpressionTree}. For example
 *
 * <pre>
 *   switch ( <em>expression</em> ) {
 *     <em>cases</em>
 *   }
 * </pre>
 *
 * @param switchExpressionTree the switch expression whose cases are returned
 * @return the cases of {@code switchExpressionTree}
 */
public static List<? extends CaseTree> switchExpressionTreeGetCases(Tree switchExpressionTree) {
    try {
        Class<?> switchExpressionClass = Class.forName("com.sun.source.tree.SwitchExpressionTree");
        Method getCasesMethod = switchExpressionClass.getMethod("getCases");
        @SuppressWarnings("unchecked") List<? extends CaseTree> cases = (List<? extends CaseTree>) getCasesMethod.invoke(switchExpressionTree);
        if (cases != null) {
            return cases;
        }
        throw new BugInCF("TreeUtils.switchExpressionTreeGetCases: cases is null for tree: %s", switchExpressionTree);
    } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
        throw new BugInCF("TreeUtils.switchExpressionTreeGetCases: reflection failed for tree: %s", switchExpressionTree, e);
    }
}
Also used : CaseTree(com.sun.source.tree.CaseTree) List(java.util.List) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException)

Example 12 with CaseTree

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

the class SwitchExpressionScanner method scanSwitchExpression.

/**
 * Scans the given switch expression and calls {@link #visitSwitchResultExpression(ExpressionTree,
 * Object)} on each result expression of the switch expression. {@link #combineResults(Object,
 * Object)} is called to combine the results of visiting multiple switch result expressions.
 *
 * @param switchExpression a switch expression tree
 * @param p the parameter to pass to {@link #visitSwitchResultExpression(ExpressionTree, Object)}
 * @return the result of calling {@link #visitSwitchResultExpression(ExpressionTree, Object)} on
 *     each result expression of {@code switchExpression} and combining the results using {@link
 *     #combineResults(Object, Object)}
 */
public R scanSwitchExpression(Tree switchExpression, P p) {
    assert switchExpression.getKind().name().equals("SWITCH_EXPRESSION");
    List<? extends CaseTree> caseTrees = TreeUtils.switchExpressionTreeGetCases(switchExpression);
    R result = null;
    for (CaseTree caseTree : caseTrees) {
        if (caseTree.getStatements() != null) {
            // This case is a switch labeled statement group, so scan the statements for yield
            // statements.
            result = combineResults(result, yieldVisitor.scan(caseTree.getStatements(), p));
        } else {
            @SuppressWarnings(// caseTree.getStatements() == null, so the case has a body.
            "nullness:assignment") @NonNull Tree body = TreeUtils.caseTreeGetBody(caseTree);
            // See https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.28.2.
            if (body.getKind() == Kind.BLOCK) {
                // Scan for yield statements.
                result = combineResults(result, yieldVisitor.scan(((BlockTree) body).getStatements(), p));
            } else if (body.getKind() != Kind.THROW) {
                // The expression is the result expression.
                ExpressionTree expressionTree = (ExpressionTree) body;
                result = combineResults(result, visitSwitchResultExpression(expressionTree, p));
            }
        }
    }
    @SuppressWarnings(// switch expressions must have at least one case that results in a
    "nullness:assignment") @NonNull R nonNullResult = result;
    return nonNullResult;
}
Also used : CaseTree(com.sun.source.tree.CaseTree) NonNull(org.checkerframework.checker.nullness.qual.NonNull) BlockTree(com.sun.source.tree.BlockTree) ExpressionTree(com.sun.source.tree.ExpressionTree) CaseTree(com.sun.source.tree.CaseTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree)

Example 13 with CaseTree

use of com.sun.source.tree.CaseTree in project j2objc by google.

the class TreeConverter method convertSwitch.

private TreeNode convertSwitch(SwitchTree node, TreePath parent) {
    TreePath path = getTreePath(parent, node);
    SwitchStatement newNode = new SwitchStatement().setExpression(convertWithoutParens(node.getExpression(), path));
    for (CaseTree switchCase : node.getCases()) {
        newNode.addStatement((SwitchCase) convert(switchCase, path));
        TreePath switchCasePath = getTreePath(path, switchCase);
        for (StatementTree s : switchCase.getStatements()) {
            newNode.addStatement((Statement) convert(s, switchCasePath));
        }
    }
    return newNode;
}
Also used : ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) LabeledStatementTree(com.sun.source.tree.LabeledStatementTree) StatementTree(com.sun.source.tree.StatementTree) CaseTree(com.sun.source.tree.CaseTree) SwitchStatement(com.google.devtools.j2objc.ast.SwitchStatement) TreePath(com.sun.source.util.TreePath)

Example 14 with CaseTree

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

the class UnnecessaryDefaultInEnumSwitch method matchSwitch.

@Override
public Description matchSwitch(SwitchTree switchTree, VisitorState state) {
    // Only look at enum switches.
    TypeSymbol switchType = ((JCSwitch) switchTree).getExpression().type.tsym;
    if (switchType.getKind() != ElementKind.ENUM) {
        return NO_MATCH;
    }
    // Extract default case and the one before it.
    CaseTree caseBeforeDefault = null;
    CaseTree defaultCase = null;
    for (CaseTree caseTree : switchTree.getCases()) {
        if (caseTree.getExpression() == null) {
            defaultCase = caseTree;
            break;
        } else {
            caseBeforeDefault = caseTree;
        }
    }
    if (caseBeforeDefault == null || defaultCase == null) {
        return NO_MATCH;
    }
    SetView<String> unhandledCases = unhandledCases(switchTree, switchType);
    if (unhandledCases.equals(ImmutableSet.of("UNRECOGNIZED"))) {
        // switch handles all values of an proto-generated enum except for 'UNRECOGNIZED'.
        return fixUnrecognized(switchTree, defaultCase, state);
    }
    if (unhandledCases.isEmpty()) {
        // switch is exhaustive, remove the default if we can.
        return fixDefault(switchTree, caseBeforeDefault, defaultCase, state);
    }
    // switch is non-exhaustive, default can stay.
    return NO_MATCH;
}
Also used : CaseTree(com.sun.source.tree.CaseTree) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol)

Example 15 with CaseTree

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

the class DifferentNameButSame method matchCompilationUnit.

@Override
public Description matchCompilationUnit(CompilationUnitTree tree, VisitorState state) {
    Table<Symbol, String, List<TreePath>> names = HashBasedTable.create();
    new TreePathScanner<Void, Void>() {

        @Override
        public Void visitImport(ImportTree importTree, Void unused) {
            return null;
        }

        @Override
        public Void visitCase(CaseTree caseTree, Void unused) {
            return null;
        }

        @Override
        public Void visitMemberSelect(MemberSelectTree memberSelectTree, Void unused) {
            if (getCurrentPath().getParentPath().getLeaf() instanceof MemberSelectTree) {
                MemberSelectTree tree = (MemberSelectTree) getCurrentPath().getParentPath().getLeaf();
                Symbol superSymbol = getSymbol(tree);
                if (superSymbol instanceof ClassSymbol) {
                    return super.visitMemberSelect(memberSelectTree, null);
                }
            }
            handle(memberSelectTree);
            return super.visitMemberSelect(memberSelectTree, null);
        }

        @Override
        public Void visitIdentifier(IdentifierTree identifierTree, Void unused) {
            Tree parent = getCurrentPath().getParentPath().getLeaf();
            if (parent instanceof NewClassTree) {
                NewClassTree newClassTree = (NewClassTree) parent;
                if (newClassTree.getIdentifier().equals(identifierTree) && newClassTree.getEnclosingExpression() != null) {
                    // don't try to fix instantiations with explicit enclosing instances, e.g. `a.new B();`
                    return null;
                }
            }
            handle(identifierTree);
            return super.visitIdentifier(identifierTree, null);
        }

        private void handle(Tree tree) {
            if (state.getEndPosition(tree) == Position.NOPOS) {
                return;
            }
            Symbol symbol = getSymbol(tree);
            if (!(symbol instanceof ClassSymbol)) {
                return;
            }
            String name = tree.toString();
            List<TreePath> treePaths = names.get(symbol, name);
            if (treePaths == null) {
                treePaths = new ArrayList<>();
                names.put(symbol, name, treePaths);
            }
            treePaths.add(getCurrentPath());
        }
    }.scan(tree, null);
    for (Map.Entry<Symbol, Map<String, List<TreePath>>> entry : names.rowMap().entrySet()) {
        Symbol symbol = entry.getKey();
        // each level.
        if (isGeneric(symbol)) {
            continue;
        }
        if (isDefinedInThisFile(symbol, tree)) {
            continue;
        }
        Map<String, List<TreePath>> references = entry.getValue();
        if (references.size() == 1) {
            continue;
        }
        // Skip if any look to be fully qualified: this will be mentioned by a different check.
        if (references.keySet().stream().anyMatch(n -> Ascii.isLowerCase(n.charAt(0)))) {
            continue;
        }
        ImmutableList<String> namesByPreference = references.entrySet().stream().sorted(REPLACEMENT_PREFERENCE).map(Map.Entry::getKey).collect(toImmutableList());
        for (String name : namesByPreference) {
            ImmutableList<TreePath> sites = references.entrySet().stream().filter(e -> !e.getKey().equals(name)).map(Map.Entry::getValue).flatMap(Collection::stream).collect(toImmutableList());
            if (!(symbol instanceof MethodSymbol) && !visibleAndReferToSameThing(name, sites, state)) {
                continue;
            }
            if (BadImport.BAD_NESTED_CLASSES.contains(name)) {
                continue;
            }
            List<String> components = DOT_SPLITTER.splitToList(name);
            SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
            for (TreePath site : sites) {
                fixBuilder.merge(createFix(site, components, state));
            }
            SuggestedFix fix = fixBuilder.build();
            for (TreePath path : sites) {
                state.reportMatch(describeMatch(path.getLeaf(), fix));
            }
            break;
        }
    }
    return NO_MATCH;
}
Also used : Arrays(java.util.Arrays) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) Matchers.annotations(com.google.errorprone.matchers.Matchers.annotations) FindIdentifiers.findIdent(com.google.errorprone.util.FindIdentifiers.findIdent) HashBasedTable(com.google.common.collect.HashBasedTable) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) StandardTags(com.google.errorprone.BugPattern.StandardTags) IdentifierTree(com.sun.source.tree.IdentifierTree) Map(java.util.Map) Splitter(com.google.common.base.Splitter) TreePath(com.sun.source.util.TreePath) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Collection(java.util.Collection) Position(com.sun.tools.javac.util.Position) ASTHelpers.getSymbol(com.google.errorprone.util.ASTHelpers.getSymbol) MultiMatcher(com.google.errorprone.matchers.MultiMatcher) Symbol(com.sun.tools.javac.code.Symbol) Set(java.util.Set) Iterables.getLast(com.google.common.collect.Iterables.getLast) NO_MATCH(com.google.errorprone.matchers.Description.NO_MATCH) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ASTHelpers.getStartPosition(com.google.errorprone.util.ASTHelpers.getStartPosition) CaseTree(com.sun.source.tree.CaseTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) List(java.util.List) CompilationUnitTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.CompilationUnitTreeMatcher) Description(com.google.errorprone.matchers.Description) AnnotationTree(com.sun.source.tree.AnnotationTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) VisitorState(com.google.errorprone.VisitorState) ImmutableList(com.google.common.collect.ImmutableList) NewClassTree(com.sun.source.tree.NewClassTree) BugPattern(com.google.errorprone.BugPattern) TreePathScanner(com.sun.source.util.TreePathScanner) ImportTree(com.sun.source.tree.ImportTree) Tree(com.sun.source.tree.Tree) AT_LEAST_ONE(com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE) Ascii(com.google.common.base.Ascii) Target(java.lang.annotation.Target) ElementType(java.lang.annotation.ElementType) KindSelector(com.sun.tools.javac.code.Kinds.KindSelector) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Comparator(java.util.Comparator) Table(com.google.common.collect.Table) SeverityLevel(com.google.errorprone.BugPattern.SeverityLevel) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) ASTHelpers.getSymbol(com.google.errorprone.util.ASTHelpers.getSymbol) Symbol(com.sun.tools.javac.code.Symbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ArrayList(java.util.ArrayList) IdentifierTree(com.sun.source.tree.IdentifierTree) NewClassTree(com.sun.source.tree.NewClassTree) CaseTree(com.sun.source.tree.CaseTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) IdentifierTree(com.sun.source.tree.IdentifierTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) CaseTree(com.sun.source.tree.CaseTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) AnnotationTree(com.sun.source.tree.AnnotationTree) 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) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) TreePath(com.sun.source.util.TreePath) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) ImportTree(com.sun.source.tree.ImportTree) Map(java.util.Map)

Aggregations

CaseTree (com.sun.source.tree.CaseTree)16 Tree (com.sun.source.tree.Tree)6 CompilationUnitTree (com.sun.source.tree.CompilationUnitTree)4 ExpressionTree (com.sun.source.tree.ExpressionTree)4 List (java.util.List)4 Iterables.getLast (com.google.common.collect.Iterables.getLast)3 BugPattern (com.google.errorprone.BugPattern)3 VisitorState (com.google.errorprone.VisitorState)3 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)3 Description (com.google.errorprone.matchers.Description)3 NO_MATCH (com.google.errorprone.matchers.Description.NO_MATCH)3 BlockTree (com.sun.source.tree.BlockTree)3 IdentifierTree (com.sun.source.tree.IdentifierTree)3 ImportTree (com.sun.source.tree.ImportTree)3 MemberSelectTree (com.sun.source.tree.MemberSelectTree)3 StatementTree (com.sun.source.tree.StatementTree)3 VariableTree (com.sun.source.tree.VariableTree)3 ArrayList (java.util.ArrayList)3 ImmutableList (com.google.common.collect.ImmutableList)2 StandardTags (com.google.errorprone.BugPattern.StandardTags)2