Skip to content
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

[Kotlin Multiplatform] Update and fixes for Kotlin 1.5.10 and Kotlinx.serialization 1.2.1 #9755

Merged
merged 6 commits into from
Jul 3, 2021
Merged

[Kotlin Multiplatform] Update and fixes for Kotlin 1.5.10 and Kotlinx.serialization 1.2.1 #9755

merged 6 commits into from
Jul 3, 2021

Conversation

837
Copy link
Contributor

@837 837 commented Jun 13, 2021

  • Update Kotlin Multiplatform with Kotlin 1.5.10, Ktor 1.6.0 and Kotlinx.serialization 1.2.1
  • remove @serializable from interfaces
  • Use CharArray.concatToString() instead of 'String(CharArray): String' as it is an error now
  • Fix, RequestConfig needs a type to infer type variable T

Fixes from @DevSrSouzaern #9232
Seemed not to be updated anymore.

  • Fix private keyword not being handle as a reservedWords
  • Fix enum serialization generation
  • Migrate gradle build to Kotlin DSL

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
  • Run the following to build the project and update samples:
    ./mvnw clean package 
    ./bin/generate-samples.sh
    ./bin/utils/export_docs_generators.sh
    
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    For Windows users, please run the script in Git BASH.
  • File the PR against the correct branch: master, 5.1.x, 6.0.x
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.
    @jimschubert , @dr4ke616, @karismann, @Zomzog, @andrewemery, @4brunu, @yutaka0m

DevSrSouza and others added 2 commits June 13, 2021 17:16
…x.serialization 1.2.1

* remove @serializable from interfaces
* Using 'String(CharArray): String' is an error. Use CharArray.concatToString() instead
* Fix, RequestConfig needs a type to infer type variable T

Fixes from @DevSrSouzaern
* Fix `private` keyword not being handle as a reservedWords
* Fix enum serialization generation
* Migrate gradle build to Kotlin DSL
@837
Copy link
Contributor Author

837 commented Jun 13, 2021

Someone an idea why CircleCi fails?

Copy link
Contributor

@4brunu 4brunu left a comment

Choose a reason for hiding this comment

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

Hi @837 since I don't have much experience with kotlin multiplatform I left some comments to try to understand the changes.

httpClientEngine: HttpClientEngine? = null,
jsonConfiguration: JsonConfiguration = JsonConfiguration.Default
) : this(baseUrl, httpClientEngine, KotlinxSerializer(Json(jsonConfiguration)))
jsonSerializer: Json
Copy link
Contributor

Choose a reason for hiding this comment

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

@837 could you please explain why the change from KotlinxSerializer to Json?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The creation of the KotlinxSerializer is now lazily done in the ApiClient::class.
The Json is used to pass down settings as they might vary depending on the api:

Json {
            isLenient = true
            ignoreUnknownKeys = true
        }

Copy link
Contributor

Choose a reason for hiding this comment

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

Now when instantiating some Api class, it's needed to pass jsonSerializer. It wasn't needed before this PR (jsonConfiguration: JsonConfiguration = JsonConfiguration.Default in the constructor that was removed), so I think that we should remain backward-compatible here and some kind of a sane default Json configuration would be good. Best if this default configuration is accessible for the client, so that they can customize it by building upon the default one.

I agree that e.g. ignoreUnknownKeys = true should be in this default. Otherwise if the service being called starts including some new properties, JSON deserialization will fail. No experience/opinion on isLenient.

@4brunu
Copy link
Contributor

4brunu commented Jun 22, 2021

I'm not a kotlin multiplaform users, but I don't see nothing wrong here.
@wing328 what do you think of this PR?

Copy link
Contributor

@krzema12 krzema12 left a comment

Choose a reason for hiding this comment

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

Thanks for opening this PR! I started one myself (#9827) but it's so similar to yours that I'm happy to help you polish this one :)

As a smoke test, I cloned your repo and branch, and generated a client for my company's internal service. For an example call, it works good!

Apart from the comments I placed inline, let me repeat concerns that I have for my PR:

  • are there any end-to-end tests that actually try to call the Petstore service with the generated module? Ideally we'd like to test various edge cases in an automated and repeatable way
  • how to ensure there are no regressions in other Kotlin templates that reuse the shared pieces of template?
  • is master the right target branch for this change, given it's formally backward-incompatible? The policy is confusing to me

docs/generators/kotlin.md Outdated Show resolved Hide resolved
}

private fun RequestConfig.updateForAuth(authNames: kotlin.collections.List<String>) {
private fun <T: Any?> RequestConfig<T>.updateForAuth(authNames: kotlin.collections.List<String>) {
for (authName in authNames) {
val auth = authentications?.get(authName) ?: throw Exception("Authentication undefined: $authName")
auth.apply(query, headers)
Copy link
Contributor

Choose a reason for hiding this comment

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

A comment to line which mentions ktorio/ktor#851 and the below workaround (I cannot place a comment there 😞): how about removing this workaround? I see that this issue was resolved 2 years ago, so the newest version of Ktor almost for sure doesn't have this issue. On the other hand, to keep the number of changes minimal, I'm fine with doing it as a follow-up.

httpClientEngine: HttpClientEngine? = null,
jsonConfiguration: JsonConfiguration = JsonConfiguration.Default
) : this(baseUrl, httpClientEngine, KotlinxSerializer(Json(jsonConfiguration)))
jsonSerializer: Json
Copy link
Contributor

Choose a reason for hiding this comment

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

Now when instantiating some Api class, it's needed to pass jsonSerializer. It wasn't needed before this PR (jsonConfiguration: JsonConfiguration = JsonConfiguration.Default in the constructor that was removed), so I think that we should remain backward-compatible here and some kind of a sane default Json configuration would be good. Best if this default configuration is accessible for the client, so that they can customize it by building upon the default one.

I agree that e.g. ignoreUnknownKeys = true should be in this default. Otherwise if the service being called starts including some new properties, JSON deserialization will fail. No experience/opinion on isLenient.

* sample update
* revert non multiplatform kotlinx_serialization removal
* default Json{} in ApiClient
* revert accidental version push for jvm client
* Match ktor and Kotlinx Serialization version in documentation and build.gradle.kts
Copy link
Contributor

@krzema12 krzema12 left a comment

Choose a reason for hiding this comment

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

LGTM - I think we can merge as is because it works fine, and then apply any improvements like end-to-end tests or code cleanup as follow-ups.

@4brunu
Copy link
Contributor

4brunu commented Jun 29, 2021

@837 could you please close and reopen this PR to restart CI? Thanks

@837 837 closed this Jun 29, 2021
@4brunu
Copy link
Contributor

4brunu commented Jun 29, 2021

Sorry if I miscommunicated, but to restart the CI you could just close and reopen the same PR, there is no need to create a new one.
But this works too 🙂

@837
Copy link
Contributor Author

837 commented Jun 29, 2021

Oh didnt know that. Makes more sense to keep this one.

@837 837 reopened this Jun 29, 2021
@4brunu
Copy link
Contributor

4brunu commented Jun 30, 2021

Looks good to me 👍

@wing328
Copy link
Member

wing328 commented Jul 1, 2021

@837 can you please resolve the merge conflicts when you've time?

@wing328
Copy link
Member

wing328 commented Jul 3, 2021

Kotlin tests pass via #9883

@wing328 wing328 merged commit 17b6379 into OpenAPITools:master Jul 3, 2021
krzema12 added a commit to krzema12/openapi-generator that referenced this pull request Jul 28, 2021
This dependency was accidentally removed in PR OpenAPITools#9755 where we switched
from `build.gradle` to `build.gradle.kts`.
wing328 pushed a commit that referenced this pull request Jul 29, 2021
This dependency was accidentally removed in PR #9755 where we switched
from `build.gradle` to `build.gradle.kts`.
@shadowsheep1
Copy link
Contributor

shadowsheep1 commented Sep 23, 2021

I had to use a custom mustache template for HttpBasicAuth.kt.mustache to change it as:

package {{packageName}}.auth

import io.ktor.util.InternalAPI
import io.ktor.util.encodeBase64

/**
 * Custom Template
 */

class HttpBasicAuth : Authentication {
    var username: String? = null
    var password: String? = null

    @OptIn(InternalAPI::class)
    override fun apply(query: MutableMap<String, List<String>>, headers: MutableMap<String, String>) {
        if (username == null && password == null) return
        val str = (username ?: "") + ":" + (password ?: "")
        val auth = str.encodeBase64()
        headers["Authorization"] = "Basic $auth"
    }
}

Because with AS Artic Fox 2020.3.1 Patch 2

With this configuration

object Versions {
    const val iosTestTask = false
    const val foo = "8.6.8"
    const val kotlin = "1.5.31"

    // Gradle
    const val androidGradlePlugin = "7.0.2"
    const val gradle = "gradle-7.2-bin"

    // Android
    const val compileSdk = 30
    const val minSdk = 23
    const val targetSdk = compileSdk

    // You can also use this to specify versions for dependencies. Having consistent
    // versions between modules can avoid behavior conflicts.
    const val sqldelight = "1.5.1"
    const val settings = "0.8"
    const val serialization = "1.2.2"
    // https://kotlinlang.org/docs/mobile/concurrency-and-coroutines.html#multithreaded-coroutines
    const val coroutines = "1.5.1-native-mt"
    const val ktor = "1.6.3"
    const val openapigen = "5.2.1"
}

I had (using @InternalAPI annotation) this error.

e: Opt-in requirement marker annotation on override requires the same marker on base declaration

I'd to use @OptIn(InternalAPI::class) instead

@4brunu
Copy link
Contributor

4brunu commented Sep 23, 2021

@shadowsheep1 could you please add a PR with those changes?

@shadowsheep1
Copy link
Contributor

@4brunu sure 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants