Skip to content

Commit

Permalink
[Kotlin] client improvement / remove WildCards in client/server (#2862)
Browse files Browse the repository at this point in the history
  • Loading branch information
karismann authored and wing328 committed May 11, 2019
1 parent 9323cad commit ef26ce6
Show file tree
Hide file tree
Showing 58 changed files with 660 additions and 344 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Expand Up @@ -175,12 +175,14 @@ samples/client/petstore/typescript-angular/tsd-debug.log
# aspnetcore
samples/server/petstore/aspnetcore/.vs/
effective.pom

# kotlin
samples/client/petstore/kotlin/src/main/kotlin/test/
samples/client/petstore/kotlin-threetenbp/build
samples/client/petstore/kotlin-string/build
samples/server/petstore/kotlin-server/ktor/build
samples/openapi3/client/petstore/kotlin/build
samples/server/petstore/kotlin-server/ktor/build
samples/server/petstore/kotlin-springboot/build
\?

# haskell
Expand Down
6 changes: 3 additions & 3 deletions docs/generators/kotlin-server.md
Expand Up @@ -8,14 +8,14 @@ sidebar_label: kotlin-server
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|sourceFolder|source folder for generated code| |src/main/kotlin|
|packageName|Generated artifact package name.| |org.openapitools|
|packageName|Generated artifact package name.| |org.openapitools.server|
|apiSuffix|suffix for api classes| |Api|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|artifactId|Generated artifact id (name of jar).| |null|
|artifactId|Generated artifact id (name of jar).| |kotlin-server|
|artifactVersion|Generated artifact's package version.| |1.0.0|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
|parcelizeModels|toggle "@Parcelize" for generated models| |null|
|library|library template (sub-template) to use|<dl><dt>**ktor**</dt><dd>ktor framework</dd><dl>|ktor|
|library|library template (sub-template)|<dl><dt>**ktor**</dt><dd>ktor framework</dd><dl>|ktor|
|featureAutoHead|Automatically provide responses to HEAD requests for existing routes that have the GET verb defined.| |true|
|featureConditionalHeaders|Avoid sending content if client already has same content, by checking ETag or LastModified properties.| |false|
|featureHSTS|Avoid sending content if client already has same content, by checking ETag or LastModified properties.| |true|
Expand Down
4 changes: 2 additions & 2 deletions docs/generators/kotlin-spring.md
Expand Up @@ -11,7 +11,7 @@ sidebar_label: kotlin-spring
|packageName|Generated artifact package name.| |org.openapitools|
|apiSuffix|suffix for api classes| |Api|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|artifactId|Generated artifact id (name of jar).| |null|
|artifactId|Generated artifact id (name of jar).| |openapi-spring|
|artifactVersion|Generated artifact's package version.| |1.0.0|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
|parcelizeModels|toggle &quot;@Parcelize&quot; for generated models| |null|
Expand All @@ -26,4 +26,4 @@ sidebar_label: kotlin-spring
|serviceInterface|generate service interfaces to go alongside controllers. In most cases this option would be used to update an existing project, so not to override implementations. Useful to help facilitate the generation gap pattern| |false|
|serviceImplementation|generate stub service implementations that extends service interfaces. If this is set to true service interfaces will also be generated| |false|
|useBeanValidation|Use BeanValidation API annotations to validate data types| |true|
|library|library template (sub-template) to use|<dl><dt>**spring-boot**</dt><dd>Spring-boot Server application.</dd><dl>|spring-boot|
|library|library template (sub-template)|<dl><dt>**spring-boot**</dt><dd>Spring-boot Server application.</dd><dl>|spring-boot|
8 changes: 4 additions & 4 deletions docs/generators/kotlin.md
Expand Up @@ -8,12 +8,12 @@ sidebar_label: kotlin
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|sourceFolder|source folder for generated code| |src/main/kotlin|
|packageName|Generated artifact package name.| |org.openapitools|
|packageName|Generated artifact package name.| |org.openapitools.client|
|apiSuffix|suffix for api classes| |Api|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|artifactId|Generated artifact id (name of jar).| |null|
|artifactId|Generated artifact id (name of jar).| |kotlin-client|
|artifactVersion|Generated artifact's package version.| |1.0.0|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
|parcelizeModels|toggle &quot;@Parcelize&quot; for generated models| |null|
|dateLibrary|Option. Date library to use|<dl><dt>**string**</dt><dd>String</dd><dt>**java8**</dt><dd>Java 8 native JSR310</dd><dt>**threetenbp**</dt><dd>Threetenbp</dd><dl>|null|
|collectionType|Option. Collection type to use|<dl><dt>**array**</dt><dd>kotlin.Array</dd><dt>**list**</dt><dd>kotlin.collections.List</dd><dl>|null|
|dateLibrary|Option. Date library to use|<dl><dt>**string**</dt><dd>String</dd><dt>**java8**</dt><dd>Java 8 native JSR310</dd><dt>**threetenbp**</dt><dd>Threetenbp</dd><dl>|java8|
|collectionType|Option. Collection type to use|<dl><dt>**array**</dt><dd>kotlin.Array</dd><dt>**list**</dt><dd>kotlin.collections.List</dd><dl>|array|
Expand Up @@ -102,7 +102,7 @@ public JavaClientCodegen() {
apiPackage = "org.openapitools.client.api";
modelPackage = "org.openapitools.client.model";

// clioOptions default redifinition need to be updated
// cliOptions default redefinition need to be updated
updateOption(CodegenConstants.INVOKER_PACKAGE, this.getInvokerPackage());
updateOption(CodegenConstants.ARTIFACT_ID, this.getArtifactId());
updateOption(CodegenConstants.API_PACKAGE, apiPackage);
Expand Down
Expand Up @@ -21,8 +21,6 @@
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.SupportingFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.HashMap;
Expand All @@ -32,7 +30,6 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {

public static final String DATE_LIBRARY = "dateLibrary";
public static final String COLLECTION_TYPE = "collectionType";
private static final Logger LOGGER = LoggerFactory.getLogger(KotlinClientCodegen.class);

protected String dateLibrary = DateLibrary.JAVA8.value;
protected String collectionType = CollectionType.ARRAY.value;
Expand Down Expand Up @@ -69,6 +66,10 @@ public KotlinClientCodegen() {
artifactId = "kotlin-client";
packageName = "org.openapitools.client";

// cliOptions default redefinition need to be updated
updateOption(CodegenConstants.ARTIFACT_ID, this.artifactId);
updateOption(CodegenConstants.PACKAGE_NAME, this.packageName);

outputFolder = "generated-code" + File.separator + "kotlin-client";
modelTemplateFiles.put("model.mustache", ".kt");
apiTemplateFiles.put("api.mustache", ".kt");
Expand All @@ -78,21 +79,21 @@ public KotlinClientCodegen() {
apiPackage = packageName + ".apis";
modelPackage = packageName + ".models";

enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.camelCase;

CliOption dateLibrary = new CliOption(DATE_LIBRARY, "Option. Date library to use");
Map<String, String> dateOptions = new HashMap<>();
dateOptions.put(DateLibrary.THREETENBP.value, "Threetenbp");
dateOptions.put(DateLibrary.STRING.value, "String");
dateOptions.put(DateLibrary.JAVA8.value, "Java 8 native JSR310");
dateLibrary.setEnum(dateOptions);
dateLibrary.setDefault(this.dateLibrary);
cliOptions.add(dateLibrary);

CliOption collectionType = new CliOption(COLLECTION_TYPE, "Option. Collection type to use");
Map<String, String> collectionOptions = new HashMap<>();
collectionOptions.put(CollectionType.ARRAY.value, "kotlin.Array");
collectionOptions.put(CollectionType.LIST.value, "kotlin.collections.List");
collectionType.setEnum(collectionOptions);
collectionType.setDefault(this.collectionType);
cliOptions.add(collectionType);
}

Expand Down
Expand Up @@ -62,17 +62,22 @@ public KotlinServerCodegen() {

artifactId = "kotlin-server";
packageName = "org.openapitools.server";

// cliOptions default redefinition need to be updated
updateOption(CodegenConstants.ARTIFACT_ID, this.artifactId);
updateOption(CodegenConstants.PACKAGE_NAME, this.packageName);

outputFolder = "generated-code" + File.separator + "kotlin-server";
modelTemplateFiles.put("model.mustache", ".kt");
apiTemplateFiles.put("api.mustache", ".kt");
embeddedTemplateDir = templateDir = "kotlin-server";
apiPackage = packageName + ".apis";
modelPackage = packageName + ".models";

supportedLibraries.put("ktor", "ktor framework");
supportedLibraries.put(Constants.KTOR, "ktor framework");

// TODO: Configurable server engine. Defaults to netty in build.gradle.
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
CliOption library = new CliOption(CodegenConstants.LIBRARY, CodegenConstants.LIBRARY_DESC);
library.setDefault(DEFAULT_LIBRARY);
library.setEnum(supportedLibraries);

Expand Down Expand Up @@ -147,9 +152,9 @@ public void processOpts() {

// set default library to "ktor"
if (StringUtils.isEmpty(library)) {
this.setLibrary("ktor");
additionalProperties.put(CodegenConstants.LIBRARY, "ktor");
LOGGER.info("`library` option is empty. Default to 'ktor'.");
this.setLibrary(DEFAULT_LIBRARY);
additionalProperties.put(CodegenConstants.LIBRARY, DEFAULT_LIBRARY);
LOGGER.info("`library` option is empty. Default to " + DEFAULT_LIBRARY);
}

if (additionalProperties.containsKey(Constants.AUTOMATIC_HEAD_REQUESTS)) {
Expand Down Expand Up @@ -182,7 +187,7 @@ public void processOpts() {
additionalProperties.put(Constants.COMPRESSION, getCompressionFeatureEnabled());
}

Boolean generateApis = additionalProperties.containsKey(CodegenConstants.GENERATE_APIS) && (Boolean)additionalProperties.get(CodegenConstants.GENERATE_APIS);
boolean generateApis = additionalProperties.containsKey(CodegenConstants.GENERATE_APIS) && (Boolean)additionalProperties.get(CodegenConstants.GENERATE_APIS);
String packageFolder = (sourceFolder + File.separator + packageName).replace(".", File.separator);
String resourcesFolder = "src/main/resources"; // not sure this can be user configurable.

Expand Down Expand Up @@ -226,7 +231,7 @@ private void addMustacheLambdas(Map<String, Object> objs) {
if (objs.containsKey("lambda")) {
LOGGER.warn("A property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'. " +
"You'll likely need to use a custom template, " +
"see https://github.com/swagger-api/swagger-codegen#modifying-the-client-library-format. "); // TODO: update the URL
"see https://github.com/OpenAPITools/openapi-generator/blob/master/docs/templating.md. ");
objs.put("_lambda", lambdas);
} else {
objs.put("lambda", lambdas);
Expand Down
Expand Up @@ -87,6 +87,9 @@ public KotlinSpringServerCodegen() {
apiPackage = "org.openapitools.api";
modelPackage = "org.openapitools.model";

// cliOptions default redefinition need to be updated
updateOption(CodegenConstants.ARTIFACT_ID, this.artifactId);

// Use lists instead of arrays
typeMapping.put("array", "List");
typeMapping.put("string", "String");
Expand Down Expand Up @@ -149,7 +152,7 @@ public KotlinSpringServerCodegen() {
supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
setLibrary(SPRING_BOOT);

CliOption cliOpt = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
CliOption cliOpt = new CliOption(CodegenConstants.LIBRARY, CodegenConstants.LIBRARY_DESC);
cliOpt.setDefault(SPRING_BOOT);
cliOpt.setEnum(supportedLibraries);
cliOptions.add(cliOpt);
Expand Down
Expand Up @@ -2,7 +2,7 @@

## Requires

* Kotlin 1.3.20
* Kotlin 1.3.31
* Gradle 4.9

## Build
Expand Down
Expand Up @@ -4,7 +4,17 @@ package {{apiPackage}}
{{#imports}}import {{import}}
{{/imports}}

import {{packageName}}.infrastructure.*
import {{packageName}}.infrastructure.ApiClient
import {{packageName}}.infrastructure.ClientException
import {{packageName}}.infrastructure.ClientError
import {{packageName}}.infrastructure.ServerException
import {{packageName}}.infrastructure.ServerError
import {{packageName}}.infrastructure.MultiValueMap
import {{packageName}}.infrastructure.RequestConfig
import {{packageName}}.infrastructure.RequestMethod
import {{packageName}}.infrastructure.ResponseType
import {{packageName}}.infrastructure.Success
import {{packageName}}.infrastructure.toMultiValue
{{#threetenbp}}
import org.threeten.bp.LocalDateTime
{{/threetenbp}}
Expand All @@ -23,7 +33,7 @@ class {{classname}}(basePath: kotlin.String = "{{{basePath}}}") : ApiClient(base
fun {{operationId}}({{#allParams}}{{paramName}}: {{{dataType}}}{{^required}}?{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) : {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Unit{{/returnType}} {
val localVariableBody: kotlin.Any? = {{#hasBodyParam}}{{#bodyParams}}{{paramName}}{{/bodyParams}}{{/hasBodyParam}}{{^hasBodyParam}}{{^hasFormParams}}null{{/hasFormParams}}{{#hasFormParams}}mapOf({{#formParams}}"{{{baseName}}}" to "${{paramName}}"{{#hasMore}}, {{/hasMore}}{{/formParams}}){{/hasFormParams}}{{/hasBodyParam}}
val localVariableQuery: MultiValueMap = {{^hasQueryParams}}mapOf(){{/hasQueryParams}}{{#hasQueryParams}}mapOf({{#queryParams}}"{{paramName}}" to {{#isContainer}}toMultiValue({{paramName}}.toList(), "{{collectionFormat}}"){{/isContainer}}{{^isContainer}}listOf("${{paramName}}"){{/isContainer}}{{#hasMore}}, {{/hasMore}}{{/queryParams}}){{/hasQueryParams}}
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf({{#hasFormParams}}"Content-Type" to "multipart/form-data"{{/hasFormParams}}{{^hasHeaderParams}}){{/hasHeaderParams}}{{#hasHeaderParams}}{{#hasFormParams}}, {{/hasFormParams}}{{#headerParams}}"{{baseName}}" to {{#isContainer}}{{paramName}}.joinToString(separator = collectionDelimiter("{{collectionFormat}}")){{/isContainer}}{{^isContainer}}{{paramName}}.toString(){{/isContainer}}{{#hasMore}}, {{/hasMore}}{{/headerParams}}){{/hasHeaderParams}}
val localVariableHeaders: MutableMap<String, String> = mutableMapOf({{#hasFormParams}}"Content-Type" to {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{MediaType}}"{{/consumes.0}}{{/hasFormParams}}{{^hasHeaderParams}}){{/hasHeaderParams}}{{#hasHeaderParams}}{{#hasFormParams}}, {{/hasFormParams}}{{#headerParams}}"{{baseName}}" to {{#isContainer}}{{paramName}}.joinToString(separator = collectionDelimiter("{{collectionFormat}}")){{/isContainer}}{{^isContainer}}{{paramName}}.toString(){{/isContainer}}{{#hasMore}}, {{/hasMore}}{{/headerParams}}){{/hasHeaderParams}}
val localVariableConfig = RequestConfig(
RequestMethod.{{httpMethod}},
"{{path}}"{{#pathParams}}.replace("{"+"{{baseName}}"+"}", "${{paramName}}"){{/pathParams}},
Expand Down
Expand Up @@ -7,7 +7,7 @@ wrapper {
}

buildscript {
ext.kotlin_version = '1.3.20'
ext.kotlin_version = '1.3.31'
repositories {
mavenCentral()
Expand All @@ -32,7 +32,7 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
compile "com.squareup.moshi:moshi-kotlin:1.5.0"
compile "com.squareup.moshi:moshi-adapters:1.5.0"
compile "com.squareup.okhttp3:okhttp:3.8.0"
compile "org.threeten:threetenbp:1.3.6"
compile "com.squareup.okhttp3:okhttp:3.14.0"
compile "org.threeten:threetenbp:1.3.8"
testImplementation "io.kotlintest:kotlintest-runner-junit5:3.1.0"
}

0 comments on commit ef26ce6

Please sign in to comment.