Search in sources :

Example 36 with Types

use of com.sun.tools.javac.code.Types 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());
    DoubleAndFloatStatus doubleAndFloatStatus = doubleAndFloatStatus(state, type, argType);
    if (HASH_CODE.matches(parent, state)) {
        // e.g. new Integer($A).hashCode() -> Integer.hashCode($A)
        SuggestedFix.Builder fix = SuggestedFix.builder();
        String replacement;
        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;
        }
        // in Java 7, those don't exist, so we suggest Guava
        if (shouldUseGuavaHashCode(state.context)) {
            fix.addImport("com.google.common.primitives." + typeName + "s");
            replacement = String.format("%ss.hashCode(", typeName);
        } else {
            replacement = String.format("%s.hashCode(", typeName);
        }
        return fix.replace(parent.getStartPosition(), arg.getStartPosition(), replacement + optionalCast).replace(state.getEndPosition(arg), state.getEndPosition(parent), optionalSuffix + ")").build();
    }
    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(/* startPos= */
        state.getEndPosition(arg), /* endPos= */
        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)

Example 37 with Types

use of com.sun.tools.javac.code.Types in project error-prone by google.

the class CatchFail method deleteFix.

// Extract the argument to a call to assertWithMessage, e.g. in:
// assertWithMessage("message").fail();
Optional<Fix> deleteFix(TryTree tree, ImmutableList<CatchTree> catchBlocks, VisitorState state) {
    SuggestedFix.Builder fix = SuggestedFix.builder();
    if (tree.getFinallyBlock() != null || catchBlocks.size() < tree.getCatches().size()) {
        // If the try statement has a finally region, or other catch blocks, delete only the
        // unnecessary blocks.
        catchBlocks.stream().forEachOrdered(fix::delete);
    } else {
        // The try statement has no finally region and all catch blocks are unnecessary. Replace it
        // with the try statements, deleting all catches.
        List<? extends StatementTree> tryStatements = tree.getBlock().getStatements();
        String source = state.getSourceCode().toString();
        // Replace the full region to work around a GJF partial formatting bug that prevents it from
        // re-indenting unchanged lines. This means that fixes may overlap, but that's (hopefully)
        // unlikely.
        // TODO(b/24140798): emit more precise replacements if GJF is fixed
        fix.replace(tree, source.substring(((JCTree) tryStatements.get(0)).getStartPosition(), state.getEndPosition(Iterables.getLast(tryStatements))));
    }
    MethodTree enclosing = findEnclosing(state.getPath());
    if (enclosing == null) {
        // There isn't an enclosing method, possibly because we're in a lambda or initializer block.
        return Optional.empty();
    }
    if (isExpectedExceptionTest(ASTHelpers.getSymbol(enclosing), state)) {
        // tests, so don't use that fix for methods annotated with @Test(expected=...).
        return Optional.empty();
    }
    // Fix up the enclosing method's throws declaration to include the new thrown exception types.
    Collection<Type> thrownTypes = ASTHelpers.getSymbol(enclosing).getThrownTypes();
    Types types = state.getTypes();
    // Find all types in the deleted catch blocks that are not already in the throws declaration.
    ImmutableList<Type> toThrow = catchBlocks.stream().map(c -> ASTHelpers.getType(c.getParameter())).flatMap(t -> t instanceof UnionClassType ? ImmutableList.copyOf(((UnionClassType) t).getAlternativeTypes()).stream() : Stream.of(t)).filter(t -> thrownTypes.stream().noneMatch(x -> types.isAssignable(t, x))).collect(toImmutableList());
    if (!toThrow.isEmpty()) {
        if (!TEST_CASE.matches(enclosing, state)) {
            // not be a safe local refactoring.
            return Optional.empty();
        }
        String throwsString = toThrow.stream().map(t -> SuggestedFixes.qualifyType(state, fix, t)).distinct().collect(joining(", "));
        if (enclosing.getThrows().isEmpty()) {
            // Add a new throws declaration.
            fix.prefixWith(enclosing.getBody(), "throws " + throwsString);
        } else {
            // Append to an existing throws declaration.
            fix.postfixWith(Iterables.getLast(enclosing.getThrows()), ", " + throwsString);
        }
    }
    return Optional.of(fix.build());
}
Also used : SuggestedFixes(com.google.errorprone.fixes.SuggestedFixes) Iterables(com.google.common.collect.Iterables) Matchers.anyOf(com.google.errorprone.matchers.Matchers.anyOf) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodTree(com.sun.source.tree.MethodTree) VisitorState(com.google.errorprone.VisitorState) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Matchers.expressionStatement(com.google.errorprone.matchers.Matchers.expressionStatement) ImmutableList(com.google.common.collect.ImmutableList) TryTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.TryTreeMatcher) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) BugPattern(com.google.errorprone.BugPattern) Matcher(com.google.errorprone.matchers.Matcher) Fix(com.google.errorprone.fixes.Fix) Tree(com.sun.source.tree.Tree) MethodNameMatcher(com.google.errorprone.matchers.method.MethodMatchers.MethodNameMatcher) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) TreePath(com.sun.source.util.TreePath) UnionClassType(com.sun.tools.javac.code.Type.UnionClassType) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Matchers.hasAnnotation(com.google.errorprone.matchers.Matchers.hasAnnotation) Collection(java.util.Collection) Compound(com.sun.tools.javac.code.Attribute.Compound) Iterables.getOnlyElement(com.google.common.collect.Iterables.getOnlyElement) NO_MATCH(com.google.errorprone.matchers.Description.NO_MATCH) JCTree(com.sun.tools.javac.tree.JCTree) JUNIT4_TEST_ANNOTATION(com.google.errorprone.matchers.JUnitMatchers.JUNIT4_TEST_ANNOTATION) Collectors.joining(java.util.stream.Collectors.joining) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) JUnitMatchers.isJunit3TestCase(com.google.errorprone.matchers.JUnitMatchers.isJunit3TestCase) TreeScanner(com.sun.source.util.TreeScanner) Objects(java.util.Objects) List(java.util.List) MethodMatchers.staticMethod(com.google.errorprone.matchers.method.MethodMatchers.staticMethod) Types(com.sun.tools.javac.code.Types) Stream(java.util.stream.Stream) JUnitMatchers(com.google.errorprone.matchers.JUnitMatchers) Description(com.google.errorprone.matchers.Description) StatementTree(com.sun.source.tree.StatementTree) TryTree(com.sun.source.tree.TryTree) Optional(java.util.Optional) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) UnionClassType(com.sun.tools.javac.code.Type.UnionClassType) Types(com.sun.tools.javac.code.Types) MethodTree(com.sun.source.tree.MethodTree) JCTree(com.sun.tools.javac.tree.JCTree) UnionClassType(com.sun.tools.javac.code.Type.UnionClassType) Type(com.sun.tools.javac.code.Type) SuggestedFix(com.google.errorprone.fixes.SuggestedFix)

Example 38 with Types

use of com.sun.tools.javac.code.Types in project error-prone by google.

the class IdentityBinaryExpression method isNanReplacement.

private static Optional<String> isNanReplacement(BinaryTree tree, VisitorState state) {
    Types types = state.getTypes();
    Symtab symtab = state.getSymtab();
    Type type = getType(tree.getLeftOperand());
    if (type == null) {
        return Optional.empty();
    }
    type = types.unboxedTypeOrType(type);
    String name;
    if (isSameType(type, symtab.floatType, state)) {
        name = "Float";
    } else if (isSameType(type, symtab.doubleType, state)) {
        name = "Double";
    } else {
        return Optional.empty();
    }
    return Optional.of(String.format("%s.isNaN(%s)", name, state.getSourceForNode(tree.getLeftOperand())));
}
Also used : Symtab(com.sun.tools.javac.code.Symtab) Types(com.sun.tools.javac.code.Types) 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)

Example 39 with Types

use of com.sun.tools.javac.code.Types in project error-prone by google.

the class InexactVarargsConditional method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
    MethodSymbol sym = ASTHelpers.getSymbol(tree);
    if (!sym.isVarArgs()) {
        return NO_MATCH;
    }
    if (tree.getArguments().size() != sym.getParameters().size()) {
        // explicit varargs call with more actuals than formals
        return NO_MATCH;
    }
    Tree arg = getLast(tree.getArguments());
    if (!(arg instanceof ConditionalExpressionTree)) {
        return NO_MATCH;
    }
    Types types = state.getTypes();
    if (types.isArray(getType(arg))) {
        return NO_MATCH;
    }
    ConditionalExpressionTree cond = (ConditionalExpressionTree) arg;
    boolean trueIsArray = types.isArray(getType(cond.getTrueExpression()));
    if (!(trueIsArray ^ types.isArray(getType(cond.getFalseExpression())))) {
        return NO_MATCH;
    }
    SuggestedFix.Builder fix = SuggestedFix.builder();
    String qualified = SuggestedFixes.qualifyType(state, fix, types.elemtype(getLast(sym.getParameters()).asType()));
    Tree toFix = !trueIsArray ? cond.getTrueExpression() : cond.getFalseExpression();
    fix.prefixWith(toFix, String.format("new %s[] {", qualified)).postfixWith(toFix, "}");
    return describeMatch(tree, fix.build());
}
Also used : Types(com.sun.tools.javac.code.Types) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Tree(com.sun.source.tree.Tree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree)

Aggregations

Types (com.sun.tools.javac.code.Types)39 Type (com.sun.tools.javac.code.Type)29 MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)10 Tree (com.sun.source.tree.Tree)9 Symbol (com.sun.tools.javac.code.Symbol)9 VisitorState (com.google.errorprone.VisitorState)8 ASTHelpers.getType (com.google.errorprone.util.ASTHelpers.getType)7 ExpressionTree (com.sun.source.tree.ExpressionTree)6 Symtab (com.sun.tools.javac.code.Symtab)6 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)5 Description (com.google.errorprone.matchers.Description)5 ClassTree (com.sun.source.tree.ClassTree)5 MethodTree (com.sun.source.tree.MethodTree)5 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)5 VarSymbol (com.sun.tools.javac.code.Symbol.VarSymbol)5 JavacProcessingEnvironment (com.sun.tools.javac.processing.JavacProcessingEnvironment)5 ArrayList (java.util.ArrayList)5 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)4 List (java.util.List)4 BugPattern (com.google.errorprone.BugPattern)3