/** * Returns true if the method has synthetic parameter names, indicating the real names are not * available. */ public static boolean containsSyntheticParameterName(MethodSymbol sym) { return sym.getParameters().stream() .anyMatch(p -> SYNTHETIC_PARAMETER_NAME.matcher(p.getSimpleName()).matches()); }
private static boolean hasAttribute(Symbol sym, Name annotationName) { return sym.getRawAttributes().stream() .anyMatch(a -> a.type.tsym.getQualifiedName().equals(annotationName)); }
private static ImmutableSet<Symbol> getAnnotations(MethodSymbol symbol) { return symbol.getRawAttributes().stream().map(a -> a.type.tsym).collect(toImmutableSet()); } }
/** * A string representation of a method descriptor, where all parameters whose type is a functional * interface are "erased" to the interface's function type. For example, `foo(Supplier<String>)` * is represented as `foo(()->Ljava/lang/String;)`. */ private static String functionalInterfaceSignature(VisitorState state, MethodSymbol msym) { return String.format( "%s(%s)", msym.getSimpleName(), msym.getParameters().stream() .map(p -> functionalInterfaceSignature(state, p.type)) .collect(joining(","))); }
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); }
/** Returns a string descriptor of a method's reference type. */ private String methodReferenceDescriptor(Types types, MethodSymbol sym) { StringBuilder sb = new StringBuilder(); sb.append(sym.getSimpleName()).append('('); if (!sym.isStatic()) { sb.append(Signatures.descriptor(sym.owner.type, types)); } sym.params().stream().map(p -> Signatures.descriptor(p.type, types)).forEachOrdered(sb::append); sb.append(")"); return sb.toString(); } }
/** * NOTE: this method does not work for getting all annotations of parameters of methods from class * files. For that case, use {@link #getAllAnnotationsForParameter(Symbol.MethodSymbol, int)} * * @param symbol the symbol * @return all annotations on the symbol and on the type of the symbol */ public static Stream<? extends AnnotationMirror> getAllAnnotations(Symbol symbol) { // for methods, we care about annotations on the return type, not on the method type itself Stream<? extends AnnotationMirror> typeUseAnnotations = getTypeUseAnnotations(symbol); return Stream.concat(symbol.getAnnotationMirrors().stream(), typeUseAnnotations); }
/** * Returns true if the given type parameter's declaration is annotated with {@link * #typeParameterAnnotation} indicated it will only ever be instantiated with thread-safe types. */ public boolean hasThreadSafeTypeParameterAnnotation(TypeVariableSymbol symbol) { return typeParameterAnnotation != null && symbol.getAnnotationMirrors().stream() .anyMatch(t -> t.type.tsym.flatName().contentEquals(typeParameterAnnotation.getName())); }
/** Checks if a method symbol has any attribute from the org.junit package. */ private static boolean hasJUnitAttr(MethodSymbol methodSym) { return methodSym.getRawAttributes().stream() .anyMatch(attr -> attr.type.tsym.getQualifiedName().toString().startsWith("org.junit.")); }
private static ImmutableSet<String> getAnnotationValueAsStrings(Symbol sym, String guardedBy) { return sym.getRawAttributes().stream() .filter(a -> a.getAnnotationType().asElement().getSimpleName().contentEquals(guardedBy)) .flatMap( a -> // TODO(cushon): after the next release: // MoreAnnotations.getValue(a, "value").map(MoreAnnotations::asStrings) a.getElementValues().entrySet().stream() .filter(e -> e.getKey().getSimpleName().contentEquals("value")) .map(Map.Entry::getValue) .findFirst() .map(GuardedByUtils::asStrings) .orElse(Stream.empty())) .collect(toImmutableSet()); }
@Override public String visitClassType(Type.ClassType t, Void s) { StringBuilder sb = new StringBuilder(); sb.append(t.tsym.getSimpleName()); if (t.getTypeArguments().nonEmpty()) { sb.append('<'); sb.append( t.getTypeArguments().stream() .map(a -> a.accept(this, null)) .collect(joining(", "))); sb.append(">"); } return sb.toString(); }
private static Stream<? extends AnnotationMirror> getTypeUseAnnotations(Symbol symbol) { Stream<Attribute.TypeCompound> rawTypeAttributes = symbol.getRawTypeAttributes().stream(); if (symbol instanceof Symbol.MethodSymbol) { // for methods, we want the type-use annotations on the return type return rawTypeAttributes.filter((t) -> t.position.type.equals(TargetType.METHOD_RETURN)); } return rawTypeAttributes; }
/** * Pretty-prints a method signature for use in diagnostics. * * <p>Uses simple names for declared types, and omitting formal type parameters and the return * type since they do not affect overload resolution. */ public static String prettyMethodSignature(ClassSymbol origin, MethodSymbol m) { StringBuilder sb = new StringBuilder(); if (!m.owner.equals(origin)) { sb.append(m.owner.getSimpleName()).append('.'); } sb.append(m.isConstructor() ? origin.getSimpleName() : m.getSimpleName()).append('('); sb.append( m.getParameters().stream() .map(v -> v.type.accept(PRETTY_TYPE_VISITOR, null)) .collect(joining(", "))); sb.append(')'); return sb.toString(); }
@Override public String visitClassType(Type.ClassType t, Void unused) { StringBuilder sb = new StringBuilder(); if (state == null || fix == null) { sb.append(t.tsym.getSimpleName()); } else { sb.append(qualifyType(state, fix, t.tsym)); } if (t.getTypeArguments().nonEmpty()) { sb.append('<'); sb.append( t.getTypeArguments().stream() .map(a -> a.accept(this, null)) .collect(joining(", "))); sb.append(">"); } return sb.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 static Optional<JCCatch> catchesType( JCTry tryStatement, Type assertionErrorType, VisitorState state) { return tryStatement.getCatches().stream() .filter( catchTree -> { Type type = ASTHelpers.getType(catchTree.getParameter()); return (type.isUnion() ? Streams.stream(((UnionClassType) type).getAlternativeTypes()) : Stream.of(type)) .anyMatch(caught -> isSubtype(assertionErrorType, caught, state)); }) .findFirst(); }
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 String suggestedSingleLetter(String id, Tree tree) { char firstLetter = id.charAt(0); Symbol sym = ASTHelpers.getSymbol(tree); List<TypeVariableSymbol> enclosingTypeSymbols = typeVariablesEnclosing(sym); for (TypeVariableSymbol typeName : enclosingTypeSymbols) { char enclosingTypeFirstLetter = typeName.toString().charAt(0); if (enclosingTypeFirstLetter == firstLetter && !TypeParameterNamingClassification.classify(typeName.name.toString()).isValidName()) { ImmutableList<String> typeVarsInScope = Streams.concat(enclosingTypeSymbols.stream(), sym.getTypeParameters().stream()) .map(v -> v.name.toString()) .collect(toImmutableList()); return firstLetterReplacementName(id, typeVarsInScope); } } return Character.toString(firstLetter); } // T -> T2
private static String functionalInterfaceSignature(VisitorState state, Type type) { Types types = state.getTypes(); if (!maybeFunctionalInterface(type, types, state)) { 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); }
private boolean isExcludedClass(Symbol.ClassSymbol classSymbol, VisitorState state) { String className = classSymbol.getQualifiedName().toString(); if (config.isExcludedClass(className)) { return true; } if (!config.fromAnnotatedPackage(classSymbol)) { return true; } // check annotations ImmutableSet<String> excludedClassAnnotations = config.getExcludedClassAnnotations(); return classSymbol .getAnnotationMirrors() .stream() .map(anno -> anno.getAnnotationType().toString()) .anyMatch(excludedClassAnnotations::contains); }