Search in sources :

Example 16 with AssignmentTree

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

the class BaseTypeVisitor method isAccessAllowed.

protected boolean isAccessAllowed(Element field, AnnotatedTypeMirror receiver, ExpressionTree accessTree) {
    AnnotationMirror unused = atypeFactory.getDeclAnnotation(field, Unused.class);
    if (unused == null) {
        return true;
    }
    String when = AnnotationUtils.getElementValueClassName(unused, "when", false).toString();
    if (!AnnotationUtils.containsSameByName(receiver.getAnnotations(), when)) {
        return true;
    }
    Tree tree = this.enclosingStatement(accessTree);
    // assigning unused to null is OK
    return (tree != null && tree.getKind() == Tree.Kind.ASSIGNMENT && ((AssignmentTree) tree).getVariable() == accessTree && ((AssignmentTree) tree).getExpression().getKind() == Tree.Kind.NULL_LITERAL);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) TypeCastTree(com.sun.source.tree.TypeCastTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) InstanceOfTree(com.sun.source.tree.InstanceOfTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ThrowTree(com.sun.source.tree.ThrowTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ReturnTree(com.sun.source.tree.ReturnTree) 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) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) NewArrayTree(com.sun.source.tree.NewArrayTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) AnnotationTree(com.sun.source.tree.AnnotationTree) MethodTree(com.sun.source.tree.MethodTree) ClassTree(com.sun.source.tree.ClassTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) JCTree(com.sun.tools.javac.tree.JCTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) AssignmentTree(com.sun.source.tree.AssignmentTree)

Example 17 with AssignmentTree

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

Example 18 with AssignmentTree

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

the class SelfAssignment method describeForAssignment.

/**
 * We expect that the lhs is a field and the rhs is an identifier, specifically a parameter to the
 * method. We base our suggested fixes on this expectation.
 *
 * <p>Case 1: If lhs is a field and rhs is an identifier, find a method parameter of the same type
 * and similar name and suggest it as the rhs. (Guess that they have misspelled the identifier.)
 *
 * <p>Case 2: If lhs is a field and rhs is not an identifier, find a method parameter of the same
 * type and similar name and suggest it as the rhs.
 *
 * <p>Case 3: If lhs is not a field and rhs is an identifier, find a class field of the same type
 * and similar name and suggest it as the lhs.
 *
 * <p>Case 4: Otherwise suggest deleting the assignment.
 */
public Description describeForAssignment(AssignmentTree assignmentTree, VisitorState state) {
    // the statement that is the parent of the self-assignment expression
    Tree parent = state.getPath().getParentPath().getLeaf();
    // default fix is to delete assignment
    Fix fix = SuggestedFix.delete(parent);
    ExpressionTree lhs = assignmentTree.getVariable();
    ExpressionTree rhs = assignmentTree.getExpression();
    // if this is a method invocation, they must be calling checkNotNull()
    if (assignmentTree.getExpression().getKind() == METHOD_INVOCATION) {
        // change the default fix to be "checkNotNull(x)" instead of "x = checkNotNull(x)"
        fix = SuggestedFix.replace(assignmentTree, rhs.toString());
        // new rhs is first argument to checkNotNull()
        rhs = stripNullCheck(rhs, state);
    }
    ImmutableList<Fix> exploratoryFieldFixes = ImmutableList.of();
    if (lhs.getKind() == MEMBER_SELECT) {
        // find a method parameter of the same type and similar name and suggest it
        // as the rhs
        // rhs should be either identifier or field access
        Preconditions.checkState(rhs.getKind() == IDENTIFIER || rhs.getKind() == MEMBER_SELECT);
        Type rhsType = ASTHelpers.getType(rhs);
        exploratoryFieldFixes = ReplacementVariableFinder.fixesByReplacingExpressionWithMethodParameter(rhs, varDecl -> ASTHelpers.isSameType(rhsType, varDecl.type, state), state);
    } else if (rhs.getKind() == IDENTIFIER) {
        // find a field of the same type and similar name and suggest it as the lhs
        // lhs should be identifier
        Preconditions.checkState(lhs.getKind() == IDENTIFIER);
        Type lhsType = ASTHelpers.getType(lhs);
        exploratoryFieldFixes = ReplacementVariableFinder.fixesByReplacingExpressionWithLocallyDeclaredField(lhs, var -> !Flags.isStatic(var.sym) && (var.sym.flags() & Flags.FINAL) == 0 && ASTHelpers.isSameType(lhsType, var.type, state), state);
    }
    if (exploratoryFieldFixes.isEmpty()) {
        return describeMatch(assignmentTree, fix);
    }
    return buildDescription(assignmentTree).addAllFixes(exploratoryFieldFixes).build();
}
Also used : Matchers.anyOf(com.google.errorprone.matchers.Matchers.anyOf) VariableTree(com.sun.source.tree.VariableTree) IDENTIFIER(com.sun.source.tree.Tree.Kind.IDENTIFIER) VisitorState(com.google.errorprone.VisitorState) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) ImmutableList(com.google.common.collect.ImmutableList) BugPattern(com.google.errorprone.BugPattern) JDK(com.google.errorprone.BugPattern.Category.JDK) Matcher(com.google.errorprone.matchers.Matcher) Fix(com.google.errorprone.fixes.Fix) Tree(com.sun.source.tree.Tree) Matchers.staticMethod(com.google.errorprone.matchers.Matchers.staticMethod) AssignmentTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.AssignmentTreeMatcher) ERROR(com.google.errorprone.BugPattern.SeverityLevel.ERROR) MEMBER_SELECT(com.sun.source.tree.Tree.Kind.MEMBER_SELECT) ExpressionTree(com.sun.source.tree.ExpressionTree) METHOD_INVOCATION(com.sun.source.tree.Tree.Kind.METHOD_INVOCATION) Symbol(com.sun.tools.javac.code.Symbol) MemberSelectTree(com.sun.source.tree.MemberSelectTree) CLASS(com.sun.source.tree.Tree.Kind.CLASS) VariableTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher) STATIC(javax.lang.model.element.Modifier.STATIC) Description(com.google.errorprone.matchers.Description) Preconditions(com.google.common.base.Preconditions) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Flags(com.sun.tools.javac.code.Flags) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) Type(com.sun.tools.javac.code.Type) Fix(com.google.errorprone.fixes.Fix) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) VariableTree(com.sun.source.tree.VariableTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ExpressionTree(com.sun.source.tree.ExpressionTree)

Example 19 with AssignmentTree

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

the class ConstructorLeaksThis method traverse.

@Override
protected void traverse(Tree tree, VisitorState state) {
    ClassSymbol thisClass = ASTHelpers.getSymbol(state.findEnclosing(ClassTree.class));
    tree.accept(new TreeScanner<Void, Void>() {

        @Override
        public Void visitIdentifier(IdentifierTree node, Void unused) {
            checkForThis(node, node.getName(), thisClass, state);
            return super.visitIdentifier(node, null);
        }

        @Override
        public Void visitMemberSelect(MemberSelectTree node, Void unused) {
            checkForThis(node, node.getIdentifier(), thisClass, state);
            // Don't examine this.foo or MyClass.this.foo
            ExpressionTree left = node.getExpression();
            if ((left instanceof IdentifierTree && ((IdentifierTree) left).getName().contentEquals("this")) || (left instanceof MemberSelectTree && ((MemberSelectTree) left).getIdentifier().contentEquals("this"))) {
                return null;
            }
            return super.visitMemberSelect(node, unused);
        }

        @Override
        public Void visitAssignment(AssignmentTree node, Void unused) {
            scan(node.getExpression(), null);
            // ignore references to 'this' in the LHS of assignments
            return null;
        }
    }, null);
}
Also used : ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ClassTree(com.sun.source.tree.ClassTree) IdentifierTree(com.sun.source.tree.IdentifierTree) ExpressionTree(com.sun.source.tree.ExpressionTree) AssignmentTree(com.sun.source.tree.AssignmentTree)

Example 20 with AssignmentTree

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

the class TreeConverter method convertAnnotation.

private TreeNode convertAnnotation(AnnotationTree node, TreePath parent) {
    List<? extends ExpressionTree> args = node.getArguments();
    String annotationName = node.getAnnotationType().toString();
    AnnotationMirror annotationMirror = ((JCAnnotation) node).attribute;
    boolean isPropertyAnnotation = annotationName.equals(Property.class.getSimpleName()) || annotationName.equals(Property.class.getName());
    Annotation newNode;
    TreePath path = getTreePath(parent, node);
    if (isPropertyAnnotation) {
        newNode = new PropertyAnnotation().setAnnotationMirror(annotationMirror);
        if (!args.isEmpty()) {
            for (String attr : ElementUtil.parsePropertyAttribute(annotationMirror)) {
                ((PropertyAnnotation) newNode).addAttribute(attr);
            }
        }
    } else if (args.isEmpty()) {
        newNode = new MarkerAnnotation().setAnnotationMirror(annotationMirror);
    } else if (args.size() == 1) {
        AssignmentTree assign = (AssignmentTree) args.get(0);
        ExpressionTree expression = assign.getExpression();
        newNode = new SingleMemberAnnotation().setValue((Expression) convert(expression, getTreePath(path, assign)));
    } else {
        NormalAnnotation normalAnn = new NormalAnnotation();
        for (ExpressionTree obj : node.getArguments()) {
            AssignmentTree assign = (AssignmentTree) obj;
            ExpressionTree variable = assign.getVariable();
            ExpressionTree expression = assign.getExpression();
            TreePath assignPath = getTreePath(path, assign);
            TreePath variablePath = getTreePath(assignPath, variable);
            SimpleName name = convertSimpleName(getElement(variablePath), getTypeMirror(variablePath), getPosition(variable));
            MemberValuePair memberPair = new MemberValuePair().setName(name).setValue((Expression) convert(expression, assignPath));
            normalAnn.addValue(memberPair);
        }
        newNode = normalAnn;
    }
    return newNode.setAnnotationMirror(annotationMirror).setTypeName((Name) convert(node.getAnnotationType(), path));
}
Also used : SingleMemberAnnotation(com.google.devtools.j2objc.ast.SingleMemberAnnotation) SimpleName(com.google.devtools.j2objc.ast.SimpleName) NormalAnnotation(com.google.devtools.j2objc.ast.NormalAnnotation) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) PropertyAnnotation(com.google.devtools.j2objc.ast.PropertyAnnotation) Annotation(com.google.devtools.j2objc.ast.Annotation) SingleMemberAnnotation(com.google.devtools.j2objc.ast.SingleMemberAnnotation) MarkerAnnotation(com.google.devtools.j2objc.ast.MarkerAnnotation) PropertyAnnotation(com.google.devtools.j2objc.ast.PropertyAnnotation) AnnotationMirror(javax.lang.model.element.AnnotationMirror) MarkerAnnotation(com.google.devtools.j2objc.ast.MarkerAnnotation) TreePath(com.sun.source.util.TreePath) MemberValuePair(com.google.devtools.j2objc.ast.MemberValuePair) PostfixExpression(com.google.devtools.j2objc.ast.PostfixExpression) InstanceofExpression(com.google.devtools.j2objc.ast.InstanceofExpression) Expression(com.google.devtools.j2objc.ast.Expression) ConditionalExpression(com.google.devtools.j2objc.ast.ConditionalExpression) InfixExpression(com.google.devtools.j2objc.ast.InfixExpression) ParenthesizedExpression(com.google.devtools.j2objc.ast.ParenthesizedExpression) JCFunctionalExpression(com.sun.tools.javac.tree.JCTree.JCFunctionalExpression) LambdaExpression(com.google.devtools.j2objc.ast.LambdaExpression) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) PrefixExpression(com.google.devtools.j2objc.ast.PrefixExpression) ThisExpression(com.google.devtools.j2objc.ast.ThisExpression) FunctionalExpression(com.google.devtools.j2objc.ast.FunctionalExpression) CastExpression(com.google.devtools.j2objc.ast.CastExpression) VariableDeclarationExpression(com.google.devtools.j2objc.ast.VariableDeclarationExpression) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) NormalAnnotation(com.google.devtools.j2objc.ast.NormalAnnotation) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) AssignmentTree(com.sun.source.tree.AssignmentTree) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation)

Aggregations

AssignmentTree (com.sun.source.tree.AssignmentTree)20 ExpressionTree (com.sun.source.tree.ExpressionTree)20 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)13 Tree (com.sun.source.tree.Tree)13 VariableTree (com.sun.source.tree.VariableTree)13 NewClassTree (com.sun.source.tree.NewClassTree)12 MemberSelectTree (com.sun.source.tree.MemberSelectTree)11 IdentifierTree (com.sun.source.tree.IdentifierTree)10 JCTree (com.sun.tools.javac.tree.JCTree)10 ClassTree (com.sun.source.tree.ClassTree)9 CompoundAssignmentTree (com.sun.source.tree.CompoundAssignmentTree)9 MethodTree (com.sun.source.tree.MethodTree)9 NewArrayTree (com.sun.source.tree.NewArrayTree)9 ReturnTree (com.sun.source.tree.ReturnTree)9 ArrayAccessTree (com.sun.source.tree.ArrayAccessTree)7 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)7 ParameterizedTypeTree (com.sun.source.tree.ParameterizedTypeTree)7 TypeCastTree (com.sun.source.tree.TypeCastTree)7 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)6 ArrayList (java.util.ArrayList)6