com.github.javaparser.resolution.types.ResolvedReferenceType Java Examples
The following examples show how to use
com.github.javaparser.resolution.types.ResolvedReferenceType.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SchemaResolverTest.java From flow with Apache License 2.0 | 6 votes |
@Test public void should_ReturnNullableOptional_When_GivenTypeIsAnOptionalBean() { ResolvedType resolvedType = mockReferencedTypeOf(Optional.class); ResolvedReferenceType resolvedReferenceType = resolvedType .asReferenceType(); List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> pairs = Collections .singletonList( new Pair<>(null, mockReferencedTypeOf(TestBean.class))); when(resolvedReferenceType.getTypeParametersMap()).thenReturn(pairs); Schema schema = schemaResolver.parseResolvedTypeToSchema(resolvedType); Assert.assertTrue(schema instanceof ComposedSchema); Assert.assertTrue(schema.getNullable()); Assert.assertEquals(1, ((ComposedSchema) schema).getAllOf().size()); String beanRef = schemaResolver .getFullQualifiedNameRef(TestBean.class.getCanonicalName()); Assert.assertEquals(beanRef, ((ComposedSchema) schema).getAllOf().get(0).get$ref()); Assert.assertEquals(1, schemaResolver.getFoundTypes().size()); }
Example #2
Source File: SchemaResolverTest.java From flow with Apache License 2.0 | 6 votes |
@Test public void should_ReturnNullableOptional_When_GivenTypeIsAnOptionalString() { ResolvedType resolvedType = mockReferencedTypeOf(Optional.class); ResolvedReferenceType resolvedReferenceType = resolvedType .asReferenceType(); List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> pairs = Collections .singletonList( new Pair<>(null, mockReferencedTypeOf(String.class))); when(resolvedReferenceType.getTypeParametersMap()).thenReturn(pairs); Schema schema = schemaResolver.parseResolvedTypeToSchema(resolvedType); Assert.assertTrue(schema instanceof StringSchema); Assert.assertTrue(schema.getNullable()); Assert.assertTrue(schemaResolver.getFoundTypes().isEmpty()); }
Example #3
Source File: SchemaResolverTest.java From flow with Apache License 2.0 | 6 votes |
@Test public void should_ReturnNotNullableMap_When_GivenTypeIsAMap() { ResolvedType resolvedType = mockReferencedTypeOf(Map.class); ResolvedReferenceType resolvedReferenceType = resolvedType .asReferenceType(); List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> pairs = new LinkedList<>(); pairs.add(null); pairs.add(new Pair<>(null, mockReferencedTypeOf(Number.class))); when(resolvedReferenceType.getTypeParametersMap()).thenReturn(pairs); Schema schema = schemaResolver.parseResolvedTypeToSchema(resolvedType); Assert.assertTrue(schema instanceof MapSchema); Assert.assertNull(schema.getNullable()); Assert.assertTrue( schema.getAdditionalProperties() instanceof NumberSchema); Assert.assertTrue(schemaResolver.getFoundTypes().isEmpty()); }
Example #4
Source File: FieldHelper.java From apigcc with MIT License | 6 votes |
/** * 获取真实的属性类型 * @param parent * @param field * @return */ public static ResolvedType getActuallyType(ResolvedReferenceType parent, ResolvedFieldDeclaration field) { ResolvedType type = field.getType(); if (type.isReferenceType()) { //将父类的T,传递给 属性的T return ClassHelper.useClassTypeParameter(parent, type.asReferenceType()); } if (type.isTypeVariable()) { //类型为T,这种泛型 Optional<ResolvedType> optional = ClassHelper.getTypeParameter(parent, field.getType().asTypeParameter().getName()); if (optional.isPresent()) { return optional.get(); } } return type; }
Example #5
Source File: SchemaResolverTest.java From flow with Apache License 2.0 | 6 votes |
@Test public void should_ReturnNotNullableArray_When_GivenTypeIsAListString() { ResolvedType resolvedType = mockReferencedTypeOf(Collection.class); ResolvedReferenceType resolvedReferenceType = resolvedType .asReferenceType(); List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> pairs = Collections .singletonList( new Pair<>(null, mockReferencedTypeOf(String.class))); when(resolvedReferenceType.getTypeParametersMap()).thenReturn(pairs); Schema schema = schemaResolver.parseResolvedTypeToSchema(resolvedType); Assert.assertTrue(schema instanceof ArraySchema); Assert.assertNull(schema.getNullable()); Assert.assertTrue( ((ArraySchema) schema).getItems() instanceof StringSchema); Assert.assertTrue(schemaResolver.getFoundTypes().isEmpty()); }
Example #6
Source File: RefactoringHelper.java From Refactoring-Bot with MIT License | 6 votes |
/** * Get all direct and indirect ancestors of a given class if possible (if * ancestor is not a external dependency for example). * * This is a modified (fallback) implementation of * ResolvedReferenceTypeDeclaration.getAllAncestors() that we use in case, for * example, that external classes are extended (which would throw an * UnresolvedSymbolException). * * @param resolvedClass * @return ancestors */ private static List<ResolvedReferenceType> getAllResolvableAncestors( ResolvedReferenceTypeDeclaration resolvedClass) { List<ResolvedReferenceType> ancestors = new ArrayList<>(); if (!(Object.class.getCanonicalName().equals(resolvedClass.getQualifiedName()))) { // Get all direct ancestors that can be resolved for (ResolvedReferenceType ancestor : resolvedClass.getAncestors(true)) { ancestors.add(ancestor); // Get indirect ancestors recursively for (ResolvedReferenceType inheritedAncestor : getAllResolvableAncestors( ancestor.getTypeDeclaration())) { if (!ancestors.contains(inheritedAncestor)) { ancestors.add(inheritedAncestor); } } } } return ancestors; }
Example #7
Source File: OpenApiObjectGenerator.java From flow with Apache License 2.0 | 6 votes |
/** * This method return a fully qualified name from a resolved reference type * which is correct for nested declaration as well. The * {@link ResolvedReferenceType#getQualifiedName()} returns a canonical name * instead of a fully qualified name, which is not correct for nested * classes to be used in reflection. That's why this method is implemented. * * {@see Related discussion about FullyQualifiedName and CanonicalName: * https://github.com/javaparser/javaparser/issues/1480} * * @param resolvedReferenceType * the type to get fully qualified name * @return fully qualified name */ private String getFullyQualifiedName( ResolvedReferenceType resolvedReferenceType) { ResolvedReferenceTypeDeclaration typeDeclaration = resolvedReferenceType .getTypeDeclaration(); String packageName = typeDeclaration.getPackageName(); String canonicalName = typeDeclaration.getQualifiedName(); if (GeneratorUtils.isBlank(packageName)) { return GeneratorUtils.replaceChars(canonicalName, '.', '$'); } else { String name = GeneratorUtils.substringAfterLast(canonicalName, packageName + "."); return String.format("%s.%s", packageName, GeneratorUtils.replaceChars(name, '.', '$')); } }
Example #8
Source File: PrimitiveTypeDescription.java From apigcc with MIT License | 5 votes |
public PrimitiveTypeDescription(ResolvedReferenceType referenceType){ switch (referenceType.getId()){ case "java.lang.Byte": value = (byte) 0; type = "byte"; break; case "java.lang.Short": value = (short) 0; type = "short"; break; case "java.lang.Integer": value = 0; type = "int"; break; case "java.lang.Long": value = 0L; type = "long"; break; case "java.lang.Float": value = 0f; type = "float"; break; case "java.lang.Double": value = 0d; type = "double"; break; case "java.lang.Character": value = (char)0; type = "char"; break; case "java.lang.Boolean": value = false; type = "boolean"; break; } }
Example #9
Source File: SchemaResolverTest.java From flow with Apache License 2.0 | 5 votes |
private ResolvedType mockReferencedTypeOf(Class clazz) { ResolvedType resolvedType = mock(ResolvedType.class); ResolvedReferenceType resolvedReferenceType = mock( ResolvedReferenceType.class); when(resolvedType.isPrimitive()).thenReturn(false); when(resolvedType.isReferenceType()).thenReturn(true); when(resolvedType.asReferenceType()).thenReturn(resolvedReferenceType); when(resolvedReferenceType.getQualifiedName()) .thenReturn(clazz.getCanonicalName()); return resolvedType; }
Example #10
Source File: OpenApiObjectGenerator.java From flow with Apache License 2.0 | 5 votes |
private Class<?> getClassFromReflection(ResolvedReferenceType resolvedType) throws ClassNotFoundException { String fullyQualifiedName = getFullyQualifiedName(resolvedType); if (typeResolverClassLoader != null) { return Class.forName(fullyQualifiedName, true, typeResolverClassLoader); } else { return Class.forName(fullyQualifiedName); } }
Example #11
Source File: OpenApiObjectGenerator.java From flow with Apache License 2.0 | 5 votes |
/** * Because it's not possible to check the `transient` modifier and * annotation of a field using JavaParser API. We need this method to * reflect the type and get those information from the reflected object. * * @param resolvedType * type of the class to get fields information * @return set of fields' name that we should generate. */ private Map<String, Boolean> getFieldsAndOptionalMap( ResolvedReferenceType resolvedType) { if (!resolvedType.getTypeDeclaration().isClass() || resolvedType.getTypeDeclaration().isAnonymousClass()) { return Collections.emptyMap(); } HashMap<String, Boolean> validFields = new HashMap<>(); try { Class<?> aClass = getClassFromReflection(resolvedType); Arrays.stream(aClass.getDeclaredFields()).filter(field -> { int modifiers = field.getModifiers(); return !Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers) && !field.isAnnotationPresent(JsonIgnore.class); }).forEach(field -> validFields.put(field.getName(), field.isAnnotationPresent(Nullable.class) || field.getType().equals(Optional.class))); } catch (ClassNotFoundException e) { String message = String.format( "Can't get list of fields from class '%s'." + "Please make sure that class '%s' is in your project's compile classpath. " + "As the result, the generated TypeScript file will be empty.", resolvedType.getQualifiedName(), resolvedType.getQualifiedName()); getLogger().info(message); getLogger().debug(message, e); } return validFields; }
Example #12
Source File: OpenApiObjectGenerator.java From flow with Apache License 2.0 | 5 votes |
@SuppressWarnings("squid:S1872") private List<Schema> parseReferencedTypeAsSchema( ResolvedReferenceType resolvedType) { List<Schema> results = new ArrayList<>(); Schema schema = createSingleSchemaFromResolvedType(resolvedType); String qualifiedName = resolvedType.getQualifiedName(); generatedSchema.add(qualifiedName); List<ResolvedReferenceType> directAncestors = resolvedType .getDirectAncestors().stream() .filter(parent -> parent.getTypeDeclaration().isClass() && !Object.class.getName() .equals(parent.getQualifiedName())) .collect(Collectors.toList()); if (directAncestors.isEmpty() || resolvedType.getTypeDeclaration().isEnum()) { results.add(schema); results.addAll(generatedRelatedSchemas(schema)); } else { ComposedSchema parentSchema = new ComposedSchema(); parentSchema.name(qualifiedName); results.add(parentSchema); for (ResolvedReferenceType directAncestor : directAncestors) { String ancestorQualifiedName = directAncestor .getQualifiedName(); String parentRef = schemaResolver .getFullQualifiedNameRef(ancestorQualifiedName); parentSchema.addAllOfItem(new ObjectSchema().$ref(parentRef)); schemaResolver.addFoundTypes(ancestorQualifiedName, directAncestor); } parentSchema.addAllOfItem(schema); results.addAll(generatedRelatedSchemas(parentSchema)); } return results; }
Example #13
Source File: OpenApiObjectGenerator.java From flow with Apache License 2.0 | 5 votes |
private Map<String, ResolvedReferenceType> collectUsedTypesFromSchema( Schema schema) { Map<String, ResolvedReferenceType> map = new HashMap<>(); if (GeneratorUtils.isNotBlank(schema.getName()) || GeneratorUtils.isNotBlank(schema.get$ref())) { String name = GeneratorUtils.firstNonBlank(schema.getName(), schemaResolver.getSimpleRef(schema.get$ref())); ResolvedReferenceType resolvedReferenceType = schemaResolver .getFoundTypeByQualifiedName(name); if (resolvedReferenceType != null) { map.put(name, resolvedReferenceType); } else { getLogger().info( "Can't find the type information of class '{}'. " + "This might result in a missing schema in the generated OpenAPI spec.", name); } } if (schema instanceof ArraySchema) { map.putAll(collectUsedTypesFromSchema( ((ArraySchema) schema).getItems())); } else if (schema instanceof MapSchema && schema.getAdditionalProperties() != null) { map.putAll(collectUsedTypesFromSchema( (Schema) schema.getAdditionalProperties())); } else if (schema instanceof ComposedSchema && ((ComposedSchema) schema).getAllOf() != null) { for (Schema child : ((ComposedSchema) schema).getAllOf()) { map.putAll(collectUsedTypesFromSchema(child)); } } if (schema.getProperties() != null) { schema.getProperties().values().forEach( o -> map.putAll(collectUsedTypesFromSchema((Schema) o))); } return map; }
Example #14
Source File: OpenApiObjectGenerator.java From flow with Apache License 2.0 | 5 votes |
private List<Schema> createSchemasFromQualifiedNameAndType( String qualifiedName, ResolvedReferenceType resolvedReferenceType) { List<Schema> list = parseNonEndpointClassAsSchema(qualifiedName); if (list.isEmpty()) { return parseReferencedTypeAsSchema(resolvedReferenceType); } else { return list; } }
Example #15
Source File: OpenApiObjectGenerator.java From flow with Apache License 2.0 | 5 votes |
private List<Schema> parseNonEndpointClassAsSchema( String fullQualifiedName) { TypeDeclaration<?> typeDeclaration = nonEndpointMap.get(fullQualifiedName); if (typeDeclaration == null || typeDeclaration.isEnumDeclaration()) { return Collections.emptyList(); } List<Schema> result = new ArrayList<>(); Schema schema = createSingleSchema(fullQualifiedName, typeDeclaration); generatedSchema.add(fullQualifiedName); NodeList<ClassOrInterfaceType> extendedTypes = null; if (typeDeclaration.isClassOrInterfaceDeclaration()) { extendedTypes = typeDeclaration.asClassOrInterfaceDeclaration() .getExtendedTypes(); } if (extendedTypes == null || extendedTypes.isEmpty()) { result.add(schema); result.addAll(generatedRelatedSchemas(schema)); } else { ComposedSchema parentSchema = new ComposedSchema(); parentSchema.setName(fullQualifiedName); result.add(parentSchema); extendedTypes.forEach(parentType -> { ResolvedReferenceType resolvedParentType = parentType.resolve(); String parentQualifiedName = resolvedParentType .getQualifiedName(); String parentRef = schemaResolver .getFullQualifiedNameRef(parentQualifiedName); parentSchema.addAllOfItem(new ObjectSchema().$ref(parentRef)); schemaResolver.addFoundTypes(parentQualifiedName, resolvedParentType); }); // The inserting order matters for `allof` property. parentSchema.addAllOfItem(schema); result.addAll(generatedRelatedSchemas(parentSchema)); } return result; }
Example #16
Source File: OpenApiObjectGenerator.java From flow with Apache License 2.0 | 5 votes |
private void init() { if (javaSourcePaths == null || configuration == null) { throw new IllegalStateException( "Java source path and configuration should not be null"); } openApiModel = createBasicModel(); nonEndpointMap = new HashMap<>(); qualifiedNameToPath = new HashMap<>(); pathItems = new TreeMap<>(); usedTypes = new HashMap<>(); generatedSchema = new HashSet<>(); endpointsJavadoc = new HashMap<>(); schemaResolver = new SchemaResolver(); ParserConfiguration parserConfiguration = createParserConfiguration(); javaSourcePaths.stream() .map(path -> new SourceRoot(path, parserConfiguration)) .forEach(this::parseSourceRoot); for (Map.Entry<String, ResolvedReferenceType> entry : usedTypes .entrySet()) { List<Schema> schemas = createSchemasFromQualifiedNameAndType( entry.getKey(), entry.getValue()); schemas.forEach(schema -> { if (qualifiedNameToPath.get(schema.getName()) != null) { schema.addExtension(EXTENSION_VAADIN_FILE_PATH, qualifiedNameToPath.get(schema.getName())); } openApiModel.getComponents().addSchemas(schema.getName(), schema); }); } addTagsInformation(); }
Example #17
Source File: SchemaResolver.java From flow with Apache License 2.0 | 5 votes |
private Schema createEnumTypeSchema(ResolvedType resolvedType) { ResolvedReferenceType type = resolvedType.asReferenceType(); List<String> entries = type .getTypeDeclaration().asEnum().getEnumConstants().stream() .map(ResolvedEnumConstantDeclaration::getName) .collect(Collectors.toList()); String qualifiedName = type.getQualifiedName(); foundTypes.put(qualifiedName, type); StringSchema schema = new StringSchema(); schema.name(qualifiedName); schema.setEnum(entries); schema.$ref(getFullQualifiedNameRef(qualifiedName)); return schema; }
Example #18
Source File: SchemaResolver.java From flow with Apache License 2.0 | 5 votes |
private boolean isTypeOf(ResolvedType type, Class... clazz) { if (!type.isReferenceType()) { return false; } List<String> classes = Arrays.stream(clazz).map(Class::getName) .collect(Collectors.toList()); return classes.contains(type.asReferenceType().getQualifiedName()) || type.asReferenceType().getAllAncestors().stream() .map(ResolvedReferenceType::getQualifiedName) .anyMatch(classes::contains); }
Example #19
Source File: SchemaResolver.java From flow with Apache License 2.0 | 5 votes |
private Schema createCollectionSchema(ResolvedReferenceType type) { ArraySchema array = new ArraySchema(); List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> typeParametersMap = type .getTypeParametersMap(); if (!typeParametersMap.isEmpty()) { ResolvedType collectionParameterType = typeParametersMap.get(0).b; array.items(parseResolvedTypeToSchema(collectionParameterType)); } return array; }
Example #20
Source File: RefactoringHelper.java From Refactoring-Bot with MIT License | 5 votes |
/** * @param targetClass * @param targetMethod * @return list of resolved classes and interfaces which are ancestors of the * given classes (not including java.lang.Object or external * dependencies) and contain the given target method * @throws BotRefactoringException */ private static Set<ResolvedReferenceTypeDeclaration> findAllAncestors(ClassOrInterfaceDeclaration targetClass, MethodDeclaration targetMethod) throws BotRefactoringException { List<ResolvedReferenceType> ancestors = new ArrayList<>(); Set<ResolvedReferenceTypeDeclaration> result = new HashSet<>(); try { ancestors = targetClass.resolve().getAllAncestors(); } catch (UnsolvedSymbolException u) { ancestors = RefactoringHelper.getAllResolvableAncestors(targetClass.resolve()); logger.warn("Refactored classes might extend/implement classes or interfaces from external dependency! " + "Please validate the correctness of the refactoring."); // TODO propagate warning } catch (InvalidPathException i) { throw new BotRefactoringException("Javaparser could not parse file: " + i.getMessage()); } catch (Exception e) { throw new BotRefactoringException("Error while resolving superclasses occured!"); } for (ResolvedReferenceType ancestor : ancestors) { if (!ancestor.getQualifiedName().equals("java.lang.Object")) { for (ResolvedMethodDeclaration method : ancestor.getAllMethods()) { if (method.getSignature().equals(targetMethod.resolve().getSignature())) { result.add(ancestor.getTypeDeclaration()); } } } } return result; }
Example #21
Source File: ClassHelper.java From apigcc with MIT License | 5 votes |
/** * 使用父类的泛型 解析当前类 * @param parent * @param field */ public static ResolvedType useClassTypeParameter(ResolvedReferenceType parent, ResolvedReferenceType field){ for (Pair<ResolvedTypeParameterDeclaration, ResolvedType> pair : field.getTypeParametersMap()) { if(pair.b.isTypeVariable()){ Optional<ResolvedType> typeParameter = getTypeParameter(parent, pair.b.asTypeVariable().describe()); if (typeParameter.isPresent()) { return field.replaceTypeVariables(pair.b.asTypeVariable().asTypeParameter(), typeParameter.get()); } } } return field; }
Example #22
Source File: ClassHelper.java From apigcc with MIT License | 5 votes |
/** * 获取泛型信息 * @param referenceType * @param a 如 T E 等 * @return */ public static Optional<ResolvedType> getTypeParameter(ResolvedReferenceType referenceType, String a){ List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> typeParameters = referenceType.getTypeParametersMap(); for (Pair<ResolvedTypeParameterDeclaration, ResolvedType> pair : typeParameters) { if(Objects.equals(pair.a.getName(),a)){ return Optional.of(pair.b); } } return Optional.empty(); }
Example #23
Source File: ClassHelper.java From apigcc with MIT License | 5 votes |
/** * 获取泛型信息 * @param referenceType * @param index 位置信息 * @return */ public static Optional<ResolvedType> getTypeParameter(ResolvedReferenceType referenceType, int index){ List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> typeParameters = referenceType.getTypeParametersMap(); if(typeParameters.size()>index){ Pair<ResolvedTypeParameterDeclaration, ResolvedType> pair = typeParameters.get(index); return Optional.of(pair.b); } return Optional.empty(); }
Example #24
Source File: ObjectTypeResolver.java From apigcc with MIT License | 5 votes |
@Override public TypeDescription resolve(ResolvedType type) { ObjectTypeDescription typeDescription = new ObjectTypeDescription(); ResolvedReferenceType referenceType = type.asReferenceType(); typeDescription.setType(referenceType.getTypeDeclaration().getName()); if (!ReferenceContext.getInstance().push(referenceType.describe())) { //类型解析缓冲池,防止循环引用 return typeDescription; } //解析父类属性,并合并至当前 for (ResolvedReferenceType directAncestor : referenceType.getDirectAncestors()) { TypeDescription ancestorDescription = Apigcc.getInstance().getTypeResolvers().resolve(directAncestor); if (ancestorDescription.isAvailable() && ancestorDescription.isObject()) { typeDescription.merge(ancestorDescription.asObject()); } } //TODO fix use access method for (ResolvedFieldDeclaration declaredField : referenceType.getTypeDeclaration().getDeclaredFields()) { if (declaredField.isStatic()) { continue; } ResolvedType fieldType = FieldHelper.getActuallyType(referenceType, declaredField); TypeDescription fieldDescription = Apigcc.getInstance().getTypeResolvers().resolve(fieldType); fieldDescription.setKey(declaredField.getName()); JsonPropertyHelper.getJsonName(declaredField).ifPresent(fieldDescription::setKey); CommentHelper.getComment(declaredField).ifPresent(fieldDescription::accept); fieldDescription.addConditions(ValidationHelper.getValidations(declaredField)); FieldHelper.getInitializerValue(declaredField).ifPresent(fieldDescription::setDefaultValue); typeDescription.add(fieldDescription); } ReferenceContext.getInstance().remove(referenceType.describe()); return typeDescription; }
Example #25
Source File: SchemaResolver.java From flow with Apache License 2.0 | 4 votes |
Map<String, ResolvedReferenceType> getFoundTypes() { return foundTypes; }
Example #26
Source File: SchemaResolver.java From flow with Apache License 2.0 | 4 votes |
ResolvedReferenceType getFoundTypeByQualifiedName(String qualifiedName) { return foundTypes.get(qualifiedName); }
Example #27
Source File: SchemaResolver.java From flow with Apache License 2.0 | 4 votes |
void addFoundTypes(String qualifiedName, ResolvedReferenceType type) { foundTypes.put(qualifiedName, type); }
Example #28
Source File: SchemaResolver.java From flow with Apache License 2.0 | 4 votes |
private Schema createOptionalSchema(ResolvedReferenceType type) { ResolvedType typeInOptional = type.getTypeParametersMap().get(0).b; Schema nestedTypeSchema = parseResolvedTypeToSchema(typeInOptional); return createNullableWrapper(nestedTypeSchema); }
Example #29
Source File: MemberExplorer.java From jeddict with Apache License 2.0 | 4 votes |
private ResolvedReferenceType getReferenceType() { return field.getElementType().resolve().asReferenceType(); }
Example #30
Source File: AnnotatedMember.java From jeddict with Apache License 2.0 | 4 votes |
static Optional<ResolvedTypeDeclaration> getResolvedClassAttribute(AnnotationExpr annotationExpr, String attributeName) { return getTypeClassAttribute(annotationExpr, attributeName) .map(Type::resolve) .map(ResolvedType::asReferenceType) .map(ResolvedReferenceType::getTypeDeclaration); }