TypeElements { @Nonnull public static List<TypeName> findGenericTypes(@Nonnull TypeElement element, @Nonnull String className) { TypeElement currentElement = element; while (currentElement != null) { for (final TypeMirror interfaceType : currentElement.getInterfaces()) { final DeclaredType declaredType = (DeclaredType) interfaceType; final TypeElement interfaceElement = TypeElements.toElement(declaredType); if (interfaceElement.getSimpleName().toString().equals(className)) { return declaredType.getTypeArguments() .stream() .map(TypeName::get) .collect(toList()); } final List<TypeName> found = findGenericTypes(interfaceElement, className); if (!found.isEmpty()) { return found; } } final TypeMirror superClassType = currentElement.getSuperclass(); if (superClassType.getKind() == TypeKind.DECLARED) { currentElement = TypeElements.toElement(superClassType); } else { currentElement = null; } } return Collections.emptyList(); } private  TypeElements(); @Nonnull static TypeElement toElement(@Nonnull TypeMirror type); @Nonnull static List<TypeName> findGenericTypes(@Nonnull TypeElement element, @Nonnull String className);  }
@Test public void findGenericTypesShouldCollectGenericTypesRecursively() throws Exception { final TypeElement element = elements.getTypeElement(CustomConverter.class.getCanonicalName()); final List<TypeName> actual = TypeElements.findGenericTypes(element, Converter.class.getSimpleName()); assertThat(actual).hasSize(2); assertThat(actual.get(0)).isInstanceOf(ArrayTypeName.class); assertThat(actual.get(0).toString()).isEqualTo("java.lang.String[]"); assertThat(actual.get(1)).isInstanceOf(ClassName.class); assertThat(actual.get(1).toString()).isEqualTo("java.lang.String"); }
@Test public void findGenericTypesShouldCollectGenericTypes() throws Exception { final TypeElement element = elements.getTypeElement(ParentConverter.class.getCanonicalName()); final List<TypeName> actual = TypeElements.findGenericTypes(element, Converter.class.getSimpleName()); assertThat(actual).hasSize(2); assertThat(actual.get(0)).isInstanceOf(ParameterizedTypeName.class); assertThat(actual.get(0).toString()).isEqualTo("java.util.List<java.lang.String>"); assertThat(actual.get(1)).isInstanceOf(ClassName.class); assertThat(actual.get(1).toString()).isEqualTo("java.lang.String"); }
@Test public void findGenericTypesShouldEmptyList() throws Exception { final TypeElement element = elements.getTypeElement(HashMap.class.getCanonicalName()); final List<TypeName> actual = TypeElements.findGenericTypes(element, Converter.class.getSimpleName()); assertThat(actual).isEmpty(); }