use of com.sun.tools.javac.code.Type in project error-prone by google.
the class ForOverrideChecker method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
MethodSymbol method = ASTHelpers.getSymbol(tree);
if (method == null) {
return Description.NO_MATCH;
}
Type currentClass = getOutermostClass(state);
if (method.isStatic() || method.isConstructor() || currentClass == null) {
return Description.NO_MATCH;
}
// allow super.foo() calls to @ForOverride methods from overriding methods
if (isSuperCall(currentClass, tree, state)) {
MethodTree currentMethod = findDirectMethod(state.getPath());
// currentMethod might be null if we are in a field initializer
if (currentMethod != null) {
// MethodSymbol.overrides doesn't check that names match, so we need to do that first.
if (currentMethod.getName().equals(method.name)) {
MethodSymbol currentMethodSymbol = ASTHelpers.getSymbol(currentMethod);
if (currentMethodSymbol.overrides(method, (TypeSymbol) method.owner, state.getTypes(), true)) {
return Description.NO_MATCH;
}
}
}
}
List<MethodSymbol> overriddenMethods = getOverriddenMethods(state, method);
for (Symbol overriddenMethod : overriddenMethods) {
Type declaringClass = overriddenMethod.outermostClass().asType();
if (!declaringClass.equals(currentClass)) {
String customMessage = MESSAGE_BASE + "must not be invoked directly " + "(except by the declaring class, " + declaringClass + ")";
return buildDescription(tree).setMessage(customMessage).build();
}
}
return Description.NO_MATCH;
}
use of com.sun.tools.javac.code.Type in project error-prone by google.
the class ForOverrideChecker method getOverriddenMethods.
/**
* Get overridden @ForOverride methods.
*
* @param state the VisitorState
* @param method the method to find overrides for
* @return a list of methods annotated @ForOverride that the method overrides, including the
* method itself if it has the annotation
*/
private List<MethodSymbol> getOverriddenMethods(VisitorState state, MethodSymbol method) {
// Static methods cannot override, only overload.
if (method.isStatic()) {
throw new IllegalArgumentException("getOverriddenMethods may not be called on a static method");
}
List<MethodSymbol> list = new LinkedList<MethodSymbol>();
list.add(method);
// Iterate over supertypes of the type that owns this method, collecting a list of all method
// symbols with the same name. We intentionally exclude interface methods because interface
// methods cannot be annotated @ForOverride. @ForOverride methods must have protected or
// package-private visibility, but interface methods have implicit public visibility.
Type currType = state.getTypes().supertype(method.owner.type);
while (currType != null && !currType.equals(state.getSymtab().objectType) && !currType.equals(Type.noType)) {
Symbol sym = currType.tsym.members().findFirst(method.name);
if (sym instanceof MethodSymbol) {
list.add((MethodSymbol) sym);
}
currType = state.getTypes().supertype(currType);
}
// Remove methods that either don't have the @ForOverride annotation or don't override the
// method in question.
Iterator<MethodSymbol> iter = list.iterator();
while (iter.hasNext()) {
MethodSymbol member = iter.next();
if (!hasAnnotation(FOR_OVERRIDE, member) || // already checked that this method is not static.
!method.overrides(member, (TypeSymbol) member.owner, state.getTypes(), true)) {
iter.remove();
}
}
return list;
}
use of com.sun.tools.javac.code.Type in project error-prone by google.
the class FunctionalInterfaceClash method functionalInterfaceSignature.
private static String functionalInterfaceSignature(VisitorState state, Type type) {
Types types = state.getTypes();
if (!maybeFunctionalInterface(type, types)) {
return Signatures.descriptor(type, types);
}
Type descriptorType = types.findDescriptorType(type);
List<Type> fiparams = descriptorType.getParameterTypes();
// Implicitly typed block-statement-bodied lambdas are potentially compatible with
// void-returning and value-returning functional interface types, so we don't consider return
// types in general. The except is nullary functional interfaces, since the lambda parameters
// will never be implicitly typed.
String result = fiparams.isEmpty() ? Signatures.descriptor(descriptorType.getReturnType(), types) : "_";
return String.format("(%s)->%s", fiparams.stream().map(t -> Signatures.descriptor(t, types)).collect(joining(",")), result);
}
use of com.sun.tools.javac.code.Type in project error-prone by google.
the class FuturesGetCheckedIllegalExceptionType method canBeUsedByGetChecked.
private static boolean canBeUsedByGetChecked(MethodSymbol constructor, VisitorState state) {
Type stringType = state.getSymtab().stringType;
Type throwableType = state.getSymtab().throwableType;
// TODO(cpovirk): Check visibility of enclosing types (assuming that it matters to getChecked).
if (!constructor.getModifiers().contains(PUBLIC)) {
return false;
}
for (VarSymbol param : constructor.getParameters()) {
if (!isSameType(param.asType(), stringType, state) && !isSameType(param.asType(), throwableType, state)) {
return false;
}
}
return true;
}
use of com.sun.tools.javac.code.Type 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;
}
Aggregations