Search in sources :

Example 96 with JCTree

use of com.sun.tools.javac.tree.JCTree in project bazel by bazelbuild.

the class AnnotationProcessingPlugin method recordInfo.

private void recordInfo(JCCompilationUnit toplevel) {
    CompilationUnit.Builder builder = CompilationUnit.newBuilder();
    if (toplevel.sourcefile != null) {
        // FileObject#getName() returns the original exec root-relative path of
        // the source file, which is want we want.
        // Paths.get(sourcefile.toUri()) would absolutize the path.
        Path path = Paths.get(toplevel.sourcefile.getName());
        builder.setPath(processingModule.stripSourceRoot(path).toString());
        builder.setGeneratedByAnnotationProcessor(processingModule.isGenerated(path));
    }
    if (toplevel.getPackageName() != null) {
        builder.setPkg(toplevel.getPackageName().toString());
    }
    for (JCTree decl : toplevel.defs) {
        if (decl instanceof JCClassDecl) {
            builder.addTopLevel(((JCClassDecl) decl).getSimpleName().toString());
        }
    }
    processingModule.recordUnit(builder.build());
}
Also used : CompilationUnit(com.google.devtools.build.buildjar.proto.JavaCompilation.CompilationUnit) JCCompilationUnit(com.sun.tools.javac.tree.JCTree.JCCompilationUnit) Path(java.nio.file.Path) JCClassDecl(com.sun.tools.javac.tree.JCTree.JCClassDecl) JCTree(com.sun.tools.javac.tree.JCTree)

Example 97 with JCTree

use of com.sun.tools.javac.tree.JCTree in project error-prone by google.

the class BoxedPrimitiveConstructor method buildFix.

private Fix buildFix(NewClassTree tree, VisitorState state) {
    boolean autoboxFix = shouldAutoboxFix(state);
    Types types = state.getTypes();
    Type type = types.unboxedTypeOrType(getType(tree));
    if (types.isSameType(type, state.getSymtab().booleanType)) {
        Object value = literalValue(tree.getArguments().iterator().next());
        if (value instanceof Boolean) {
            return SuggestedFix.replace(tree, literalFix((boolean) value, autoboxFix));
        } else if (value instanceof String) {
            return SuggestedFix.replace(tree, literalFix(Boolean.parseBoolean((String) value), autoboxFix));
        }
    }
    // Primitive constructors are all unary
    JCTree.JCExpression arg = (JCTree.JCExpression) getOnlyElement(tree.getArguments());
    Type argType = getType(arg);
    if (autoboxFix && argType.isPrimitive()) {
        return SuggestedFix.builder().replace(((JCTree) tree).getStartPosition(), arg.getStartPosition(), maybeCast(state, type, argType)).replace(state.getEndPosition(arg), state.getEndPosition(tree), "").build();
    }
    JCTree parent = (JCTree) state.getPath().getParentPath().getParentPath().getLeaf();
    if (TO_STRING.matches(parent, state)) {
        // e.g. new Integer($A).toString() -> String.valueOf($A)
        return SuggestedFix.builder().replace(parent.getStartPosition(), arg.getStartPosition(), "String.valueOf(").replace(state.getEndPosition(arg), state.getEndPosition(parent), ")").build();
    }
    String typeName = state.getSourceForNode(tree.getIdentifier());
    if (HASH_CODE.matches(parent, state)) {
        // e.g. new Integer($A).hashCode() -> Integer.hashCode($A)
        SuggestedFix.Builder fix = SuggestedFix.builder();
        String replacement;
        if (types.isSameType(type, state.getSymtab().longType)) {
            // TODO(b/29979605): Long.hashCode was added in JDK8
            fix.addImport(Longs.class.getName());
            replacement = "Longs.hashCode(";
        } else {
            replacement = String.format("%s.hashCode(", typeName);
        }
        return fix.replace(parent.getStartPosition(), arg.getStartPosition(), replacement).replace(state.getEndPosition(arg), state.getEndPosition(parent), ")").build();
    }
    DoubleAndFloatStatus doubleAndFloatStatus = doubleAndFloatStatus(state, type, argType);
    if (COMPARE_TO.matches(parent, state) && ASTHelpers.getReceiver((ExpressionTree) parent).equals(tree)) {
        JCMethodInvocation compareTo = (JCMethodInvocation) parent;
        // e.g. new Integer($A).compareTo($B) -> Integer.compare($A, $B)
        JCTree.JCExpression rhs = getOnlyElement(compareTo.getArguments());
        String optionalCast = "";
        String optionalSuffix = "";
        switch(doubleAndFloatStatus) {
            case PRIMITIVE_DOUBLE_INTO_FLOAT:
                // new Float(double).compareTo($foo) => Float.compare((float) double, foo)
                optionalCast = "(float) ";
                break;
            case BOXED_DOUBLE_INTO_FLOAT:
                // new Float(Double).compareTo($foo) => Float.compare(Double.floatValue(), foo)
                optionalSuffix = ".floatValue()";
                break;
            default:
                break;
        }
        return SuggestedFix.builder().replace(compareTo.getStartPosition(), arg.getStartPosition(), String.format("%s.compare(%s", typeName, optionalCast)).replace(state.getEndPosition(arg), rhs.getStartPosition(), String.format("%s, ", optionalSuffix)).replace(state.getEndPosition(rhs), state.getEndPosition(compareTo), ")").build();
    }
    // Patch new Float(Double) => Float.valueOf(float) by downcasting the double, since
    // neither valueOf(float) nor valueOf(String) match.
    String prefixToArg;
    String suffix = "";
    switch(doubleAndFloatStatus) {
        case PRIMITIVE_DOUBLE_INTO_FLOAT:
            // new Float(double) => Float.valueOf((float) double)
            prefixToArg = String.format("%s.valueOf(%s", typeName, "(float) ");
            break;
        case BOXED_DOUBLE_INTO_FLOAT:
            // new Float(Double) => Double.floatValue()
            prefixToArg = "";
            suffix = ".floatValue(";
            break;
        default:
            prefixToArg = String.format("%s.valueOf(", typeName);
            break;
    }
    return SuggestedFix.builder().replace(((JCTree) tree).getStartPosition(), arg.getStartPosition(), prefixToArg).postfixWith(arg, suffix).build();
}
Also used : Types(com.sun.tools.javac.code.Types) JCTree(com.sun.tools.javac.tree.JCTree) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) Matchers.toType(com.google.errorprone.matchers.Matchers.toType) ASTHelpers.getType(com.google.errorprone.util.ASTHelpers.getType) ASTHelpers.isSameType(com.google.errorprone.util.ASTHelpers.isSameType) Type(com.sun.tools.javac.code.Type) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Longs(com.google.common.primitives.Longs)

Example 98 with JCTree

use of com.sun.tools.javac.tree.JCTree in project error-prone by google.

the class ClassNewInstance method fixExceptions.

// if the match occurrs inside the body of a try statement with existing catch clauses
// update or add a catch block to handle the new exceptions
private boolean fixExceptions(final VisitorState state, SuggestedFix.Builder fix) {
    TryTree tryTree = null;
    OUTER: for (TreePath path = state.getPath(); path != null; path = path.getParentPath()) {
        if (path.getLeaf() instanceof CatchTree) {
            // don't add more catch blocks if newInstance() was called in a catch block
            return false;
        } else if (path.getLeaf() instanceof TryTree && !((TryTree) path.getLeaf()).getCatches().isEmpty()) {
            tryTree = (TryTree) path.getLeaf();
            break;
        }
    }
    if (tryTree == null) {
        return false;
    }
    ImmutableMap.Builder<Type, CatchTree> catches = ImmutableMap.builder();
    for (CatchTree c : tryTree.getCatches()) {
        catches.put(ASTHelpers.getType(c.getParameter().getType()), c);
    }
    UnhandledResult<CatchTree> result = unhandled(catches.build(), state);
    if (result.unhandled.isEmpty()) {
        // no fix needed
        return true;
    }
    {
        // if there's an existing multi-catch at the end that handles reflective exceptions,
        // replace all of them with ROE and leave any non-reflective exceptions.
        // earlier catch blocks are left unchanged.
        CatchTree last = Iterables.getLast(tryTree.getCatches());
        Tree lastType = last.getParameter().getType();
        if (lastType.getKind() == Tree.Kind.UNION_TYPE) {
            Type roe = state.getTypeFromString(ReflectiveOperationException.class.getName());
            Set<String> exceptions = new LinkedHashSet<>();
            boolean foundReflective = false;
            for (Tree alternate : ((UnionTypeTree) lastType).getTypeAlternatives()) {
                if (ASTHelpers.isSubtype(ASTHelpers.getType(alternate), roe, state)) {
                    foundReflective = true;
                    exceptions.add("ReflectiveOperationException");
                } else {
                    exceptions.add(state.getSourceForNode(alternate));
                }
            }
            if (foundReflective) {
                fix.replace(lastType, Joiner.on(" | ").join(exceptions));
                return true;
            }
        }
    }
    // check for duplicated catch blocks that handle reflective exceptions exactly the same way,
    // and merge them into a single block that catches ROE
    Set<String> uniq = new HashSet<>();
    for (CatchTree ct : result.handles.values()) {
        uniq.add(state.getSourceForNode(ct.getBlock()));
    }
    // the catch blocks are all unique, append a new fresh one
    if (uniq.size() != 1) {
        CatchTree last = Iterables.getLast(tryTree.getCatches());
        // borrow the variable name of the previous catch variable, in case the naive 'e' conflicts
        // with something in the current scope
        String name = last.getParameter().getName().toString();
        fix.postfixWith(last, String.format("catch (ReflectiveOperationException %s) {" + " throw new LinkageError(%s.getMessage(), %s); }", name, name, name));
        return true;
    }
    // if the catch blocks contain calls to newInstance, don't delete any of them to avoid
    // overlapping fixes
    final AtomicBoolean newInstanceInCatch = new AtomicBoolean(false);
    ((JCTree) result.handles.values().iterator().next()).accept(new TreeScanner() {

        @Override
        public void visitApply(JCTree.JCMethodInvocation tree) {
            if (NEW_INSTANCE.matches(tree, state)) {
                newInstanceInCatch.set(true);
            }
        }
    });
    if (newInstanceInCatch.get()) {
        fix.replace(Iterables.getLast(result.handles.values()).getParameter().getType(), "ReflectiveOperationException");
        return true;
    }
    // otherwise, merge the duplicated catch blocks into a single block that
    // handles ROE
    boolean first = true;
    for (CatchTree ct : result.handles.values()) {
        if (first) {
            fix.replace(ct.getParameter().getType(), "ReflectiveOperationException");
            first = false;
        } else {
            fix.delete(ct);
        }
    }
    return true;
}
Also used : HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) CatchTree(com.sun.source.tree.CatchTree) JCTree(com.sun.tools.javac.tree.JCTree) ImmutableMap(com.google.common.collect.ImmutableMap) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Type(com.sun.tools.javac.code.Type) TreePath(com.sun.source.util.TreePath) TreeScanner(com.sun.tools.javac.tree.TreeScanner) MethodTree(com.sun.source.tree.MethodTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) CatchTree(com.sun.source.tree.CatchTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) JCTree(com.sun.tools.javac.tree.JCTree) TryTree(com.sun.source.tree.TryTree) UnionTypeTree(com.sun.source.tree.UnionTypeTree) TryTree(com.sun.source.tree.TryTree) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 99 with JCTree

use of com.sun.tools.javac.tree.JCTree in project error-prone by google.

the class ComparisonOutOfRange method describe.

/**
   * Suggested fixes are as follows.  For the byte case, convert the literal to its byte
   * representation. For example, "255" becomes "-1.  For the character case, replace the
   * comparison with "true"/"false" since it's not clear what was intended and that is
   * semantically equivalent.
   *
   * TODO(eaftan): Suggested fixes don't handle side-effecting expressions, such as
   * (d = reader.read()) == -1.  Maybe add special case handling for assignments.
   */
public Description describe(BinaryTree tree, VisitorState state) {
    List<ExpressionTree> binaryTreeMatches = ASTHelpers.matchBinaryTree(tree, Arrays.asList(Matchers.<ExpressionTree>isInstance(JCLiteral.class), Matchers.<ExpressionTree>anything()), state);
    if (binaryTreeMatches == null) {
        throw new IllegalStateException("Expected one of the operands to be a literal");
    }
    JCLiteral literal = (JCLiteral) binaryTreeMatches.get(0);
    JCTree nonLiteralOperand = (JCTree) binaryTreeMatches.get(1);
    boolean byteMatch = state.getTypes().isSameType(nonLiteralOperand.type, state.getSymtab().byteType);
    boolean willEvaluateTo = (tree.getKind() != Kind.EQUAL_TO);
    Fix fix;
    String customDiagnosticMessage;
    if (byteMatch) {
        String replacement = Byte.toString(((Number) literal.getValue()).byteValue());
        // Correct for poor javac 6 literal parsing.
        int actualStart = ASTHelpers.getActualStartPosition(literal, state.getSourceCode());
        if (actualStart != literal.getStartPosition()) {
            fix = SuggestedFix.replace(literal, replacement, actualStart - literal.getStartPosition(), 0);
        } else {
            fix = SuggestedFix.replace(literal, replacement);
        }
        customDiagnosticMessage = String.format(MESSAGE_TEMPLATE, "byte", (int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, literal.toString(), Boolean.toString(willEvaluateTo));
    } else {
        fix = SuggestedFix.replace(tree, Boolean.toString(willEvaluateTo));
        customDiagnosticMessage = String.format(MESSAGE_TEMPLATE, "char", (int) Character.MIN_VALUE, (int) Character.MAX_VALUE, literal.toString(), Boolean.toString(willEvaluateTo));
    }
    return buildDescription(tree).addFix(fix).setMessage(customDiagnosticMessage).build();
}
Also used : SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Fix(com.google.errorprone.fixes.Fix) ExpressionTree(com.sun.source.tree.ExpressionTree) JCLiteral(com.sun.tools.javac.tree.JCTree.JCLiteral) JCTree(com.sun.tools.javac.tree.JCTree)

Example 100 with JCTree

use of com.sun.tools.javac.tree.JCTree in project error-prone by google.

the class InfiniteRecursion method matchMethod.

@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
    if (tree.getBody() == null || tree.getBody().getStatements().size() != 1) {
        return NO_MATCH;
    }
    Tree statement = TreeInfo.skipParens((JCTree) Iterables.getOnlyElement(tree.getBody().getStatements()));
    ExpressionTree expr = statement.accept(new SimpleTreeVisitor<ExpressionTree, Void>() {

        @Override
        public ExpressionTree visitExpressionStatement(ExpressionStatementTree tree, Void unused) {
            return tree.getExpression();
        }

        @Override
        public ExpressionTree visitReturn(ReturnTree tree, Void unused) {
            return tree.getExpression();
        }
    }, null);
    if (!(expr instanceof MethodInvocationTree)) {
        return NO_MATCH;
    }
    ExpressionTree select = ((MethodInvocationTree) expr).getMethodSelect();
    switch(select.getKind()) {
        case IDENTIFIER:
            break;
        case MEMBER_SELECT:
            ExpressionTree receiver = ((MemberSelectTree) select).getExpression();
            if (receiver.getKind() != Kind.IDENTIFIER) {
                return NO_MATCH;
            }
            if (!((IdentifierTree) receiver).getName().contentEquals("this")) {
                return NO_MATCH;
            }
            break;
        default:
            return NO_MATCH;
    }
    MethodSymbol sym = ASTHelpers.getSymbol(tree);
    if (sym == null || !sym.equals(ASTHelpers.getSymbol(expr))) {
        return NO_MATCH;
    }
    return describeMatch(statement);
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ReturnTree(com.sun.source.tree.ReturnTree) MethodTree(com.sun.source.tree.MethodTree) 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) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) IdentifierTree(com.sun.source.tree.IdentifierTree) ReturnTree(com.sun.source.tree.ReturnTree)

Aggregations

JCTree (com.sun.tools.javac.tree.JCTree)183 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)28 Symbol (com.sun.tools.javac.code.Symbol)22 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)22 Type (com.sun.tools.javac.code.Type)19 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)17 Tree (com.sun.source.tree.Tree)15 ExpressionTree (com.sun.source.tree.ExpressionTree)14 JCFieldAccess (com.sun.tools.javac.tree.JCTree.JCFieldAccess)14 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)11 JCClassDecl (com.sun.tools.javac.tree.JCTree.JCClassDecl)11 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)10 ArrayList (java.util.ArrayList)10 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)9 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)9 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)8 ListBuffer (com.sun.tools.javac.util.ListBuffer)8 Type (com.redhat.ceylon.model.typechecker.model.Type)7 ClassTree (com.sun.source.tree.ClassTree)7 MemberSelectTree (com.sun.source.tree.MemberSelectTree)7