Search in sources :

Example 21 with IdentifierTree

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

the class FindIdentifiers method createFindIdentifiersScanner.

/**
 * Finds all identifiers in a tree. Takes an optional stop point as its argument: the depth-first
 * walk will stop if this node is encountered.
 */
private static final TreeScanner<Void, Void> createFindIdentifiersScanner(ImmutableSet.Builder<Symbol> builder, @Nullable Tree stoppingPoint) {
    return new TreeScanner<Void, Void>() {

        @Override
        public Void scan(Tree tree, Void unused) {
            return Objects.equals(stoppingPoint, tree) ? null : super.scan(tree, unused);
        }

        @Override
        public Void scan(Iterable<? extends Tree> iterable, Void unused) {
            if (stoppingPoint != null && iterable != null) {
                ImmutableList.Builder<Tree> builder = ImmutableList.builder();
                for (Tree t : iterable) {
                    if (stoppingPoint.equals(t)) {
                        break;
                    }
                    builder.add(t);
                }
                iterable = builder.build();
            }
            return super.scan(iterable, unused);
        }

        @Override
        public Void visitIdentifier(IdentifierTree identifierTree, Void unused) {
            Symbol symbol = ASTHelpers.getSymbol(identifierTree);
            if (symbol != null) {
                builder.add(symbol);
            }
            return null;
        }
    };
}
Also used : TreeScanner(com.sun.source.util.TreeScanner) 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) 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) IdentifierTree(com.sun.source.tree.IdentifierTree)

Example 22 with IdentifierTree

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

the class StringLiteralTest method notMatches.

@Test
public void notMatches() {
    // TODO(b/67738557): consolidate helpers for creating fake trees
    LiteralTree tree = new LiteralTree() {

        @Override
        public Kind getKind() {
            throw new UnsupportedOperationException();
        }

        @Override
        public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
            throw new UnsupportedOperationException();
        }

        @Override
        public Object getValue() {
            return "a string literal";
        }
    };
    assertFalse(new StringLiteral("different string").matches(tree, null));
    IdentifierTree idTree = new IdentifierTree() {

        @Override
        public Name getName() {
            return null;
        }

        @Override
        public Kind getKind() {
            throw new UnsupportedOperationException();
        }

        @Override
        public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
            throw new UnsupportedOperationException();
        }
    };
    assertFalse(new StringLiteral("test").matches(idTree, null));
    // TODO(b/67738557): consolidate helpers for creating fake trees
    LiteralTree intTree = new LiteralTree() {

        @Override
        public Object getValue() {
            return 5;
        }

        @Override
        public Kind getKind() {
            throw new UnsupportedOperationException();
        }

        @Override
        public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
            throw new UnsupportedOperationException();
        }
    };
    assertFalse(new StringLiteral("test").matches(intTree, null));
}
Also used : TreeVisitor(com.sun.source.tree.TreeVisitor) IdentifierTree(com.sun.source.tree.IdentifierTree) LiteralTree(com.sun.source.tree.LiteralTree) Test(org.junit.Test)

Example 23 with IdentifierTree

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

the class WildcardImport method qualifiedNameFix.

/**
 * Add an import for {@code owner}, and qualify all on demand imported references to members of
 * owner by owner's simple name.
 */
private static void qualifiedNameFix(final SuggestedFix.Builder fix, final Symbol owner, VisitorState state) {
    fix.addImport(owner.getQualifiedName().toString());
    final JCCompilationUnit unit = (JCCompilationUnit) state.getPath().getCompilationUnit();
    new TreePathScanner<Void, Void>() {

        @Override
        public Void visitIdentifier(IdentifierTree tree, Void unused) {
            Symbol sym = ASTHelpers.getSymbol(tree);
            if (sym == null) {
                return null;
            }
            Tree parent = getCurrentPath().getParentPath().getLeaf();
            if (parent.getKind() == Tree.Kind.CASE && ((CaseTree) parent).getExpression().equals(tree) && sym.owner.getKind() == ElementKind.ENUM) {
                // switch cases can refer to enum constants by simple name without importing them
                return null;
            }
            if (sym.owner.equals(owner) && unit.starImportScope.includes(sym)) {
                fix.prefixWith(tree, owner.getSimpleName() + ".");
            }
            return null;
        }
    }.scan(unit, null);
}
Also used : JCCompilationUnit(com.sun.tools.javac.tree.JCTree.JCCompilationUnit) CaseTree(com.sun.source.tree.CaseTree) Symbol(com.sun.tools.javac.code.Symbol) IdentifierTree(com.sun.source.tree.IdentifierTree) IdentifierTree(com.sun.source.tree.IdentifierTree) ImportTree(com.sun.source.tree.ImportTree) Tree(com.sun.source.tree.Tree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) CaseTree(com.sun.source.tree.CaseTree) JCTree(com.sun.tools.javac.tree.JCTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree)

Example 24 with IdentifierTree

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

the class Parameter method getArgumentName.

/**
 * Extract the name from an argument.
 *
 * <p>
 *
 * <ul>
 *   <li>IdentifierTree - if the identifier is 'this' then use the name of the enclosing class,
 *       otherwise use the name of the identifier
 *   <li>MemberSelectTree - the name of its identifier
 *   <li>NewClassTree - the name of the class being constructed
 *   <li>Null literal - a wildcard name
 *   <li>MethodInvocationTree - use the method name stripping off 'get', 'set', 'is' prefix. If
 *       this results in an empty name then recursively search the receiver
 * </ul>
 *
 * All other trees (including literals other than Null literal) do not have a name and this method
 * will return the marker for an unknown name.
 */
@VisibleForTesting
static String getArgumentName(ExpressionTree expressionTree) {
    switch(expressionTree.getKind()) {
        case MEMBER_SELECT:
            return ((MemberSelectTree) expressionTree).getIdentifier().toString();
        case NULL_LITERAL:
            // null could match anything pretty well
            return NAME_NULL;
        case IDENTIFIER:
            IdentifierTree idTree = (IdentifierTree) expressionTree;
            if (idTree.getName().contentEquals("this")) {
                // for the 'this' keyword the argument name is the name of the object's class
                Symbol sym = ASTHelpers.getSymbol(idTree);
                return sym != null ? getClassName(ASTHelpers.enclosingClass(sym)) : NAME_NOT_PRESENT;
            } else {
                // if we have a variable, just extract its name
                return idTree.getName().toString();
            }
        case METHOD_INVOCATION:
            MethodInvocationTree methodInvocationTree = (MethodInvocationTree) expressionTree;
            MethodSymbol methodSym = ASTHelpers.getSymbol(methodInvocationTree);
            if (methodSym != null) {
                String name = methodSym.getSimpleName().toString();
                List<String> terms = NamingConventions.splitToLowercaseTerms(name);
                String firstTerm = Iterables.getFirst(terms, null);
                if (METHODNAME_PREFIXES_TO_REMOVE.contains(firstTerm)) {
                    if (terms.size() == 1) {
                        ExpressionTree receiver = ASTHelpers.getReceiver(methodInvocationTree);
                        if (receiver == null) {
                            return getClassName(ASTHelpers.enclosingClass(methodSym));
                        }
                        // recursively try to get a name from the receiver
                        return getArgumentName(receiver);
                    } else {
                        return name.substring(firstTerm.length());
                    }
                } else {
                    return name;
                }
            } else {
                return NAME_NOT_PRESENT;
            }
        case NEW_CLASS:
            MethodSymbol constructorSym = ASTHelpers.getSymbol((NewClassTree) expressionTree);
            return constructorSym != null && constructorSym.owner != null ? getClassName((ClassSymbol) constructorSym.owner) : NAME_NOT_PRESENT;
        default:
            return NAME_NOT_PRESENT;
    }
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) Symbol(com.sun.tools.javac.code.Symbol) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) IdentifierTree(com.sun.source.tree.IdentifierTree) ExpressionTree(com.sun.source.tree.ExpressionTree) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 25 with IdentifierTree

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

the class InconsistentCapitalization method matchClass.

@Override
public Description matchClass(ClassTree tree, VisitorState state) {
    ImmutableSet<Symbol> fields = FieldScanner.findFields(tree);
    if (fields.isEmpty()) {
        return Description.NO_MATCH;
    }
    ImmutableMap<String, Symbol> fieldNamesMap = fields.stream().collect(toImmutableMap(symbol -> symbol.toString().toLowerCase(), identity()));
    ImmutableMap<TreePath, Symbol> matchedParameters = MatchingParametersScanner.findMatchingParameters(fieldNamesMap, state.getPath());
    if (matchedParameters.isEmpty()) {
        return Description.NO_MATCH;
    }
    for (Entry<TreePath, Symbol> entry : matchedParameters.entrySet()) {
        TreePath parameterPath = entry.getKey();
        Symbol field = entry.getValue();
        String fieldName = field.getSimpleName().toString();
        VariableTree parameterTree = (VariableTree) parameterPath.getLeaf();
        SuggestedFix.Builder fix = SuggestedFix.builder().merge(SuggestedFixes.renameVariable(parameterTree, fieldName, state));
        if (parameterPath.getParentPath() != null) {
            String qualifiedName = getExplicitQualification(parameterPath, tree, state) + field.getSimpleName();
            // If the field was accessed in a non-qualified way, by renaming the parameter this may
            // cause clashes with it. Thus, it is required to qualify all uses of the field within the
            // parameter's scope just in case.
            parameterPath.getParentPath().getLeaf().accept(new TreeScanner<Void, Void>() {

                @Override
                public Void visitIdentifier(IdentifierTree tree, Void unused) {
                    if (field.equals(ASTHelpers.getSymbol(tree))) {
                        fix.replace(tree, qualifiedName);
                    }
                    return null;
                }
            }, null);
        }
        state.reportMatch(buildDescription(parameterPath.getLeaf()).setMessage(String.format("Found the field '%s' with the same name as the parameter '%s' but with " + "different capitalization.", fieldName, ((VariableTree) parameterPath.getLeaf()).getName())).addFix(fix.build()).build());
    }
    return Description.NO_MATCH;
}
Also used : SuggestedFixes(com.google.errorprone.fixes.SuggestedFixes) TreePath(com.sun.source.util.TreePath) ImmutableSet(com.google.common.collect.ImmutableSet) ElementKind(javax.lang.model.element.ElementKind) ImmutableMap(com.google.common.collect.ImmutableMap) ClassTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher) Symbol(com.sun.tools.javac.code.Symbol) VariableTree(com.sun.source.tree.VariableTree) TreeScanner(com.sun.source.util.TreeScanner) VisitorState(com.google.errorprone.VisitorState) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Description(com.google.errorprone.matchers.Description) IdentifierTree(com.sun.source.tree.IdentifierTree) Function.identity(java.util.function.Function.identity) Entry(java.util.Map.Entry) BugPattern(com.google.errorprone.BugPattern) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) JDK(com.google.errorprone.BugPattern.Category.JDK) TreePathScanner(com.sun.source.util.TreePathScanner) Tree(com.sun.source.tree.Tree) ASTHelpers(com.google.errorprone.util.ASTHelpers) ClassTree(com.sun.source.tree.ClassTree) Symbol(com.sun.tools.javac.code.Symbol) VariableTree(com.sun.source.tree.VariableTree) IdentifierTree(com.sun.source.tree.IdentifierTree) TreePath(com.sun.source.util.TreePath) SuggestedFix(com.google.errorprone.fixes.SuggestedFix)

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