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();
}
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());
}
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())));
}
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());
}
Aggregations