private static ImmutableMap<TypeVariableSymbol, Type> getInstantiation( Types types, Type methodType) { List<Type> to = new ArrayList<>(); ArrayList<Type> from = new ArrayList<>(); getSubst(getMapping(methodType), from, to); Map<TypeVariableSymbol, Type> mapping = new LinkedHashMap<>(); Streams.forEachPair( from.stream(), to.stream(), (f, t) -> { Type existing = mapping.put((TypeVariableSymbol) f.asElement(), t); if (existing != null && !types.isSameType(t, existing)) { throw new AssertionError( String.format("%s instantiated as both %s and %s", f.asElement(), t, existing)); } }); return ImmutableMap.copyOf(mapping); }
@Override public Symbol.MethodSymbol resolveMethod( MethodInvocationTree node, GuardedByExpression base, javax.lang.model.element.Name identifier) { Symbol baseSym = base.kind() == GuardedByExpression.Kind.THIS ? enclosingClass : base.type().asElement(); return getMethod(baseSym, identifier.toString()); }
@Override public Symbol resolveSelect(GuardedByExpression base, MemberSelectTree node) { Symbol baseSym = base.kind() == GuardedByExpression.Kind.THIS ? enclosingClass : base.type().asElement(); return getField(baseSym, node.getIdentifier().toString()); }
private static boolean implementsImmutableInterface(ClassSymbol symbol) { return Streams.concat(symbol.getInterfaces().stream(), Stream.of(symbol.getSuperclass())) .anyMatch(supertype -> supertype.asElement().getAnnotation(Immutable.class) != null); } }
private boolean containerOfSubtyping( Set<String> containerTypeParameters, AnnotationInfo annotation, TypeVariableSymbol typaram, Type tyargument) { // (1) if (!tyargument.hasTag(TypeTag.TYPEVAR)) { return false; } // (2) if (!containerTypeParameters.contains(tyargument.asElement().getSimpleName().toString()) || isTypeParameterThreadSafe( (TypeVariableSymbol) tyargument.asElement(), containerTypeParameters)) { return false; } // (3) if (annotation.containerOf().contains(typaram.getSimpleName().toString())) { return false; } return true; }
private static Multimap<TypeVariableSymbol, TypeInfo> getResolvedGenerics( MethodInvocationTree tree) { Type type = ASTHelpers.getType(tree.getMethodSelect()); List<Type> from = new ArrayList<>(); List<Type> to = new ArrayList<>(); getSubst(type, from, to); Multimap<TypeVariableSymbol, TypeInfo> result = Streams.zip( from.stream(), to.stream(), (f, t) -> new TypeInfo((TypeVariableSymbol) f.asElement(), t, tree)) .collect( toMultimap( k -> k.sym, k -> k, MultimapBuilder.linkedHashKeys().arrayListValues()::build)); return result; }
@Override public Description matchSwitch(SwitchTree tree, VisitorState state) { Type switchType = ASTHelpers.getType(tree.getExpression()); if (switchType.asElement().getKind() != ElementKind.ENUM) { return Description.NO_MATCH; } // default case is present if (tree.getCases().stream().anyMatch(c -> c.getExpression() == null)) { return Description.NO_MATCH; } ImmutableSet<String> handled = tree.getCases().stream() .map(CaseTree::getExpression) .filter(IdentifierTree.class::isInstance) .map(e -> ((IdentifierTree) e).getName().toString()) .collect(toImmutableSet()); Set<String> unhandled = Sets.difference(ASTHelpers.enumValues(switchType.asElement()), handled); if (unhandled.isEmpty()) { return Description.NO_MATCH; } return buildDescription(tree).setMessage(buildMessage(unhandled)).build(); }
.filter(anno -> isAnnotationOnType(sym, anno.position))) .collect( groupingBy(c -> c.type.asElement().getQualifiedName(), LinkedHashMap::new, toList())) .values().stream() .map(c -> c.get(0));
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 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; }
private static Type getComparableTypeArgument(ClassTree tree, VisitorState state) { final Type comparable = state .getTypes() .asSuper(ASTHelpers.getType(tree), state.getSymtab().comparableType.asElement()); if (comparable != null && !comparable.getTypeArguments().isEmpty()) { return Iterables.getOnlyElement(comparable.getTypeArguments()); } return null; } }
private static boolean knownNonNullMethod( MethodSymbol methodSymbol, ClassSymbol clazzSymbol, @Nullable Types types) { if (types == null) { return false; } // Proto getters are not null if (methodSymbol.name.toString().startsWith("get") && methodSymbol.params().isEmpty() && !methodSymbol.isStatic()) { Type type = clazzSymbol.type; while (type != null) { TypeSymbol typeSymbol = type.asElement(); if (typeSymbol == null) { break; } if (typeSymbol .getQualifiedName() .contentEquals("com.google.protobuf.AbstractMessageLite")) { return true; } type = types.supertype(type); } } return false; }
private Description describeIfObsolete( @Nullable Tree tree, Iterable<Type> types, VisitorState state) { for (Type type : types) { Obsolete obsolete = OBSOLETE.get(type.asElement().getQualifiedName().toString()); if (obsolete == null) { continue; } if (shouldSkip(state, type)) { continue; } Description.Builder description = buildDescription(state.getPath().getLeaf()).setMessage(obsolete.message()); if (tree != null) { obsolete.fix(tree, state).ifPresent(description::addFix); } return description.build(); } return NO_MATCH; }
public void addShadowType(TypeElement shadowType, TypeElement actualType, TypeElement shadowPickerType) { TypeElement shadowBaseType = null; if (shadowPickerType != null) { TypeMirror iface = helpers.findInterface(shadowPickerType, ShadowPicker.class); if (iface != null) { com.sun.tools.javac.code.Type type = ((com.sun.tools.javac.code.Type.ClassType) iface) .allparams().get(0); String baseClassName = type.asElement().getQualifiedName().toString(); shadowBaseType = helpers.getTypeElement(baseClassName); } } ShadowInfo shadowInfo = new ShadowInfo(shadowType, actualType, shadowPickerType, shadowBaseType); if (shadowInfo.isInAndroidSdk()) { registerType(shadowInfo.shadowType); registerType(shadowInfo.actualType); registerType(shadowInfo.shadowBaseClass); } shadowTypes.put(shadowType.getQualifiedName().toString(), shadowInfo); }
type.asElement().getTypeParameters().stream(), type.getTypeArguments().stream(), (typaram, argument) -> {
@Override public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { if (!MATCHER.matches(tree, state)) { return NO_MATCH; } Type classType = getType(getOnlyElement(tree.getArguments())); if (classType == null || classType.getTypeArguments().isEmpty()) { return NO_MATCH; } Type type = getUpperBound(getOnlyElement(classType.getTypeArguments()), state.getTypes()); if (isSameType(type, state.getSymtab().annotationType, state)) { return NO_MATCH; } RetentionPolicy retention = state.getTypes().getRetention(type.asElement()); switch (retention) { case RUNTIME: break; case SOURCE: case CLASS: return buildDescription(tree) .setMessage( String.format( "%s; %s has %s retention", message(), type.asElement().getSimpleName(), retention)) .build(); } return NO_MATCH; } }
/** Ignore some common ThreadLocal type arguments that are fine to have per-instance copies of. */ private boolean wellKnownTypeArgument(NewClassTree tree, VisitorState state) { Type type = getType(tree); if (type == null) { return false; } type = state.getTypes().asSuper(type, state.getSymbolFromString("java.lang.ThreadLocal")); if (type == null) { return false; } if (type.getTypeArguments().isEmpty()) { return false; } Type argType = getOnlyElement(type.getTypeArguments()); if (WELL_KNOWN_TYPES.contains(argType.asElement().getQualifiedName().toString())) { return true; } if (isSubtype(argType, state.getTypeFromString("java.text.DateFormat"), state)) { return true; } return false; } }
@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); }
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; }