use of com.sun.tools.javac.code.Types in project error-prone by google.
the class ASTHelpers method findMatchingMethods.
/**
* Finds all methods in any superclass of {@code startClass} with a certain {@code name} that
* match the given {@code predicate}.
*
* @return The (possibly empty) set of methods in any superclass that match {@code predicate} and
* have the given {@code name}.
*/
public static Set<MethodSymbol> findMatchingMethods(Name name, final Predicate<MethodSymbol> predicate, Type startClass, Types types) {
Filter<Symbol> matchesMethodPredicate = sym -> sym instanceof MethodSymbol && predicate.apply((MethodSymbol) sym);
Set<MethodSymbol> matchingMethods = new HashSet<>();
// Iterate over all classes and interfaces that startClass inherits from.
for (Type superClass : types.closure(startClass)) {
// Iterate over all the methods declared in superClass.
TypeSymbol superClassSymbol = superClass.tsym;
Scope superClassSymbols = superClassSymbol.members();
if (superClassSymbols != null) {
// Can be null if superClass is a type variable
for (Symbol symbol : superClassSymbols.getSymbolsByName(name, matchesMethodPredicate, NON_RECURSIVE)) {
// By definition of the filter, we know that the symbol is a MethodSymbol.
matchingMethods.add((MethodSymbol) symbol);
}
}
}
return matchingMethods;
}
use of com.sun.tools.javac.code.Types in project error-prone by google.
the class CollectionToArraySafeParameter method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree methodInvocationTree, VisitorState visitorState) {
if (!TO_ARRAY_MATCHER.matches(methodInvocationTree, visitorState)) {
return NO_MATCH;
}
Types types = visitorState.getTypes();
Type variableType = types.elemtype(getType(getOnlyElement(methodInvocationTree.getArguments())));
if (variableType == null) {
return NO_MATCH;
}
Type collectionType = types.asSuper(ASTHelpers.getReceiverType(methodInvocationTree), visitorState.getSymbolFromString("java.util.Collection"));
List<Type> typeArguments = collectionType.getTypeArguments();
if (!typeArguments.isEmpty() && !types.isCastable(types.erasure(variableType), types.erasure(getOnlyElement(typeArguments)))) {
return describeMatch(methodInvocationTree);
}
return NO_MATCH;
}
use of com.sun.tools.javac.code.Types in project error-prone by google.
the class ArrayHashCode method matchMethodInvocation.
/**
* Wraps identity hashcode computations in calls to {@link java.util.Arrays#hashCode} if the array
* is single dimensional or {@link java.util.Arrays#deepHashCode} if the array is
* multidimensional.
*
* <p>If there is only one argument to the hashcode method or the instance hashcode method is
* used, replaces the whole method invocation. If there are multiple arguments, wraps any that are
* of array type with the appropriate {@link java.util.Arrays} hashcode method.
*/
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
SuggestedFix.Builder fix = null;
Types types = state.getTypes();
if (jdk7HashCodeMethodMatcher.matches(tree, state)) {
// java.util.Objects#hashCode takes a single argument, so rewrite the whole method call
// to use Arrays.hashCode/deepHashCode instead.
fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(tree.getArguments().get(0), types));
} else if (instanceHashCodeMethodMatcher.matches(tree, state)) {
// Rewrite call to instance hashCode method to use Arrays.hashCode/deepHashCode instead.
fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(((JCFieldAccess) tree.getMethodSelect()).getExpression(), types));
} else if (varargsHashCodeMethodMatcher.matches(tree, state)) {
// com.google.common.base.Objects#hashCode
if (tree.getArguments().size() == 1) {
// If only one argument, type must be either primitive array or multidimensional array.
// Types like Object[], String[], etc. are not an error because they don't get boxed
// in this single-argument varargs call.
ExpressionTree arg = tree.getArguments().get(0);
Type elemType = types.elemtype(ASTHelpers.getType(arg));
if (elemType.isPrimitive() || types.isArray(elemType)) {
fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(arg, types));
}
} else {
// If more than one argument, wrap each argument in a call to Arrays#hashCode/deepHashCode.
fix = SuggestedFix.builder();
for (ExpressionTree arg : tree.getArguments()) {
if (types.isArray(ASTHelpers.getType(arg))) {
fix.replace(arg, rewriteArrayArgument(arg, types));
}
}
}
}
if (fix != null) {
fix.addImport("java.util.Arrays");
return describeMatch(tree, fix.build());
}
return Description.NO_MATCH;
}
use of com.sun.tools.javac.code.Types in project error-prone by google.
the class FormatStringValidation method validate.
@Nullable
public static ValidationResult validate(Collection<? extends ExpressionTree> arguments, final VisitorState state) {
Deque<ExpressionTree> args = new ArrayDeque<>(arguments);
Stream<String> formatStrings = constValues(args.removeFirst());
if (formatStrings == null) {
return null;
}
// Bail out, since we don't know what the actual argument types are.
if (args.size() == 1) {
Type type = ASTHelpers.getType(Iterables.getOnlyElement(args));
if (type instanceof Type.ArrayType && ASTHelpers.isSameType(((Type.ArrayType) type).elemtype, state.getSymtab().objectType, state)) {
return null;
}
}
Iterable<Object> instances = Iterables.transform(args, new Function<ExpressionTree, Object>() {
@Override
public Object apply(ExpressionTree input) {
try {
return getInstance(input, state);
} catch (Throwable t) {
// ignore symbol completion failures
return null;
}
}
});
return formatStrings.map(formatString -> validate(formatString, instances)).filter(x -> x != null).findFirst().orElse(null);
}
use of com.sun.tools.javac.code.Types in project error-prone by google.
the class StrictFormatStringValidation method validateFormatStringParamter.
/**
* Helps {@code validate()} validate a format string that is declared as a method parameter.
*/
private static ValidationResult validateFormatStringParamter(ExpressionTree formatStringTree, Symbol formatStringSymbol, List<? extends ExpressionTree> args, VisitorState state) {
if (!isFormatStringParameter(formatStringSymbol, state)) {
return ValidationResult.create(null, String.format("Format strings must be compile time constant or parameters annotated " + "@FormatString: %s", formatStringTree));
}
List<VarSymbol> ownerParams = ((MethodSymbol) formatStringSymbol.owner).getParameters();
int ownerFormatStringIndex = ownerParams.indexOf(formatStringSymbol);
ImmutableList.Builder<Type> ownerFormatArgTypesBuilder = ImmutableList.builder();
for (VarSymbol paramSymbol : ownerParams.subList(ownerFormatStringIndex + 1, ownerParams.size())) {
ownerFormatArgTypesBuilder.add(paramSymbol.type);
}
ImmutableList<Type> ownerFormatArgTypes = ownerFormatArgTypesBuilder.build();
Types types = state.getTypes();
ImmutableList.Builder<Type> calleeFormatArgTypesBuilder = ImmutableList.builder();
for (ExpressionTree formatArgExpression : args) {
calleeFormatArgTypesBuilder.add(types.erasure(((JCExpression) formatArgExpression).type));
}
ImmutableList<Type> calleeFormatArgTypes = calleeFormatArgTypesBuilder.build();
if (ownerFormatArgTypes.size() != calleeFormatArgTypes.size()) {
return ValidationResult.create(null, String.format("The number of format arguments passed " + "with an @FormatString must match the number of format arguments in the " + "@FormatMethod header where the format string was declared.\n\t" + "Format args passed: %d\n\tFormat args expected: %d", calleeFormatArgTypes.size(), ownerFormatArgTypes.size()));
} else {
for (int i = 0; i < calleeFormatArgTypes.size(); i++) {
if (!ASTHelpers.isSameType(ownerFormatArgTypes.get(i), calleeFormatArgTypes.get(i), state)) {
return ValidationResult.create(null, String.format("The format argument types passed " + "with an @FormatString must match the types of the format arguments in " + "the @FormatMethod header where the format string was declared.\n\t" + "Format arg types passed: %s\n\tFormat arg types expected: %s", calleeFormatArgTypes.toArray(), ownerFormatArgTypes.toArray()));
}
}
}
// Format string usage was valid.
return null;
}
Aggregations