Skip to content

Commit

Permalink
Merge pull request #883 from MikeEdgar/848_kotlin_coroutine_context
Browse files Browse the repository at this point in the history
Support `kotlin.coroutines.Continuation` default response type
  • Loading branch information
phillip-kruger committed Aug 22, 2021
2 parents 82eca70 + cb58732 commit 4950ad4
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.smallrye.openapi.api.constants;

import org.jboss.jandex.DotName;

/**
* Constants related to the Kotlin language
*
* @author Michael Edgar {@literal <michael@xlate.io>}
*/
public class KotlinConstants {

public static final DotName CONTINUATION = DotName
.createSimple("kotlin.coroutines.Continuation");

private KotlinConstants() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.Type;
import org.jboss.jandex.Type.Kind;

import io.smallrye.openapi.api.OpenApiConfig.OperationIdStrategy;
import io.smallrye.openapi.api.constants.KotlinConstants;
import io.smallrye.openapi.api.constants.OpenApiConstants;
import io.smallrye.openapi.api.constants.SecurityConstants;
import io.smallrye.openapi.api.models.OperationImpl;
Expand Down Expand Up @@ -410,8 +412,9 @@ default void createResponseFromRestMethod(final AnnotationScannerContext context
Schema schema;

if (isMultipartOutput(returnType)) {
schema = new SchemaImpl();
schema.setType(Schema.SchemaType.OBJECT);
schema = new SchemaImpl().type(Schema.SchemaType.OBJECT);
} else if (isKotlinContinuation(method)) {
schema = kotlinContinuationToSchema(context, method);
} else {
schema = SchemaFactory.typeToSchema(context, returnType, context.getExtensions());
}
Expand Down Expand Up @@ -492,6 +495,35 @@ default boolean isVoidResponse(final MethodInfo method) {
return false;
}

default boolean isKotlinContinuation(MethodInfo method) {
if (method.parameters().size() != 1) {
return false;
}

return KotlinConstants.CONTINUATION.equals(method.parameters().get(0).name());
}

default Schema kotlinContinuationToSchema(AnnotationScannerContext context, MethodInfo method) {
Schema schema;
Type type = context.getResourceTypeResolver().resolve(method.parameters().get(0));

if (type.kind() == Kind.PARAMETERIZED_TYPE) {
type = type.asParameterizedType().arguments().get(0);

if (type.kind() == Kind.WILDCARD_TYPE) {
Type extendsBound = type.asWildcardType().extendsBound();
Type superBound = type.asWildcardType().superBound();
type = superBound != null ? superBound : extendsBound;
}

schema = SchemaFactory.typeToSchema(context, type, context.getExtensions());
} else {
schema = new SchemaImpl().type(Schema.SchemaType.OBJECT);
}

return schema;
}

/**
* Determine if the default response information should be generated.
* It should be done when no responses have been declared or if the default
Expand Down
8 changes: 7 additions & 1 deletion extension-jaxrs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,13 @@
<scope>test</scope>
<type>pom</type>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-kotlin</artifactId>
<version>${version.quarkus}</version>
<scope>test</scope>
</dependency>

<!-- Depend on core tests -->
<dependency>
<groupId>${project.groupId}</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,42 @@ public jakarta.ws.rs.core.MultivaluedMap<String, Map<String, CustomResponse>> ge
NavigableMap.class,
HashMap.class);
}

@Test
void testKotlinContinuationStringResponse() throws IOException, JSONException {
@jakarta.ws.rs.Path("/hello")
class Resource {

/**
* Java equivalent of Kotlin function
* <code>
* suspend fun hello(): String {
* return "Hello RESTEasy Reactive"
* }
* </code>
*
* @param completion maps to Kotlin string return type when using `suspend`
* @return nothing
*/
@jakarta.ws.rs.GET
@jakarta.ws.rs.Path("/async")
@jakarta.ws.rs.Produces({ "text/plain" })
public Object hello1(kotlin.coroutines.Continuation<? super String> completion) {
return null;
}

@jakarta.ws.rs.GET
@jakarta.ws.rs.Path("/sync")
@jakarta.ws.rs.Produces({ "text/plain" })
public String hello2() {
return "Hello";
}
}

test("responses.kotlin-continuation.json",
Resource.class,
kotlin.coroutines.Continuation.class,
kotlin.coroutines.CoroutineContext.class);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"openapi": "3.0.3",
"paths": {
"/hello/async": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/hello/sync": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
}
}

0 comments on commit 4950ad4

Please sign in to comment.