private static Stream<MethodSymbol> findSuperMethods( MethodSymbol methodSymbol, Types types, boolean skipInterfaces) { TypeSymbol owner = (TypeSymbol) methodSymbol.owner; return types.closure(owner.type).stream() .filter(closureTypes -> skipInterfaces ? !closureTypes.isInterface() : true) .map(type -> findSuperMethodInType(methodSymbol, type, types)) .filter(Objects::nonNull); }
/** * 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; }
/** Finds all the visible fields declared or inherited in the target class */ public static List<VarSymbol> findAllFields(Type classType, VisitorState state) { // TODO(andrewrice): Switch collector to ImmutableList.toImmutableList() when released return state.getTypes().closure(classType).stream() .flatMap( type -> { TypeSymbol tsym = type.tsym; if (tsym == null) { return ImmutableList.<VarSymbol>of().stream(); } WriteableScope scope = tsym.members(); if (scope == null) { return ImmutableList.<VarSymbol>of().stream(); } return ImmutableList.copyOf(scope.getSymbols(VarSymbol.class::isInstance)).reverse() .stream() .map(v -> (VarSymbol) v) .filter(v -> isVisible(v, state.getPath())); }) .collect(Collectors.toCollection(ArrayList::new)); }
/** * Returns the type of the first superclass or superinterface in the hierarchy annotated with * {@code @Immutable}, or {@code null} if no such super type exists. */ private Type immutableSupertype(Symbol sym, VisitorState state) { for (Type superType : state.getTypes().closure(sym.type)) { if (superType.tsym.equals(sym.type.tsym)) { continue; } // Don't use getImmutableAnnotation here: subtypes of trusted types are // also trusted, only check for explicitly annotated supertypes. if (immutableAnnotations.stream() .anyMatch(annotation -> ASTHelpers.hasAnnotation(superType.tsym, annotation, state))) { return superType; } // We currently trust that @interface annotations are immutable, but don't enforce that // custom interface implementations are also immutable. That means the check can be // defeated by writing a custom mutable annotation implementation, and passing it around // using the superclass type. // // TODO(b/25630189): fix this // // if (superType.tsym.getKind() == ElementKind.ANNOTATION_TYPE) { // return superType; // } } return null; }
private static Symbol getFinalizer(VisitorState state, ClassSymbol enclosing) { Type finalizerType = state.getTypeFromString("com.google.common.labs.base.Finalizer"); Optional<VarSymbol> finalizerField = state.getTypes().closure(enclosing.asType()).stream() .flatMap(s -> getFields(s.asElement())) .filter(s -> ASTHelpers.isSameType(finalizerType, s.asType(), state)) .findFirst(); if (finalizerField.isPresent()) { return finalizerField.get(); } return ASTHelpers.resolveExistingMethod( state, enclosing.enclClass(), state.getName("finalize"), /* argTypes= */ ImmutableList.of(), /* tyargTypes= */ ImmutableList.of()); }
private Symbol getSuperType(Symbol symbol, String name) { for (Type t : types.closure(symbol.type)) { if (t.asElement().getSimpleName().contentEquals(name)) { return t.asElement(); } } return null; }
private static boolean isMapMethod(Symbol.MethodSymbol symbol, Types types, String methodName) { if (!symbol.getSimpleName().toString().equals(methodName)) { return false; } Symbol owner = symbol.owner; if (owner.getQualifiedName().toString().equals("java.util.Map")) { return true; } com.sun.tools.javac.util.List<Type> supertypes = types.closure(owner.type); for (Type t : supertypes) { if (t.asElement().getQualifiedName().toString().equals("java.util.Map")) { return true; } } return false; }
for (Type s : types.closure(owner.type)) { if (s.equals(owner.type)) { continue;
/** * Returns the {@link MethodSymbol} of the first method that sym overrides in its supertype * closure, or {@code null} if no such method exists. */ private MethodSymbol getFirstOverride(Symbol sym, Types types) { ClassSymbol owner = sym.enclClass(); if (ignoreInterfaceOverrides && owner.isInterface()) { // pretend the method does not override anything return null; } for (Type s : types.closure(owner.type)) { if (s == owner.type) { continue; } for (Symbol m : s.tsym.members().getSymbolsByName(sym.name)) { if (!(m instanceof MethodSymbol)) { continue; } MethodSymbol msym = (MethodSymbol) m; if (msym.isStatic()) { continue; } if (sym.overrides(msym, owner, types, /* checkResult= */ false)) { return msym; } } } return null; } }
List<Type> classTypeClosure = state.getTypes().closure(classType); List<Type> superTypes = classTypeClosure.size() <= 1
private <T extends Symbol> T getMember( Class<T> type, ElementKind kind, Symbol classSymbol, String name) { if (classSymbol.type == null) { return null; } for (Type t : types.closure(classSymbol.type)) { Scope scope = t.tsym.members(); for (Symbol sym : scope.getSymbolsByName(getName(name))) { if (sym.getKind().equals(kind)) { return type.cast(sym); } } } if (classSymbol.hasOuterInstance()) { T sym = getMember(type, kind, classSymbol.type.getEnclosingType().asElement(), name); if (sym != null) { return sym; } } if (classSymbol.owner != null && classSymbol != classSymbol.owner && classSymbol.owner instanceof Symbol.ClassSymbol) { T sym = getMember(type, kind, classSymbol.owner, name); if (sym != null && sym.isStatic()) { return sym; } } return null; }
@Override public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { if (!MATCHER.matches(tree, state)) { return NO_MATCH; } if (state.getTypes().closure(ASTHelpers.getSymbol(tree).enclClass().asType()).stream() .anyMatch( s -> s.asElement() .packge() .getQualifiedName() .toString() .startsWith("java.util.concurrent"))) { return NO_MATCH; } if (blockEndsInBreakOrReturn(state)) { return NO_MATCH; } ExpressionTree collection = getReceiver(tree); if (collection == null) { return NO_MATCH; } if (!enclosingLoop(state.getPath(), collection)) { return NO_MATCH; } return describeMatch(tree); }
for (Type sup : types.closure(ASTHelpers.getSymbol(classTree).type)) { if (equals == null) { equals = getMatchingMethod(sup, equalsName, equalsPredicate);
/** Check if the method declares or inherits an implementation of .equals() */ public static boolean implementsEquals(Type type, VisitorState state) { Name equalsName = state.getName("equals"); Symbol objectEquals = getOnlyMember(state, state.getSymtab().objectType, "equals"); for (Type sup : state.getTypes().closure(type)) { if (sup.tsym.isInterface()) { continue; } if (ASTHelpers.isSameType(sup, state.getSymtab().objectType, state)) { return false; } Scope scope = sup.tsym.members(); if (scope == null) { continue; } for (Symbol sym : scope.getSymbolsByName(equalsName)) { if (sym.overrides(objectEquals, type.tsym, state.getTypes(), /* checkResult= */ false)) { return true; } } } return false; } }
private static Stream<MethodSymbol> findSuperMethods( MethodSymbol methodSymbol, Types types, boolean skipInterfaces) { TypeSymbol owner = (TypeSymbol) methodSymbol.owner; return types.closure(owner.type).stream() .filter(closureTypes -> skipInterfaces ? !closureTypes.isInterface() : true) .map(type -> findSuperMethodInType(methodSymbol, type, types)) .filter(Objects::nonNull); }
private Symbol getSuperType(Symbol symbol, String name) { for (Type t : types.closure(symbol.type)) { if (t.asElement().getSimpleName().contentEquals(name)) { return t.asElement(); } } return null; }
/** * {@inheritDoc} */ public FilteredMemberList getAllMembers(TypeElement element) { Symbol sym = cast(Symbol.class, element); Scope scope = sym.members().dupUnshared(); List<Type> closure = types.closure(sym.asType()); for (Type t : closure) addMembers(scope, t); return new FilteredMemberList(scope); } // where
List<Type> erasedSupertypes(Type t) { ListBuffer<Type> buf = new ListBuffer<>(); for (Type sup : closure(t)) { if (sup.hasTag(TYPEVAR)) { buf.append(sup); } else { buf.append(erasure(sup)); } } return buf.toList(); }
/** * {@inheritDoc} */ public FilteredMemberList getAllMembers(TypeElement element) { Symbol sym = cast(Symbol.class, element); Scope scope = sym.members().dupUnshared(); List<Type> closure = types.closure(sym.asType()); for (Type t : closure) addMembers(scope, t); return new FilteredMemberList(scope); } // where
/** * {@inheritDoc} */ public FilteredMemberList getAllMembers(TypeElement element) { Symbol sym = cast(Symbol.class, element); Scope scope = sym.members().dupUnshared(); List<Type> closure = types.closure(sym.asType()); for (Type t : closure) addMembers(scope, t); return new FilteredMemberList(scope); } // where