Search in sources :

Example 71 with IdentifierTree

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

the class TreeParserTest method parsesIndex.

@Test
public void parsesIndex() {
    String value = "array[2]";
    ExpressionTree parsed = parser.parseTree(value);
    Assert.assertTrue(parsed instanceof ArrayAccessTree);
    ArrayAccessTree access = (ArrayAccessTree) parsed;
    Assert.assertEquals(2, ((LiteralTree) access.getIndex()).getValue());
    Assert.assertEquals("array", ((IdentifierTree) access.getExpression()).getName().toString());
}
Also used : ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) ExpressionTree(com.sun.source.tree.ExpressionTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Test(org.junit.Test)

Example 72 with IdentifierTree

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

the class BaseTypeValidator method extractParameterizedTypeTree.

/**
 * If {@code tree} has a {@link ParameterizedTypeTree}, then the tree and its type is returned.
 * Otherwise null and {@code type} are returned.
 *
 * @param tree tree to search
 * @param type type to return if no {@code ParameterizedTypeTree} is found
 * @return if {@code tree} has a {@code ParameterizedTypeTree}, then returns the tree and its
 *     type. Otherwise, returns null and {@code type}.
 */
private Pair<@Nullable ParameterizedTypeTree, AnnotatedDeclaredType> extractParameterizedTypeTree(Tree tree, AnnotatedDeclaredType type) {
    ParameterizedTypeTree typeargtree = null;
    switch(tree.getKind()) {
        case VARIABLE:
            Tree lt = ((VariableTree) tree).getType();
            if (lt instanceof ParameterizedTypeTree) {
                typeargtree = (ParameterizedTypeTree) lt;
            } else {
            // System.out.println("Found a: " + lt);
            }
            break;
        case PARAMETERIZED_TYPE:
            typeargtree = (ParameterizedTypeTree) tree;
            break;
        case NEW_CLASS:
            NewClassTree nct = (NewClassTree) tree;
            ExpressionTree nctid = nct.getIdentifier();
            if (nctid.getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
                typeargtree = (ParameterizedTypeTree) nctid;
                /*
           * This is quite tricky... for anonymous class instantiations,
           * the type at this point has no type arguments. By doing the
           * following, we get the type arguments again.
           */
                type = (AnnotatedDeclaredType) atypeFactory.getAnnotatedType(typeargtree);
            }
            break;
        case ANNOTATED_TYPE:
            AnnotatedTypeTree tr = (AnnotatedTypeTree) tree;
            ExpressionTree undtr = tr.getUnderlyingType();
            if (undtr instanceof ParameterizedTypeTree) {
                typeargtree = (ParameterizedTypeTree) undtr;
            } else if (undtr instanceof IdentifierTree) {
            // @Something D -> Nothing to do
            } else {
                // TODO: add more test cases to ensure that nested types are
                // handled correctly,
                // e.g. @Nullable() List<@Nullable Object>[][]
                Pair<ParameterizedTypeTree, AnnotatedDeclaredType> p = extractParameterizedTypeTree(undtr, type);
                typeargtree = p.first;
                type = p.second;
            }
            break;
        case IDENTIFIER:
        case ARRAY_TYPE:
        case NEW_ARRAY:
        case MEMBER_SELECT:
        case UNBOUNDED_WILDCARD:
        case EXTENDS_WILDCARD:
        case SUPER_WILDCARD:
        case TYPE_PARAMETER:
            // Nothing to do.
            break;
        case METHOD:
            // If a MethodTree is passed, it's just the return type that is validated.
            // See BaseTypeVisitor#validateTypeOf.
            MethodTree methodTree = (MethodTree) tree;
            if (methodTree.getReturnType() instanceof ParameterizedTypeTree) {
                typeargtree = (ParameterizedTypeTree) methodTree.getReturnType();
            }
            break;
        default:
            // No need to do anything further.
            break;
    }
    return Pair.of(typeargtree, type);
}
Also used : AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) TypeParameterTree(com.sun.source.tree.TypeParameterTree) NewClassTree(com.sun.source.tree.NewClassTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) ExpressionTree(com.sun.source.tree.ExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) IdentifierTree(com.sun.source.tree.IdentifierTree) NewClassTree(com.sun.source.tree.NewClassTree) Pair(org.checkerframework.javacutil.Pair)

Example 73 with IdentifierTree

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

the class ExpectedTreesVisitor method visitExpressionStatement.

@Override
public Void visitExpressionStatement(ExpressionStatementTree tree, Void p) {
    // These don't have matching JavaParser nodes.
    if (JointJavacJavaParserVisitor.isDefaultSuperConstructorCall(tree)) {
        return null;
    }
    // Whereas synthetic constructors should be skipped, regular super() and this() should still
    // be added. JavaParser has no expression statement surrounding these, so remove the
    // expression statement itself.
    Void result = super.visitExpressionStatement(tree, p);
    if (tree.getExpression().getKind() == Tree.Kind.METHOD_INVOCATION) {
        MethodInvocationTree invocation = (MethodInvocationTree) tree.getExpression();
        if (invocation.getMethodSelect().getKind() == Tree.Kind.IDENTIFIER) {
            IdentifierTree identifier = (IdentifierTree) invocation.getMethodSelect();
            if (identifier.getName().contentEquals("this") || identifier.getName().contentEquals("super")) {
                trees.remove(tree);
                trees.remove(identifier);
            }
        }
    }
    return result;
}
Also used : MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree)

Example 74 with IdentifierTree

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

the class StreamResourceLeak method addFix.

@Override
protected void addFix(Description.Builder description, ExpressionTree tree, VisitorState state) {
    TreePath parentPath = state.getPath().getParentPath();
    Tree parent = parentPath.getLeaf();
    SuggestedFix.Builder fix = SuggestedFix.builder();
    String streamType = SuggestedFixes.prettyType(state, fix, ASTHelpers.getReturnType(tree));
    if (parent instanceof MemberSelectTree) {
        StatementTree statement = state.findEnclosing(StatementTree.class);
        if (statement instanceof VariableTree) {
            // Variables need to be declared outside the try-with-resources:
            // e.g. `int count = Files.lines(p).count();`
            // -> `int count; try (Stream<String> stream = Files.lines(p)) { count = stream.count(); }`
            VariableTree var = (VariableTree) statement;
            int pos = ((JCTree) var).getStartPosition();
            int initPos = ((JCTree) var.getInitializer()).getStartPosition();
            int eqPos = pos + state.getSourceForNode(var).substring(0, initPos - pos).lastIndexOf('=');
            fix.replace(eqPos, initPos, String.format(";\ntry (%s stream = %s) {\n%s =", streamType, state.getSourceForNode(tree), var.getName().toString()));
        } else {
            // the non-variable case, e.g. `return Files.lines(p).count()`
            // -> try (Stream<Stream> stream = Files.lines(p)) { return stream.count(); }`
            fix.prefixWith(statement, String.format("try (%s stream = %s) {\n", streamType, state.getSourceForNode(tree)));
        }
        fix.replace(tree, "stream");
        fix.postfixWith(statement, "}");
        description.addFix(fix.build());
    } else if (parent instanceof VariableTree) {
        // If the stream is assigned to a variable, wrap the variable in a try-with-resources
        // that includes all statements in the same block that reference the variable.
        Tree grandParent = parentPath.getParentPath().getLeaf();
        if (!(grandParent instanceof BlockTree)) {
            return;
        }
        List<? extends StatementTree> statements = ((BlockTree) grandParent).getStatements();
        int idx = statements.indexOf(parent);
        int lastUse = idx;
        for (int i = idx + 1; i < statements.size(); i++) {
            boolean[] found = { false };
            statements.get(i).accept(new TreeScanner<Void, Void>() {

                @Override
                public Void visitIdentifier(IdentifierTree tree, Void unused) {
                    if (Objects.equals(ASTHelpers.getSymbol(tree), ASTHelpers.getSymbol(parent))) {
                        found[0] = true;
                    }
                    return null;
                }
            }, null);
            if (found[0]) {
                lastUse = i;
            }
        }
        fix.prefixWith(parent, "try (");
        fix.replace(state.getEndPosition(((VariableTree) parent).getInitializer()), state.getEndPosition(parent), ") {");
        fix.postfixWith(statements.get(lastUse), "}");
        description.addFix(fix.build());
    } else if (parent instanceof EnhancedForLoopTree) {
        // If the stream is used in a loop (e.g. directory streams), wrap the loop in
        // try-with-resources.
        fix.prefixWith(parent, String.format("try (%s stream = %s) {\n", streamType, state.getSourceForNode(tree)));
        fix.replace(tree, "stream");
        fix.postfixWith(parent, "}");
        description.addFix(fix.build());
    } else if (parent instanceof MethodInvocationTree) {
        // If the stream is used in a method that is called in an expression statement, wrap it in
        // try-with-resources.
        Tree grandParent = parentPath.getParentPath().getLeaf();
        if (!(grandParent instanceof ExpressionStatementTree)) {
            return;
        }
        fix.prefixWith(parent, String.format("try (%s stream = %s) {\n", streamType, state.getSourceForNode(tree)));
        fix.replace(tree, "stream");
        fix.postfixWith(grandParent, "}");
        description.addFix(fix.build());
    }
}
Also used : MemberSelectTree(com.sun.source.tree.MemberSelectTree) VariableTree(com.sun.source.tree.VariableTree) JCTree(com.sun.tools.javac.tree.JCTree) IdentifierTree(com.sun.source.tree.IdentifierTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) StatementTree(com.sun.source.tree.StatementTree) TreePath(com.sun.source.util.TreePath) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) TreeScanner(com.sun.source.util.TreeScanner) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) VariableTree(com.sun.source.tree.VariableTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) JCTree(com.sun.tools.javac.tree.JCTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) BlockTree(com.sun.source.tree.BlockTree) List(java.util.List) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree)

Example 75 with IdentifierTree

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

the class StringSplitter method buildFix.

public Optional<Fix> buildFix(MethodInvocationTree tree, VisitorState state) {
    Tree arg = getOnlyElement(tree.getArguments());
    String value = ASTHelpers.constValue(arg, String.class);
    boolean maybeRegex = false;
    if (value != null) {
        Optional<String> regexAsLiteral = convertRegexToLiteral(value);
        if (regexAsLiteral.isPresent()) {
            value = SourceCodeEscapers.javaCharEscaper().escape(regexAsLiteral.get());
            if (value.length() == 1) {
                value = String.format("'%s'", value.charAt(0));
            } else {
                value = String.format("\"%s\"", value);
            }
        } else {
            maybeRegex = true;
            value = state.getSourceForNode(arg);
        }
    } else {
        value = state.getSourceForNode(arg);
    }
    Tree parent = state.getPath().getParentPath().getLeaf();
    if (parent instanceof EnhancedForLoopTree && ((EnhancedForLoopTree) parent).getExpression().equals(tree)) {
        // fix for `for (... : s.split(...)) {}` -> `for (... : Splitter.on(...).split(s)) {}`
        return Optional.of(replaceWithSplitter(SuggestedFix.builder(), tree, value, state, "split", maybeRegex, /* mutableList= */
        false).build());
    }
    if (parent instanceof ArrayAccessTree) {
        ArrayAccessTree arrayAccessTree = (ArrayAccessTree) parent;
        if (!arrayAccessTree.getExpression().equals(tree)) {
            return Optional.empty();
        }
        SuggestedFix.Builder fix = SuggestedFix.builder().addImport("com.google.common.collect.Iterables").replace(((JCTree) arrayAccessTree).getStartPosition(), ((JCTree) arrayAccessTree).getStartPosition(), "Iterables.get(").replace(/* startPos= */
        state.getEndPosition(arrayAccessTree.getExpression()), /* endPos= */
        ((JCTree) arrayAccessTree.getIndex()).getStartPosition(), String.format(", ")).replace(state.getEndPosition(arrayAccessTree.getIndex()), state.getEndPosition(arrayAccessTree), ")");
        return Optional.of(replaceWithSplitter(fix, tree, value, state, "split", maybeRegex, /* mutableList= */
        false).build());
    }
    // enclosing method. If we don't know how to fix any of them, bail out.
    if (!(parent instanceof VariableTree)) {
        return Optional.empty();
    }
    VariableTree varTree = (VariableTree) parent;
    if (!varTree.getInitializer().equals(tree)) {
        return Optional.empty();
    }
    VarSymbol sym = ASTHelpers.getSymbol(varTree);
    TreePath enclosing = findEnclosing(state);
    if (enclosing == null) {
        return Optional.empty();
    }
    // find all uses of the variable in the enclosing method
    List<TreePath> uses = new ArrayList<>();
    new TreePathScanner<Void, Void>() {

        @Override
        public Void visitIdentifier(IdentifierTree tree, Void unused) {
            if (Objects.equals(sym, ASTHelpers.getSymbol(tree))) {
                uses.add(getCurrentPath());
            }
            return super.visitIdentifier(tree, null);
        }
    }.scan(enclosing, null);
    SuggestedFix.Builder fix = SuggestedFix.builder();
    // a mutable boolean to track whether we want split or splitToList
    boolean[] needsList = { false };
    boolean[] needsMutableList = { false };
    // try to fix all uses of the variable
    for (TreePath path : uses) {
        class UseFixer extends TreePathScanner<Boolean, Void> {

            @Override
            public Boolean visitEnhancedForLoop(EnhancedForLoopTree tree, Void unused) {
                // fix here.
                return sym.equals(ASTHelpers.getSymbol(tree.getExpression()));
            }

            @Override
            public Boolean visitArrayAccess(ArrayAccessTree tree, Void unused) {
                // replace `pieces[N]` with `pieces.get(N)`
                ExpressionTree expression = tree.getExpression();
                ExpressionTree index = tree.getIndex();
                if (!sym.equals(ASTHelpers.getSymbol(expression))) {
                    return false;
                }
                Tree parent = getCurrentPath().getParentPath().getLeaf();
                if (parent instanceof AssignmentTree && ((AssignmentTree) parent).getVariable() == tree) {
                    AssignmentTree assignmentTree = (AssignmentTree) parent;
                    fix.replace(/* startPos= */
                    state.getEndPosition(expression), /* endPos= */
                    ((JCTree) index).getStartPosition(), ".set(").replace(/* startPos= */
                    state.getEndPosition(index), /* endPos= */
                    ((JCTree) assignmentTree.getExpression()).getStartPosition(), ", ").postfixWith(assignmentTree, ")");
                    needsMutableList[0] = true;
                } else {
                    fix.replace(/* startPos= */
                    state.getEndPosition(expression), /* endPos= */
                    ((JCTree) index).getStartPosition(), ".get(").replace(state.getEndPosition(index), state.getEndPosition(tree), ")");
                }
                // we want a list for indexing
                needsList[0] = true;
                return true;
            }

            @Override
            public Boolean visitMemberSelect(MemberSelectTree tree, Void aVoid) {
                // replace `pieces.length` with `pieces.size`
                if (sym.equals(ASTHelpers.getSymbol(tree.getExpression())) && tree.getIdentifier().contentEquals("length")) {
                    fix.replace(state.getEndPosition(tree.getExpression()), state.getEndPosition(tree), ".size()");
                    needsList[0] = true;
                    return true;
                }
                return false;
            }
        }
        if (!firstNonNull(new UseFixer().scan(path.getParentPath(), null), false)) {
            return Optional.empty();
        }
    }
    if (needsList[0]) {
        fix.replace((varTree).getType(), "List<String>").addImport("java.util.List");
        replaceWithSplitter(fix, tree, value, state, "splitToList", maybeRegex, needsMutableList[0]);
    } else {
        fix.replace((varTree).getType(), "Iterable<String>");
        replaceWithSplitter(fix, tree, value, state, "split", maybeRegex, needsMutableList[0]);
    }
    return Optional.of(fix.build());
}
Also used : ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) VariableTree(com.sun.source.tree.VariableTree) ArrayList(java.util.ArrayList) JCTree(com.sun.tools.javac.tree.JCTree) IdentifierTree(com.sun.source.tree.IdentifierTree) TreePathScanner(com.sun.source.util.TreePathScanner) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) TreePath(com.sun.source.util.TreePath) ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) VariableTree(com.sun.source.tree.VariableTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) JCTree(com.sun.tools.javac.tree.JCTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ExpressionTree(com.sun.source.tree.ExpressionTree) AssignmentTree(com.sun.source.tree.AssignmentTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree)

Aggregations

IdentifierTree (com.sun.source.tree.IdentifierTree)82 ExpressionTree (com.sun.source.tree.ExpressionTree)41 MemberSelectTree (com.sun.source.tree.MemberSelectTree)36 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)28 Element (javax.lang.model.element.Element)24 Tree (com.sun.source.tree.Tree)21 ExecutableElement (javax.lang.model.element.ExecutableElement)18 VariableTree (com.sun.source.tree.VariableTree)17 TypeElement (javax.lang.model.element.TypeElement)16 MethodTree (com.sun.source.tree.MethodTree)13 VariableElement (javax.lang.model.element.VariableElement)13 ClassTree (com.sun.source.tree.ClassTree)12 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)11 ArrayAccessTree (com.sun.source.tree.ArrayAccessTree)10 NewClassTree (com.sun.source.tree.NewClassTree)10 AssignmentTree (com.sun.source.tree.AssignmentTree)9 BinaryTree (com.sun.source.tree.BinaryTree)9 LiteralTree (com.sun.source.tree.LiteralTree)8 StatementTree (com.sun.source.tree.StatementTree)8 Symbol (com.sun.tools.javac.code.Symbol)8