Explode query params for kotlin generator (#13154)

This commit is contained in:
Sorin Florea 2022-08-24 17:33:31 +02:00 committed by GitHub
parent 1fbc047478
commit 2d73a4df2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 28 deletions

View File

@ -60,10 +60,7 @@ interface {{classname}} {
* {{notes}} * {{notes}}
* Responses:{{#responses}} * Responses:{{#responses}}
* - {{code}}: {{{message}}}{{/responses}} * - {{code}}: {{{message}}}{{/responses}}
* *{{>paramJavadoc}}
{{#allParams}}
* @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}}
{{/allParams}}
* @return {{^useCoroutines}}[Call]<{{/useCoroutines}}{{#isResponseFile}}[ResponseBody]{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}[{{{.}}}]{{/returnType}}{{^returnType}}[Unit]{{/returnType}}{{/isResponseFile}}{{^useCoroutines}}>{{/useCoroutines}} * @return {{^useCoroutines}}[Call]<{{/useCoroutines}}{{#isResponseFile}}[ResponseBody]{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}[{{{.}}}]{{/returnType}}{{^returnType}}[Unit]{{/returnType}}{{/isResponseFile}}{{^useCoroutines}}>{{/useCoroutines}}
*/ */
{{#isDeprecated}} {{#isDeprecated}}

View File

@ -0,0 +1 @@
@Query("{{baseName}}") {{{baseName}}}: {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}}{{#required}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}{{/required}}{{^required}}?{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}

View File

@ -0,0 +1,5 @@
{{#allParams}}{{#isDeepObject}}
* @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}}{{/isDeepObject}}{{^isDeepObject}}{{#isExplode}}{{#hasVars}}{{#vars}}
* @param {{{baseName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}}{{/vars}}{{/hasVars}}{{^hasVars}}
* @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}}{{/hasVars}}{{/isExplode}}{{^isExplode}}
* @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}}{{/isExplode}}{{/isDeepObject}}{{/allParams}}

View File

@ -0,0 +1 @@
@Query("{{baseName}}") {{{paramName}}}: {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}}{{#required}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}{{/required}}{{^required}}?{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}

View File

@ -1 +1 @@
{{#isQueryParam}}@Query("{{baseName}}") {{{paramName}}}: {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}}{{#required}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}{{/required}}{{^required}}?{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}{{/isQueryParam}} {{#isQueryParam}}{{#isDeepObject}}{{>queryParam}}{{/isDeepObject}}{{^isDeepObject}}{{#isExplode}}{{#hasVars}}{{#vars}}{{>explodedQueryParam}}{{^-last}}, {{/-last}}{{/vars}}{{/hasVars}}{{^hasVars}}{{>queryParam}}{{/hasVars}}{{/isExplode}}{{^isExplode}}{{>queryParam}}{{/isExplode}}{{/isDeepObject}}{{/isQueryParam}}

View File

@ -18,48 +18,66 @@
package org.openapitools.codegen.kotlin; package org.openapitools.codegen.kotlin;
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.*; import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.DateTimeSchema;
import io.swagger.v3.oas.models.media.IntegerSchema;
import io.swagger.v3.oas.models.media.MapSchema;
import io.swagger.v3.oas.models.media.ObjectSchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenProperty; import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.DefaultCodegen; import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.TestUtils; import org.openapitools.codegen.TestUtils;
import org.openapitools.codegen.config.CodegenConfigurator;
import org.openapitools.codegen.languages.KotlinClientCodegen; import org.openapitools.codegen.languages.KotlinClientCodegen;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SuppressWarnings("static-method") @SuppressWarnings("static-method")
public class KotlinClientCodegenModelTest { public class KotlinClientCodegenModelTest {
private Schema getArrayTestSchema() { private Schema getArrayTestSchema() {
return new ObjectSchema() return new ObjectSchema()
.description("a sample model") .description("a sample model")
.addProperties("id", new IntegerSchema().format("int64")) .addProperties("id", new IntegerSchema().format("int64"))
.addProperties("examples", new ArraySchema().items(new StringSchema())) .addProperties("examples", new ArraySchema().items(new StringSchema()))
.addRequiredItem("id"); .addRequiredItem("id");
} }
private Schema getSimpleSchema() { private Schema getSimpleSchema() {
return new ObjectSchema() return new ObjectSchema()
.description("a sample model") .description("a sample model")
.addProperties("id", new IntegerSchema().format("int64")) .addProperties("id", new IntegerSchema().format("int64"))
.addProperties("name", new StringSchema()) .addProperties("name", new StringSchema())
.addProperties("createdAt", new DateTimeSchema()) .addProperties("createdAt", new DateTimeSchema())
.addRequiredItem("id") .addRequiredItem("id")
.addRequiredItem("name"); .addRequiredItem("name");
} }
private Schema getMapSchema() { private Schema getMapSchema() {
return new ObjectSchema() return new ObjectSchema()
.description("a sample model") .description("a sample model")
.addProperties("mapping", new MapSchema() .addProperties("mapping", new MapSchema()
.additionalProperties(new StringSchema())); .additionalProperties(new StringSchema()));
} }
private Schema getComplexSchema() { private Schema getComplexSchema() {
return new ObjectSchema() return new ObjectSchema()
.description("a sample model") .description("a sample model")
.addProperties("child", new ObjectSchema().$ref("#/components/schemas/Child")); .addProperties("child", new ObjectSchema().$ref("#/components/schemas/Child"));
} }
@Test(description = "convert a simple model") @Test(description = "convert a simple model")
@ -321,11 +339,11 @@ public class KotlinClientCodegenModelTest {
@DataProvider(name = "modelNames") @DataProvider(name = "modelNames")
public static Object[][] modelNames() { public static Object[][] modelNames() {
return new Object[][]{ return new Object[][]{
{"TestNs.TestClass", new ModelNameTest("TestNs.TestClass", "TestNsTestClass")}, {"TestNs.TestClass", new ModelNameTest("TestNs.TestClass", "TestNsTestClass")},
{"$", new ModelNameTest("$", "Dollar")}, {"$", new ModelNameTest("$", "Dollar")},
{"for", new ModelNameTest("`for`", "For")}, {"for", new ModelNameTest("`for`", "For")},
{"One<Two", new ModelNameTest("One<Two", "OneLessThanTwo")}, {"One<Two", new ModelNameTest("One<Two", "OneLessThanTwo")},
{"this is a test", new ModelNameTest("this is a test", "ThisIsATest")} {"this is a test", new ModelNameTest("this is a test", "ThisIsATest")}
}; };
} }
@ -341,9 +359,34 @@ public class KotlinClientCodegenModelTest {
Assert.assertEquals(cm.classname, testCase.expectedClassName); Assert.assertEquals(cm.classname, testCase.expectedClassName);
} }
@Test
public void testNativeClientExplodedQueryParamObject() throws IOException {
Map<String, Object> properties = new HashMap<>();
properties.put(CodegenConstants.API_PACKAGE, "xyz.abcdef.api");
File output = Files.createTempDirectory("test").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("kotlin")
.setLibrary("jvm-retrofit2")
.setAdditionalProperties(properties)
.setInputSpec("src/test/resources/3_0/issue4808.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
Assert.assertEquals(files.size(), 28);
TestUtils.assertFileContains(Paths.get(output + "/src/main/kotlin/xyz/abcdef/api/DefaultApi.kt"),
"fun getSomeValue(@Query(\"since\") since: kotlin.String? = null, @Query(\"sinceBuild\") sinceBuild: kotlin.String? = null, @Query(\"maxBuilds\") maxBuilds: kotlin.Int? = null, @Query(\"maxWaitSecs\") maxWaitSecs: kotlin.Int? = null)"
);
}
private static class ModelNameTest { private static class ModelNameTest {
private String expectedName; private final String expectedName;
private String expectedClassName; private final String expectedClassName;
private ModelNameTest(String nameAndClass) { private ModelNameTest(String nameAndClass) {
this.expectedName = nameAndClass; this.expectedName = nameAndClass;