From f5f478332602755b7e5cdf869877b6019bf25217 Mon Sep 17 00:00:00 2001 From: Michael Edgar Date: Thu, 11 Aug 2022 05:41:28 -0400 Subject: [PATCH] Update OpenAPI auto-tag processing to account for SR 2.2.0 changes Save method hashes based on resource implementation classes and both the concrete and (potentially) abstract methods. --- .../deployment/SmallRyeOpenApiProcessor.java | 50 ++++++++++--------- .../test/jaxrs/AutoTagFetchableResource.java | 16 ++++++ .../openapi/test/jaxrs/AutoTagResource.java | 15 ++++-- .../openapi/test/jaxrs/AutoTagTestCase.java | 29 ++++------- 4 files changed, 66 insertions(+), 44 deletions(-) create mode 100644 extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagFetchableResource.java diff --git a/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/SmallRyeOpenApiProcessor.java b/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/SmallRyeOpenApiProcessor.java index 2501b3d19c034c..64617f16de9125 100644 --- a/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/SmallRyeOpenApiProcessor.java +++ b/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/SmallRyeOpenApiProcessor.java @@ -535,10 +535,11 @@ private List getAuthenticatedMethodReferences( } private Map getClassNamesMethodReferences(OpenApiFilteredIndexViewBuildItem apiFilteredIndexViewBuildItem) { + FilteredIndexView filteredIndex = apiFilteredIndexViewBuildItem.getIndex(); List openapiAnnotations = new ArrayList<>(); Set allOpenAPIEndpoints = getAllOpenAPIEndpoints(); for (DotName dotName : allOpenAPIEndpoints) { - openapiAnnotations.addAll(apiFilteredIndexViewBuildItem.getIndex().getAnnotations(dotName)); + openapiAnnotations.addAll(filteredIndex.getAnnotations(dotName)); } Map classNames = new HashMap<>(); @@ -546,35 +547,38 @@ private Map getClassNamesMethodReferences(OpenApiFilteredIndexVi for (AnnotationInstance ai : openapiAnnotations) { if (ai.target().kind().equals(AnnotationTarget.Kind.METHOD)) { MethodInfo method = ai.target().asMethod(); - if (Modifier.isInterface(method.declaringClass().flags())) { - Collection allKnownImplementors = apiFilteredIndexViewBuildItem.getIndex() - .getAllKnownImplementors(method.declaringClass().name()); - for (ClassInfo impl : allKnownImplementors) { - MethodInfo implMethod = impl.method(method.name(), method.parameterTypes().toArray(new Type[] {})); - if (implMethod != null) { - String implRef = JandexUtil.createUniqueMethodReference(impl, method); - classNames.put(implRef, impl.simpleName()); - } - } - } else if (Modifier.isAbstract(method.declaringClass().flags())) { - Collection allKnownSubclasses = apiFilteredIndexViewBuildItem.getIndex() - .getAllKnownSubclasses(method.declaringClass().name()); - for (ClassInfo impl : allKnownSubclasses) { - MethodInfo implMethod = impl.method(method.name(), method.parameterTypes().toArray(new Type[] {})); - if (implMethod != null) { - String implRef = JandexUtil.createUniqueMethodReference(impl, method); - classNames.put(implRef, impl.simpleName()); - } - } + ClassInfo declaringClass = method.declaringClass(); + Type[] params = method.parameterTypes().toArray(new Type[] {}); + + if (Modifier.isInterface(declaringClass.flags())) { + addMethodImplementationClassNames(method, params, filteredIndex + .getAllKnownImplementors(declaringClass.name()), classNames); + } else if (Modifier.isAbstract(declaringClass.flags())) { + addMethodImplementationClassNames(method, params, filteredIndex + .getAllKnownSubclasses(declaringClass.name()), classNames); } else { - String ref = JandexUtil.createUniqueMethodReference(method.declaringClass(), method); - classNames.put(ref, method.declaringClass().simpleName()); + String ref = JandexUtil.createUniqueMethodReference(declaringClass, method); + classNames.put(ref, declaringClass.simpleName()); } } } return classNames; } + void addMethodImplementationClassNames(MethodInfo method, Type[] params, Collection classes, + Map classNames) { + for (ClassInfo impl : classes) { + String simpleClassName = impl.simpleName(); + MethodInfo implMethod = impl.method(method.name(), params); + + if (implMethod != null) { + classNames.put(JandexUtil.createUniqueMethodReference(impl, implMethod), simpleClassName); + } + + classNames.put(JandexUtil.createUniqueMethodReference(impl, method), simpleClassName); + } + } + private boolean isValidOpenAPIMethodForAutoAdd(MethodInfo method, DotName securityRequirement) { return isOpenAPIEndpoint(method) && !method.hasAnnotation(securityRequirement) && method.declaringClass().classAnnotation(securityRequirement) == null; diff --git a/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagFetchableResource.java b/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagFetchableResource.java new file mode 100644 index 00000000000000..bdacd069266163 --- /dev/null +++ b/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagFetchableResource.java @@ -0,0 +1,16 @@ +package io.quarkus.smallrye.openapi.test.jaxrs; + +import java.util.List; + +import javax.ws.rs.GET; + +public abstract class AutoTagFetchableResource implements AbstractAutoTagResource { + + @GET + abstract List getAll(); + + @Override + public T getById(long id) { + return null; + } +} diff --git a/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagResource.java b/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagResource.java index b01b89aecb6c26..0412d7d6b93c01 100644 --- a/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagResource.java +++ b/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagResource.java @@ -1,11 +1,20 @@ package io.quarkus.smallrye.openapi.test.jaxrs; +import java.util.List; + import javax.ws.rs.Path; -@Path("/address") -public class AutoTagResource implements AbstractAutoTagResource { +@Path("/tagged") +public class AutoTagResource extends AutoTagFetchableResource { + @Override public String getById(long id) { return "Disney Land, Gate " + id; } -} \ No newline at end of file + + @Override + public List getAll() { + return null; + } + +} diff --git a/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagTestCase.java b/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagTestCase.java index 126c8fc2eda398..2d259fdf3173d8 100644 --- a/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagTestCase.java +++ b/extensions/smallrye-openapi/deployment/src/test/java/io/quarkus/smallrye/openapi/test/jaxrs/AutoTagTestCase.java @@ -7,34 +7,27 @@ import io.quarkus.test.QuarkusUnitTest; import io.restassured.RestAssured; -public class AutoTagTestCase { +class AutoTagTestCase { @RegisterExtension static QuarkusUnitTest runner = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar - .addClasses(OpenApiResourceWithNoTag.class, AutoTagResource.class, AbstractAutoTagResource.class)); + .addClasses(OpenApiResourceWithNoTag.class, AutoTagResource.class, AutoTagFetchableResource.class, + AbstractAutoTagResource.class)); @Test - public void testAutoSecurityRequirement() { + void testTagInOpenApi() { RestAssured.given().header("Accept", "application/json") - .when().get("/q/openapi") + .when() + .get("/q/openapi") .then() - .log().body() - .and() + .log().ifValidationFails() + .assertThat() + .statusCode(200) + .body("paths.'/tagged'.get.tags", Matchers.hasItem("Auto Tag Resource")) + .body("paths.'/tagged/{id}'.get.tags", Matchers.hasItem("Auto Tag Resource")) .body("paths.'/resource/annotated'.get.tags", Matchers.hasItem("From Annotation")) - .and() .body("paths.'/resource/auto'.get.tags", Matchers.hasItem("Open Api Resource With No Tag")) - .and() .body("paths.'/resource/auto'.post.tags", Matchers.hasItem("Open Api Resource With No Tag")); - - } - - @Test - public void testTagInOpenApi() { - RestAssured.given().header("Accept", "application/json") - .when().get("/q/openapi") - .then() - .statusCode(200) - .body(Matchers.containsString("Auto Tag Resource")); } }