use of com.google.errorprone.annotations.CompatibleWith in project error-prone by google.
the class CompatibleWithMisuse method matchAnnotation.
@Override
public Description matchAnnotation(AnnotationTree annoTree, VisitorState state) {
if (!IS_COMPATIBLE_WITH_ANNOTATION.matches(annoTree, state)) {
return Description.NO_MATCH;
}
// Hunt for type args on the declared method
// TODO(glorioso): Once annotation is TYPE_USE, make sure that the node is actually a method
// parameter
MethodTree methodTree = ASTHelpers.findEnclosingNode(state.getPath(), MethodTree.class);
VariableTree paramTree = ASTHelpers.findEnclosingNode(state.getPath(), VariableTree.class);
MethodSymbol declaredMethod = ASTHelpers.getSymbol(methodTree);
// We're disallowing tags on varargs methods for now, but we may revisit it in the future.
if (declaredMethod.isVarArgs() && Iterables.getLast(methodTree.getParameters()) == paramTree) {
return describeWithMessage(annoTree, "@CompatibleWith can't be used on a varargs parameter");
}
// This restriction may need to be removed to allow more complex declaration hierarchies.
for (MethodSymbol methodSymbol : ASTHelpers.findSuperMethods(declaredMethod, state.getTypes())) {
if (methodSymbol.params().stream().anyMatch(p -> ASTHelpers.hasAnnotation(p, CompatibleWith.class, state))) {
return describeWithMessage(annoTree, String.format("This method overrides a method in %s that already has @CompatibleWith", methodSymbol.owner.getSimpleName()));
}
}
List<TypeVariableSymbol> potentialTypeVars = new ArrayList<>(declaredMethod.getTypeParameters());
// Check enclosing types (not superclasses)
ClassSymbol cs = (ClassSymbol) declaredMethod.owner;
do {
potentialTypeVars.addAll(cs.getTypeParameters());
cs = cs.isInner() ? cs.owner.enclClass() : null;
} while (cs != null);
if (potentialTypeVars.isEmpty()) {
return describeWithMessage(annoTree, "There are no type arguments in scope to match against.");
}
Set<String> validNames = potentialTypeVars.stream().map(TypeVariableSymbol::getSimpleName).map(Object::toString).collect(toImmutableSet());
String constValue = valueArgumentFromCompatibleWithAnnotation(annoTree);
if (constValue == null || constValue.isEmpty()) {
return describeWithMessage(annoTree, String.format("The value of @CompatibleWith must not be empty (valid arguments are %s)", printTypeArgs(validNames)));
}
return validNames.contains(constValue) ? Description.NO_MATCH : describeWithMessage(annoTree, String.format("%s is not a valid type argument. Valid arguments are: %s", constValue, printTypeArgs(validNames)));
}
use of com.google.errorprone.annotations.CompatibleWith in project error-prone by google.
the class IncompatibleArgumentType method populateTypesToEnforce.
@CheckReturnValue
private boolean populateTypesToEnforce(MethodSymbol declaredMethod, Type calledMethodType, Type calledReceiverType, List<RequiredType> requiredTypesAtCallSite, VisitorState state) {
// We'll only search the first method in the hierarchy with an annotation.
boolean found = false;
com.sun.tools.javac.util.List<VarSymbol> params = declaredMethod.params();
for (int i = 0; i < params.size(); i++) {
VarSymbol varSymbol = params.get(i);
CompatibleWith anno = ASTHelpers.getAnnotation(varSymbol, CompatibleWith.class);
if (anno != null) {
found = true;
if (requiredTypesAtCallSite.size() <= i) {
// void foo(String...); foo();
break;
}
// Now we try and resolve the generic type argument in the annotation against the current
// method call's projection of this generic type.
RequiredType requiredType = resolveRequiredTypeForThisCall(state, calledMethodType, calledReceiverType, declaredMethod, anno.value());
requiredTypesAtCallSite.set(i, requiredType);
}
}
return found;
}
Aggregations