OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
22.02k stars 6.61k forks source link

[BUG] [multiplatform] Support for x-enum-varnames #10466

Open shadowsheep1 opened 3 years ago

shadowsheep1 commented 3 years ago

With this setup:

AS Artic Fox 2020.3.1 Patch 2

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"
}

For enum declaration in the openapi specification like that:

"softwareTiers" : {
            "type" : "array",
            "items" : {
              "type" : "integer",
              "format" : "int32",
              "enum" : [ 200, 250, 300, 310, 350, 400, 401, 701, 503, 600, 900, 410, 800, 8888, 9999, 1000, 6666, 7777, 7778, 1100, 5555, 11111, 21111, 22111 ],
              "x-enum-varnames" : [ "CASISTICA_GUASTI", "CASISTICA_GUASTI_EDIT", "OFFICINA", "ODL", "WORKSHOP_NET", "REVISIONI", "REGISTRO_REVISIONI", "KROMEDA", "DATA_FULL", "FATTURAZIONE_ITALIA", "COMUNICAZIONI", "SMART", "YAP_LITE", "ADMIN", "LANG", "MAGAZZINO", "MEZZI_SPECIALI", "GOMME", "CONTESTO_GOMME", "CED", "PRIMA_NOTA", "E_TICKET", "FCA", "FIRMA" ]
            }
          },

I've found this error:

/**
     * 
     *
     * Values: CASISTICA_GUASTI,CASISTICA_GUASTI_EDIT,OFFICINA,ODL,WORKSHOP_NET,REVISIONI,REGISTRO_REVISIONI,KROMEDA,DATA_FULL,FATTURAZIONE_ITALIA,COMUNICAZIONI,SMART,YAP_LITE,ADMIN,LANG,MAGAZZINO,MEZZI_SPECIALI,GOMME,CONTESTO_GOMME,CED,PRIMA_NOTA,E_TICKET,FCA,FIRMA
     */
    @Serializable
    enum class SoftwareTiers(val value: kotlin.String) {
        @SerialName(value = "200") CASISTICA_GUASTI(200),
        @SerialName(value = "250") CASISTICA_GUASTI_EDIT(250),
        @SerialName(value = "300") OFFICINA(300),
        @SerialName(value = "310") ODL(310),
        @SerialName(value = "350") WORKSHOP_NET(350),
        @SerialName(value = "400") REVISIONI(400),
        @SerialName(value = "401") REGISTRO_REVISIONI(401),
        @SerialName(value = "701") KROMEDA(701),
        @SerialName(value = "503") DATA_FULL(503),
        @SerialName(value = "600") FATTURAZIONE_ITALIA(600),
        @SerialName(value = "900") COMUNICAZIONI(900),
        @SerialName(value = "410") SMART(410),
        @SerialName(value = "800") YAP_LITE(800),
        @SerialName(value = "8888") ADMIN(8888),
        @SerialName(value = "9999") LANG(9999),
        @SerialName(value = "1000") MAGAZZINO(1000),
        @SerialName(value = "6666") MEZZI_SPECIALI(6666),
        @SerialName(value = "7777") GOMME(7777),
        @SerialName(value = "7778") CONTESTO_GOMME(7778),
        @SerialName(value = "1100") CED(1100),
        @SerialName(value = "5555") PRIMA_NOTA(5555),
        @SerialName(value = "11111") E_TICKET(11111),
        @SerialName(value = "21111") FCA(21111),
        @SerialName(value = "22111") FIRMA(22111);
    }

The integer literal does not conform to the expected type String

I've found a solution changing this file: https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache

By changing this part:

{{#multiplatform}}
        @SerialName(value = {{^isString}}"{{/isString}}{{{value}}}{{^isString}}"{{/isString}}) {{&name}}({{^isString}}{{#isContainer}}"{{/isContainer}}{{/isString}}{{{value}}}{{^isString}}{{#isContainer}}"{{/isContainer}}{{/isString}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
        {{/multiplatform}}

with this:

{{#multiplatform}}
        @SerialName(value = {{^isString}}"{{/isString}}{{{value}}}{{^isString}}"{{/isString}}) {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
        {{/multiplatform}}

By wrapping with double quotes " the values of the enum in the value constructor.

@Serializable
    enum class SoftwareTiers(val value: kotlin.String) {
        @SerialName(value = "200") CASISTICA_GUASTI("200"),
        @SerialName(value = "250") CASISTICA_GUASTI_EDIT("250"),
        @SerialName(value = "300") OFFICINA("300"),
        @SerialName(value = "310") ODL("310"),
        @SerialName(value = "350") WORKSHOP_NET("350"),
        @SerialName(value = "400") REVISIONI("400"),
        @SerialName(value = "401") REGISTRO_REVISIONI("401"),
        @SerialName(value = "701") KROMEDA("701"),
        @SerialName(value = "503") DATA_FULL("503"),
        @SerialName(value = "600") FATTURAZIONE_ITALIA("600"),
        @SerialName(value = "900") COMUNICAZIONI("900"),
        @SerialName(value = "410") SMART("410"),
        @SerialName(value = "800") YAP_LITE("800"),
        @SerialName(value = "8888") ADMIN("8888"),
        @SerialName(value = "9999") LANG("9999"),
        @SerialName(value = "1000") MAGAZZINO("1000"),
        @SerialName(value = "6666") MEZZI_SPECIALI("6666"),
        @SerialName(value = "7777") GOMME("7777"),
        @SerialName(value = "7778") CONTESTO_GOMME("7778"),
        @SerialName(value = "1100") CED("1100"),
        @SerialName(value = "5555") PRIMA_NOTA("5555"),
        @SerialName(value = "11111") E_TICKET("11111"),
        @SerialName(value = "21111") FCA("21111"),
        @SerialName(value = "22111") FIRMA("22111");
    }

But I'm not sure if my solution

{{^isString}}{{#isContainer}}"{{/isContainer}}{{/isString}}{{{value}}}{{^isString}}{{#isContainer}}"{{/isContainer}

addresses all the cases or if is semantically right.

It also seems that the above enum doesn't match the specifications, because I'd expect to see an Int value constructor, and not a String one, so a better solution should be to add an Int constructor and all should work fine.

I'm not a mustache template file expert, so I need help choosing the right solution in this case.

shadowsheep1 commented 3 years ago

The x-enum-varnames should also be addressed here https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/kotlin-client/enum_class.mustache and in all other files that bulds enums.

shadowsheep1 commented 3 years ago

The old plugin version generates an x-enum-varnames type enum like that instead:

@Serializable
    enum class SoftwareTiers {

        @SerialName("200")
        CASISTICA_GUASTI,

        @SerialName("250")
        CASISTICA_GUASTI_EDIT,

        @SerialName("300")
        OFFICINA,

        @SerialName("310")
        ODL,

        @SerialName("350")
        WORKSHOP_NET,

        @SerialName("400")
        REVISIONI,

        @SerialName("401")
        REGISTRO_REVISIONI,

        @SerialName("701")
        KROMEDA,

        @SerialName("503")
        DATA_FULL,

        @SerialName("600")
        FATTURAZIONE_ITALIA,

        @SerialName("900")
        COMUNICAZIONI,

        @SerialName("410")
        SMART,

        @SerialName("800")
        YAP_LITE,

        @SerialName("8888")
        ADMIN,

        @SerialName("9999")
        LANG,

        @SerialName("1000")
        MAGAZZINO,

        @SerialName("6666")
        MEZZI_SPECIALI,

        @SerialName("7777")
        GOMME,

        @SerialName("7778")
        CONTESTO_GOMME,

        @SerialName("1100")
        CED,

        @SerialName("5555")
        PRIMA_NOTA,

        @SerialName("11111")
        E_TICKET,

        @SerialName("21111")
        FCA,

        @SerialName("22111")
        FIRMA;

    }