Skip to content

Upgrade multiplatform libraries #7149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,11 @@ 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/client/petstore/kotlin*/build
samples/client/petstore/kotlin*/.gradle
samples/openapi3/client/petstore/kotlin/build
samples/server/petstore/kotlin-server/ktor/build
samples/server/petstore/kotlin-springboot/build
samples/client/petstore/kotlin-multiplatform/build/
samples/client/petstore/kotlin-okhttp3/build/
\?

# haskell
Expand Down
2 changes: 1 addition & 1 deletion docs/generators/kotlin.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ sidebar_label: kotlin
|artifactVersion|Generated artifact's package version.| |1.0.0|
|collectionType|Option. Collection type to use|<dl><dt>**array**</dt><dd>kotlin.Array</dd><dt>**list**</dt><dd>kotlin.collections.List</dd></dl>|list|
|dateLibrary|Option. Date library to use|<dl><dt>**threetenbp-localdatetime**</dt><dd>Threetenbp - Backport of JSR310 (jvm only, for legacy app only)</dd><dt>**string**</dt><dd>String</dd><dt>**java8-localdatetime**</dt><dd>Java 8 native JSR310 (jvm only, for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (jvm only, preferred for jdk 1.8+)</dd><dt>**threetenbp**</dt><dd>Threetenbp - Backport of JSR310 (jvm only, preferred for jdk &lt; 1.8)</dd></dl>|java8|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |PascalCase|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|library|Library template (sub-template) to use|<dl><dt>**jvm-okhttp4**</dt><dd>[DEFAULT] Platform: Java Virtual Machine. HTTP client: OkHttp 4.2.0 (Android 5.0+ and Java 8+). JSON processing: Moshi 1.8.0.</dd><dt>**jvm-okhttp3**</dt><dd>Platform: Java Virtual Machine. HTTP client: OkHttp 3.12.4 (Android 2.3+ and Java 7+). JSON processing: Moshi 1.8.0.</dd><dt>**jvm-retrofit2**</dt><dd>Platform: Java Virtual Machine. HTTP client: Retrofit 2.6.2.</dd><dt>**multiplatform**</dt><dd>Platform: Kotlin multiplatform. HTTP client: Ktor 1.2.4. JSON processing: Kotlinx Serialization: 0.12.0.</dd></dl>|jvm-okhttp4|
|modelMutable|Create mutable models| |false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
// (mustache does not allow for boolean operators so we need this extra field)
protected boolean doNotUseRxAndCoroutines = true;

protected String baseFolder;
protected String authFolder;

public enum DateLibrary {
Expand Down Expand Up @@ -150,6 +151,8 @@ public KotlinClientCodegen() {
// cliOptions default redefinition need to be updated
updateOption(CodegenConstants.ARTIFACT_ID, this.artifactId);
updateOption(CodegenConstants.PACKAGE_NAME, this.packageName);
// Kotlin convention
updateOption(CodegenConstants.ENUM_PROPERTY_NAMING, "PascalCase");

outputFolder = "generated-code" + File.separator + "kotlin-client";
modelTemplateFiles.put("model.mustache", ".kt");
Expand Down Expand Up @@ -284,7 +287,7 @@ public void processOpts() {
super.processOpts();

if (MULTIPLATFORM.equals(getLibrary())) {
sourceFolder = "src/commonMain/kotlin";
sourceFolder = "src/common/main";
}


Expand All @@ -311,13 +314,13 @@ public void processOpts() {
if (hasConflict) {
LOGGER.warn("You specified RxJava versions 1 and 2 and 3 or Coroutines together, please choose one of them.");
} else if (hasRx) {
this.setUseRxJava(Boolean.valueOf(additionalProperties.get(USE_RX_JAVA).toString()));
this.setUseRxJava(Boolean.parseBoolean(additionalProperties.get(USE_RX_JAVA).toString()));
} else if (hasRx2) {
this.setUseRxJava2(Boolean.valueOf(additionalProperties.get(USE_RX_JAVA2).toString()));
this.setUseRxJava2(Boolean.parseBoolean(additionalProperties.get(USE_RX_JAVA2).toString()));
} else if (hasRx3) {
this.setUseRxJava3(Boolean.valueOf(additionalProperties.get(USE_RX_JAVA3).toString()));
this.setUseRxJava3(Boolean.parseBoolean(additionalProperties.get(USE_RX_JAVA3).toString()));
} else if (hasCoroutines) {
this.setUseCoroutines(Boolean.valueOf(additionalProperties.get(USE_COROUTINES).toString()));
this.setUseCoroutines(Boolean.parseBoolean(additionalProperties.get(USE_COROUTINES).toString()));
}

if (!hasRx && !hasRx2 && !hasRx3 && !hasCoroutines) {
Expand All @@ -327,7 +330,8 @@ public void processOpts() {

// infrastructure destination folder
final String infrastructureFolder = (sourceFolder + File.separator + packageName + File.separator + "infrastructure").replace(".", "/");
authFolder = (sourceFolder + File.separator + packageName + File.separator + "auth").replace(".", "/");
authFolder = (sourceFolder + File.separator + packageName + File.separator + "auth").replace(".", File.separator);
baseFolder = (sourceFolder + File.separator + packageName).replace(".", File.separator);

// additional properties
if (additionalProperties.containsKey(DATE_LIBRARY)) {
Expand Down Expand Up @@ -496,6 +500,7 @@ private void processJVMOkHttpLibrary(final String infrastructureFolder) {
setLibrary(JVM_OKHTTP);

// jvm specific supporting files
supportingFiles.add(new SupportingFile("infrastructure/ApiClient.kt.mustache", infrastructureFolder, "ApiClient.kt"));
supportingFiles.add(new SupportingFile("infrastructure/ApplicationDelegates.kt.mustache", infrastructureFolder, "ApplicationDelegates.kt"));
supportingFiles.add(new SupportingFile("infrastructure/Errors.kt.mustache", infrastructureFolder, "Errors.kt"));
supportingFiles.add(new SupportingFile("infrastructure/ResponseExtensions.kt.mustache", infrastructureFolder, "ResponseExtensions.kt"));
Expand Down Expand Up @@ -533,11 +538,16 @@ private void processMultiplatformLibrary(final String infrastructureFolder) {
importMapping.put("Base64ByteArray", packageName + ".infrastructure.Base64ByteArray");
importMapping.put("OctetByteArray", packageName + ".infrastructure.OctetByteArray");

// bundled client file
supportingFiles.add(new SupportingFile("ApiClient.kt.mustache", baseFolder, "ApiClient.kt"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that renaming ApiClient.kt.mustache to ApiClientBase.kt.mustache is going to cause a lot of problems for anyone who has customized ApiClient.kt.mustache.

Can we find a naming strategy which retains ApiClient.kt.mustache without breaking existing extensions?

If not, we need to mark this PR as a breaking change and provide some guidelines in the PR for how one would migrate from using multiplatform before 5.0 to use it after this PR is merged.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's breaking pretty much, because it used experimental / alpha state libraries (MPP itself is still experimental) and they had a lot of breaking changes themselves, so that not really something you can avoid. I tried to do my best and migrate it to stable versions so there's no deprecated, opt-in or otherwise experimental stuff anymore but it might be incompatible here and there.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll see what I can do to add a little migration guide or so


// multiplatform specific supporting files
supportingFiles.add(new SupportingFile("infrastructure/ApiClientBase.kt.mustache", infrastructureFolder, "ApiClientBase.kt"));
supportingFiles.add(new SupportingFile("infrastructure/Base64ByteArray.kt.mustache", infrastructureFolder, "Base64ByteArray.kt"));
supportingFiles.add(new SupportingFile("infrastructure/Bytes.kt.mustache", infrastructureFolder, "Bytes.kt"));
supportingFiles.add(new SupportingFile("infrastructure/HttpResponse.kt.mustache", infrastructureFolder, "HttpResponse.kt"));
supportingFiles.add(new SupportingFile("infrastructure/OctetByteArray.kt.mustache", infrastructureFolder, "OctetByteArray.kt"));
supportingFiles.add(new SupportingFile("infrastructure/encoding.kt.mustache", infrastructureFolder, "encoding.kt"));

// multiplatform specific auth
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.kt.mustache", authFolder, "ApiKeyAuth.kt"));
Expand All @@ -547,30 +557,35 @@ private void processMultiplatformLibrary(final String infrastructureFolder) {
supportingFiles.add(new SupportingFile("auth/OAuth.kt.mustache", authFolder, "OAuth.kt"));

// multiplatform specific testing files
supportingFiles.add(new SupportingFile("commonTest/Coroutine.kt.mustache", "src/commonTest/kotlin/util", "Coroutine.kt"));
supportingFiles.add(new SupportingFile("iosTest/Coroutine.kt.mustache", "src/iosTest/kotlin/util", "Coroutine.kt"));
supportingFiles.add(new SupportingFile("jsTest/Coroutine.kt.mustache", "src/jsTest/kotlin/util", "Coroutine.kt"));
supportingFiles.add(new SupportingFile("jvmTest/Coroutine.kt.mustache", "src/jvmTest/kotlin/util", "Coroutine.kt"));
supportingFiles.add(new SupportingFile("commonTest/Coroutine.kt.mustache", "src/common/test/util", "Coroutine.kt"));
supportingFiles.add(new SupportingFile("iosTest/Coroutine.kt.mustache", "src/ios/test/util", "Coroutine.kt"));
supportingFiles.add(new SupportingFile("jsTest/Coroutine.kt.mustache", "src/js/test/util", "Coroutine.kt"));
supportingFiles.add(new SupportingFile("jvmTest/Coroutine.kt.mustache", "src/jvm/test/util", "Coroutine.kt"));

// gradle wrapper supporting files
supportingFiles.add(new SupportingFile("gradlew.mustache", "", "gradlew"));
supportingFiles.add(new SupportingFile("gradlew.bat.mustache", "", "gradlew.bat"));
supportingFiles.add(new SupportingFile("gradle.properties", "", "gradle.properties"));
supportingFiles.add(new SupportingFile("gradle-wrapper.properties.mustache", "gradle.wrapper".replace(".", File.separator), "gradle-wrapper.properties"));
supportingFiles.add(new SupportingFile("gradle-wrapper.jar", "gradle.wrapper".replace(".", File.separator), "gradle-wrapper.jar"));
}


private void commonJvmMultiplatformSupportingFiles(String infrastructureFolder) {
supportingFiles.add(new SupportingFile("infrastructure/ApiClient.kt.mustache", infrastructureFolder, "ApiClient.kt"));
supportingFiles.add(new SupportingFile("infrastructure/ApiAbstractions.kt.mustache", infrastructureFolder, "ApiAbstractions.kt"));
supportingFiles.add(new SupportingFile("infrastructure/RequestConfig.kt.mustache", infrastructureFolder, "RequestConfig.kt"));
supportingFiles.add(new SupportingFile("infrastructure/RequestMethod.kt.mustache", infrastructureFolder, "RequestMethod.kt"));
}

private void commonSupportingFiles() {
if (MULTIPLATFORM.equals(getLibrary())) {
supportingFiles.add(new SupportingFile("build.gradle.kts.mustache", "", "build.gradle.kts"));
supportingFiles.add(new SupportingFile("settings.gradle.kts.mustache", "", "settings.gradle.kts"));
} else {
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
}
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* Gradle 4.9
{{/jvm}}
{{#multiplatform}}
* Kotlin 1.3.50
* Kotlin 1.3.72
{{/multiplatform}}

## Build
Expand Down Expand Up @@ -36,7 +36,7 @@ This runs all tests and packages the library.
{{#jvm}}* Implementation of ApiClient is intended to reduce method counts, specifically to benefit Android targets.{{/jvm}}

{{#generateApiDocs}}
<a name="documentation-for-api-endpoints"></a>
<a id="documentation-for-api-endpoints"></a>
## Documentation for API Endpoints

All URIs are relative to *{{{basePath}}}*
Expand All @@ -48,7 +48,7 @@ Class | Method | HTTP request | Description
{{/generateApiDocs}}

{{#generateModelDocs}}
<a name="documentation-for-models"></a>
<a id="documentation-for-models"></a>
## Documentation for Models

{{#modelPackage}}
Expand All @@ -60,7 +60,7 @@ No model defined in this package
{{/modelPackage}}
{{/generateModelDocs}}

<a name="documentation-for-authorization"></a>{{! TODO: optional documentation for authorization? }}
<a id="documentation-for-authorization"></a>{{! TODO: optional documentation for authorization? }}
## Documentation for Authorization

{{^authMethods}}
Expand All @@ -72,7 +72,7 @@ Authentication schemes defined for the API:
{{/last}}
{{/authMethods}}
{{#authMethods}}
<a name="{{name}}"></a>
<a id="{{name}}"></a>
### {{name}}

{{#isApiKey}}- **Type**: API key
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Name | Type | Description | Notes
{{/vars}}
{{#vars}}{{#isEnum}}

<a name="{{{datatypeWithEnum}}}"></a>{{!NOTE: see java's resources "pojo_doc.mustache" once enums are fully implemented}}
<a id="{{{datatypeWithEnum}}}"></a>{{!NOTE: see java's resources "pojo_doc.mustache" once enums are fully implemented}}
## Enum: {{baseName}}
Name | Value
---- | -----{{#allowableValues}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ import kotlinx.android.parcel.Parcelize
{{/multiplatform}}
{{#multiplatform}}
import kotlinx.serialization.*
import kotlinx.serialization.internal.CommonEnumSerializer
{{/multiplatform}}
{{#serializableModel}}
import java.io.Serializable
{{/serializableModel}}
import kotlin.collections.*

/**
* {{{description}}}
*
{{#allVars}}
* @param {{{name}}} {{{description}}}
{{/allVars}}
Expand All @@ -42,7 +43,7 @@ import java.io.Serializable
{{#isDeprecated}}
@Deprecated(message = "This schema is deprecated.")
{{/isDeprecated}}
{{#nonPublicApi}}internal {{/nonPublicApi}}{{#discriminator}}interface{{/discriminator}}{{^discriminator}}data class{{/discriminator}} {{classname}}{{^discriminator}} (
{{#nonPublicApi}}internal {{/nonPublicApi}}{{#discriminator}}interface{{/discriminator}}{{^discriminator}}data class{{/discriminator}} {{classname}}{{^discriminator}}(
{{#allVars}}
{{#required}}{{>data_class_req_var}}{{/required}}{{^required}}{{>data_class_opt_var}}{{/required}}{{^-last}},{{/-last}}
{{/allVars}}
Expand All @@ -60,14 +61,13 @@ import java.io.Serializable
{{#vars}}
{{#isEnum}}
/**
* {{{description}}}
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
{{#multiplatform}}@Serializable(with = {{nameInCamelCase}}.Serializer::class){{/multiplatform}}
{{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{{nameInCamelCase}}}(val value: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}kotlin.String{{/isContainer}}){
* {{{description}}}
*
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
{{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{{nameInCamelCase}}}(val value: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}){
{{#allowableValues}}
{{#enumVars}}
{{^multiplatform}}
{{#moshi}}
@Json(name = {{^isString}}"{{/isString}}{{{value}}}{{^isString}}"{{/isString}}) {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/moshi}}
Expand All @@ -77,16 +77,11 @@ import java.io.Serializable
{{#jackson}}
@JsonProperty(value = {{^isString}}"{{/isString}}{{{value}}}{{^isString}}"{{/isString}}) {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/jackson}}
{{/multiplatform}}
{{#multiplatform}}
{{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
@SerialName(value = {{^isString}}"{{/isString}}{{{value}}}{{^isString}}"{{/isString}}) {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/multiplatform}}
{{/enumVars}}
{{/allowableValues}}
{{#multiplatform}}

{{#nonPublicApi}}internal {{/nonPublicApi}}object Serializer : CommonEnumSerializer<{{nameInCamelCase}}>("{{nameInCamelCase}}", values(), values().map { it.value.toString() }.toTypedArray())
{{/multiplatform}}
}
{{/isEnum}}
{{/vars}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{{#description}}
/* {{{description}}} */
/**
* {{{description}}}
*/
{{/description}}
{{^multiplatform}}
{{#moshi}}
Expand All @@ -12,7 +14,10 @@
@field:JsonProperty("{{{vendorExtensions.x-base-name-literal}}}")
{{/jackson}}
{{/multiplatform}}
{{#multiplatform}}
@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}")
{{/multiplatform}}
{{#deprecated}}
@Deprecated(message = "This property is deprecated.")
{{/deprecated}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") {{/multiplatform}}{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isListContainer}}{{#isList}}kotlin.collections.List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{classname}}.{{{nameInCamelCase}}}>{{/isListContainer}}{{^isListContainer}}{{classname}}.{{{nameInCamelCase}}}{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}
{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isListContainer}}{{#isList}}List{{/isList}}{{^isList}}Array{{/isList}}<{{classname}}.{{{nameInCamelCase}}}>{{/isListContainer}}{{^isListContainer}}{{classname}}.{{{nameInCamelCase}}}{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{{#description}}
/* {{{description}}} */
/**
* {{{description}}}
*/
{{/description}}
{{^multiplatform}}
{{#moshi}}
Expand All @@ -15,4 +17,8 @@
{{#deprecated}}
@Deprecated(message = "This property is deprecated.")
{{/deprecated}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") @Required {{/multiplatform}}{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isListContainer}}{{#isList}}kotlin.collections.List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{classname}}.{{{nameInCamelCase}}}>{{/isListContainer}}{{^isListContainer}}{{classname}}.{{{nameInCamelCase}}}{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}
{{#multiplatform}}
@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}")
@Required
{{/multiplatform}}
{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isListContainer}}{{#isList}}List{{/isList}}{{^isList}}Array{{/isList}}<{{classname}}.{{{nameInCamelCase}}}>{{/isListContainer}}{{^isListContainer}}{{classname}}.{{{nameInCamelCase}}}{{/isListContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}
Loading