[Kotlin][Client] fix missing curly bracket when the model contains enum property (#4118)

* fix kotlin okhttp3, add CI test

* update kotlin server sample
This commit is contained in:
William Cheng 2019-10-10 18:21:50 +08:00 committed by GitHub
parent 3141e483ef
commit b69b8cdd31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 129 additions and 168 deletions

1
.gitignore vendored
View File

@ -188,6 +188,7 @@ 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

View File

@ -27,8 +27,8 @@ fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -t modules/openapi-generator/src/main/resources/kotlin-client -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g kotlin --artifact-id kotlin-petstore-okhttp3 --library jvm-okhttp3 --additional-properties parcelizeModels=true -o samples/client/petstore/kotlin-okhttp3 $@"
ags="generate -t modules/openapi-generator/src/main/resources/kotlin-client -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g kotlin --artifact-id kotlin-petstore-okhttp3 --library jvm-okhttp3 -o samples/client/petstore/kotlin-okhttp3 $@"
java ${JAVA_OPTS} -jar ${executable} ${ags}
cp CI/samples.ci/client/petstore/kotlin-okhttp3/pom.xml samples/client/petstore/kotlin-okhttp3/pom.xml
#cp CI/samples.ci/client/petstore/kotlin-okhttp3/pom.xml samples/client/petstore/kotlin-okhttp3/pom.xml

View File

@ -251,9 +251,6 @@ public class CodegenConstants {
public static final String CASE_INSENSITIVE_RESPONSE_HEADERS = "caseInsensitiveResponseHeaders";
public static final String CASE_INSENSITIVE_RESPONSE_HEADERS_DESC = "Make API response's headers case-insensitive";
public static final String NEEDS_DATACLASS_BODY = "needsDataClassBody";
public static final String NEEDS_DATACLASS_BODY_DESC = "Specifies if the kotlin data class needs a body with curly braces or not.";
// Not user-configurable. System provided for use in templates.
public static final String GENERATE_APIS = "generateApis";

View File

@ -25,6 +25,7 @@ import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
@ -58,7 +59,6 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
protected boolean parcelizeModels = false;
protected boolean serializableModel = false;
protected boolean needsDataClassBody = false;
protected boolean hasEnums = false;
protected CodegenConstants.ENUM_PROPERTY_NAMING_TYPE enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.camelCase;
protected SERIALIZATION_LIBRARY_TYPE serializationLibrary = SERIALIZATION_LIBRARY_TYPE.moshi;
@ -236,7 +236,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
@Override
public String apiTestFileFolder() {
return (outputFolder + File.separator + testFolder + File.separator + apiPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar) ;
return (outputFolder + File.separator + testFolder + File.separator + apiPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
}
@Override
@ -285,7 +285,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
* Sets the serialization engine for Kotlin
*
* @param enumSerializationLibrary The string representation of the serialization library as defined by
* {@link org.openapitools.codegen.languages.AbstractKotlinCodegen.SERIALIZATION_LIBRARY_TYPE}
* {@link org.openapitools.codegen.languages.AbstractKotlinCodegen.SERIALIZATION_LIBRARY_TYPE}
*/
public void setSerializationLibrary(final String enumSerializationLibrary) {
try {
@ -352,7 +352,20 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
return postProcessModelsEnum(super.postProcessModels(objs));
objs = super.postProcessModelsEnum(objs);
List<Object> models = (List<Object>) objs.get("models");
for (Object _mo : models) {
Map<String, Object> mo = (Map<String, Object>) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");
for (CodegenProperty var : cm.vars) {
if (var.isEnum || isSerializableModel()) {
cm.vendorExtensions.put("x-has-data-class-body", true);
break;
}
}
}
return postProcessModelsEnum(objs);
}
@Override
@ -371,8 +384,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
if (additionalProperties.containsKey(CodegenConstants.SERIALIZATION_LIBRARY)) {
setSerializationLibrary((String) additionalProperties.get(CodegenConstants.SERIALIZATION_LIBRARY));
additionalProperties.put(this.serializationLibrary.name(), true);
}
else {
} else {
additionalProperties.put(this.serializationLibrary.name(), true);
}
@ -430,7 +442,6 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
additionalProperties.put(CodegenConstants.PARCELIZE_MODELS, parcelizeModels);
}
additionalProperties.put(CodegenConstants.NEEDS_DATACLASS_BODY, this.hasEnums || serializableModel);
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage());
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage());
@ -765,7 +776,6 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
CodegenModel m = super.fromModel(name, schema);
m.optionalVars = m.optionalVars.stream().distinct().collect(Collectors.toList());
m.allVars.stream().filter(p -> !m.vars.contains(p)).forEach(p -> p.isInherited = true);
this.hasEnums = m.hasEnums;
return m;
}

View File

@ -37,20 +37,25 @@ data class {{classname}} (
) {{^serializableModel}}{{#parcelizeModels}} : Parcelable{{/parcelizeModels}}{{/serializableModel}}
{{^parcelizeModels}}{{#serializableModel}}: Serializable {{/serializableModel}}{{/parcelizeModels}}
{{#parcelizeModels}}{{#serializableModel}} : Parcelable, Serializable {{/serializableModel}}{{/parcelizeModels}}
{{#needsDataClassBody}}{{=<% %>=}}{<%={{ }}=%>{{/needsDataClassBody}}
{{#vendorExtensions.x-has-data-class-body}}
{
{{/vendorExtensions.x-has-data-class-body}}
{{#serializableModel}}
companion object {
private const val serialVersionUID: Long = 123
}
{{/serializableModel}}{{#hasEnums}}
{{#vars}}{{#isEnum}}
{{/serializableModel}}
{{#hasEnums}}
{{#vars}}
{{#isEnum}}
/**
* {{{description}}}
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
{{#multiplatform}}@Serializable(with = {{nameInCamelCase}}.Serializer::class){{/multiplatform}}
enum class {{{nameInCamelCase}}}(val value: {{#isListContainer}}{{{ nestedType }}}{{/isListContainer}}{{^isListContainer}}{{{dataType}}}{{/isListContainer}}){
{{#allowableValues}}{{#enumVars}}
{{#allowableValues}}
{{#enumVars}}
{{#jvm}}
{{#moshi}}
@Json(name = {{{value}}}) {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
@ -62,11 +67,16 @@ data class {{classname}} (
{{#multiplatform}}
{{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/multiplatform}}
{{/enumVars}}{{/allowableValues}}
{{/enumVars}}
{{/allowableValues}}
{{#multiplatform}}
object Serializer : CommonEnumSerializer<{{nameInCamelCase}}>("{{nameInCamelCase}}", values(), values().map { it.value }.toTypedArray())
{{/multiplatform}}
}
{{/isEnum}}{{/vars}}
{{/hasEnums}}{{#needsDataClassBody}}{{=<% %>=}}}<%={{ }}=%>{{/needsDataClassBody}}
{{/isEnum}}
{{/vars}}
{{/hasEnums}}
{{#vendorExtensions.x-has-data-class-body}}
}
{{/vendorExtensions.x-has-data-class-body}}

View File

@ -22,21 +22,31 @@ data class {{classname}} (
{{/hasOptional}}{{/hasRequired}}{{#optionalVars}}{{>data_class_opt_var}}{{^-last}},
{{/-last}}{{/optionalVars}}
) {{^serializableModel}}{{#parcelizeModels}} : Parcelable{{/parcelizeModels}}{{/serializableModel}}{{^parcelizeModels}}{{#serializableModel}}: Serializable {{/serializableModel}}{{/parcelizeModels}}{{#parcelizeModels}}{{#serializableModel}} : Parcelable, Serializable {{/serializableModel}}{{/parcelizeModels}}
{{#needsDataClassBody}}{{=<% %>=}}{<%={{ }}=%>{{/needsDataClassBody}}
{{#vendorExtensions.x-has-data-class-body}}
{
{{/vendorExtensions.x-has-data-class-body}}
{{#serializableModel}}
companion object {
private const val serialVersionUID: Long = 123
}
{{/serializableModel}}
{{#hasEnums}}
{{#vars}}{{#isEnum}}
{{#vars}}
{{#isEnum}}
/**
* {{{description}}}
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
enum class {{nameInCamelCase}}(val value: {{dataType}}){
{{#allowableValues}}{{#enumVars}}
{{#allowableValues}}
{{#enumVars}}
{{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/enumVars}}{{/allowableValues}}
{{/enumVars}}
{{/allowableValues}}
}
{{/isEnum}}{{/vars}}{{/hasEnums}}{{#needsDataClassBody}}{{=<% %>=}}}<%={{ }}=%>{{/needsDataClassBody}}
{{/isEnum}}
{{/vars}}
{{/hasEnums}}
{{#vendorExtensions.x-has-data-class-body}}
}
{{/vendorExtensions.x-has-data-class-body}}

View File

@ -1245,6 +1245,7 @@
<module>samples/client/petstore/erlang-proper</module>
<module>samples/client/petstore/kotlin-multiplatform</module>
<module>samples/client/petstore/kotlin/</module>
<module>samples/client/petstore/kotlin-okhttp3/</module>
<module>samples/client/petstore/kotlin-threetenbp/</module>
<module>samples/client/petstore/kotlin-string/</module>
<!-- servers -->

View File

@ -35,25 +35,18 @@ data class Order (
)
{
/**
* Order Status
* Values: placed,approved,delivered
*/
@Serializable(with = Status.Serializer::class)
enum class Status(val value: kotlin.String){
placed("placed"),
approved("approved"),
delivered("delivered");
object Serializer : CommonEnumSerializer<Status>("Status", values(), values().map { it.value }.toTypedArray())
}
}

View File

@ -37,25 +37,18 @@ data class Pet (
)
{
/**
* pet status in the store
* Values: available,pending,sold
*/
@Serializable(with = Status.Serializer::class)
enum class Status(val value: kotlin.String){
available("available"),
pending("pending"),
sold("sold");
object Serializer : CommonEnumSerializer<Status>("Status", values(), values().map { it.value }.toTypedArray())
}
}

View File

@ -1 +1 @@
4.1.3-SNAPSHOT
4.2.0-SNAPSHOT

View File

@ -0,0 +1,46 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>io.swagger</groupId>
<artifactId>KotlinOkhttp3PetstoreClientTests</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>Kotlin Okhttp3 Petstore Client</name>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>bundle-test</id>
<phase>integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>gradle</executable>
<arguments>
<argument>test</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -122,7 +122,7 @@ open class ApiClient(val baseUrl: String) {
val contentType = (headers[ContentType] as String).substringBefore(";").toLowerCase()
val request = when (requestConfig.method) {
RequestMethod.DELETE -> Request.Builder().url(url).delete()
RequestMethod.DELETE -> Request.Builder().url(url).delete(requestBody(body, contentType))
RequestMethod.GET -> Request.Builder().url(url)
RequestMethod.HEAD -> Request.Builder().url(url).head()
RequestMethod.PATCH -> Request.Builder().url(url).patch(requestBody(body, contentType))

View File

@ -13,16 +13,12 @@ package org.openapitools.client.models
import com.squareup.moshi.Json
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
/**
* Describes the result of uploading an image resource
* @param code
* @param type
* @param message
*/
@Parcelize
data class ApiResponse (
@Json(name = "code")
@ -31,5 +27,7 @@ data class ApiResponse (
val type: kotlin.String? = null,
@Json(name = "message")
val message: kotlin.String? = null
) : Parcelable
)

View File

@ -13,20 +13,18 @@ package org.openapitools.client.models
import com.squareup.moshi.Json
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
/**
* A category for a pet
* @param id
* @param name
*/
@Parcelize
data class Category (
@Json(name = "id")
val id: kotlin.Long? = null,
@Json(name = "name")
val name: kotlin.String? = null
) : Parcelable
)

View File

@ -13,9 +13,6 @@ package org.openapitools.client.models
import com.squareup.moshi.Json
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
/**
* An order for a pets from the pet store
* @param id
@ -25,7 +22,6 @@ import kotlinx.android.parcel.Parcelize
* @param status Order Status
* @param complete
*/
@Parcelize
data class Order (
@Json(name = "id")
@ -41,24 +37,19 @@ data class Order (
val status: Order.Status? = null,
@Json(name = "complete")
val complete: kotlin.Boolean? = null
) : Parcelable
{
)
{
/**
* Order Status
* Values: placed,approved,delivered
*/
enum class Status(val value: kotlin.String){
@Json(name = "placed") placed("placed"),
@Json(name = "approved") approved("approved"),
@Json(name = "delivered") delivered("delivered");
}
}

View File

@ -15,9 +15,6 @@ import org.openapitools.client.models.Category
import org.openapitools.client.models.Tag
import com.squareup.moshi.Json
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
/**
* A pet for sale in the pet store
* @param id
@ -27,7 +24,6 @@ import kotlinx.android.parcel.Parcelize
* @param tags
* @param status pet status in the store
*/
@Parcelize
data class Pet (
@Json(name = "name")
@ -43,24 +39,19 @@ data class Pet (
/* pet status in the store */
@Json(name = "status")
val status: Pet.Status? = null
) : Parcelable
{
)
{
/**
* pet status in the store
* Values: available,pending,sold
*/
enum class Status(val value: kotlin.String){
@Json(name = "available") available("available"),
@Json(name = "pending") pending("pending"),
@Json(name = "sold") sold("sold");
}
}

View File

@ -13,20 +13,18 @@ package org.openapitools.client.models
import com.squareup.moshi.Json
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
/**
* A tag for a pet
* @param id
* @param name
*/
@Parcelize
data class Tag (
@Json(name = "id")
val id: kotlin.Long? = null,
@Json(name = "name")
val name: kotlin.String? = null
) : Parcelable
)

View File

@ -13,9 +13,6 @@ package org.openapitools.client.models
import com.squareup.moshi.Json
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
/**
* A User who is purchasing from the pet store
* @param id
@ -27,7 +24,6 @@ import kotlinx.android.parcel.Parcelize
* @param phone
* @param userStatus User Status
*/
@Parcelize
data class User (
@Json(name = "id")
@ -47,5 +43,7 @@ data class User (
/* User Status */
@Json(name = "userStatus")
val userStatus: kotlin.Int? = null
) : Parcelable
)

View File

@ -45,23 +45,15 @@ data class Order (
companion object {
private const val serialVersionUID: Long = 123
}
/**
* Order Status
* Values: placed,approved,delivered
*/
enum class Status(val value: kotlin.String){
@Json(name = "placed") placed("placed"),
@Json(name = "approved") approved("approved"),
@Json(name = "delivered") delivered("delivered");
}
}

View File

@ -47,23 +47,15 @@ data class Pet (
companion object {
private const val serialVersionUID: Long = 123
}
/**
* pet status in the store
* Values: available,pending,sold
*/
enum class Status(val value: kotlin.String){
@Json(name = "available") available("available"),
@Json(name = "pending") pending("pending"),
@Json(name = "sold") sold("sold");
}
}

View File

@ -40,24 +40,16 @@ data class Order (
)
{
/**
* Order Status
* Values: placed,approved,delivered
*/
enum class Status(val value: kotlin.String){
@Json(name = "placed") placed("placed"),
@Json(name = "approved") approved("approved"),
@Json(name = "delivered") delivered("delivered");
}
}

View File

@ -42,24 +42,16 @@ data class Pet (
)
{
/**
* pet status in the store
* Values: available,pending,sold
*/
enum class Status(val value: kotlin.String){
@Json(name = "available") available("available"),
@Json(name = "pending") pending("pending"),
@Json(name = "sold") sold("sold");
}
}

View File

@ -45,23 +45,15 @@ data class Order (
companion object {
private const val serialVersionUID: Long = 123
}
/**
* Order Status
* Values: placed,approved,delivered
*/
enum class Status(val value: kotlin.String){
@Json(name = "placed") placed("placed"),
@Json(name = "approved") approved("approved"),
@Json(name = "delivered") delivered("delivered");
}
}

View File

@ -47,23 +47,15 @@ data class Pet (
companion object {
private const val serialVersionUID: Long = 123
}
/**
* pet status in the store
* Values: available,pending,sold
*/
enum class Status(val value: kotlin.String){
@Json(name = "available") available("available"),
@Json(name = "pending") pending("pending"),
@Json(name = "sold") sold("sold");
}
}

View File

@ -35,19 +35,14 @@ data class Order (
companion object {
private const val serialVersionUID: Long = 123
}
/**
* Order Status
* Values: placed,approved,delivered
*/
enum class Status(val value: kotlin.String){
placed("placed"),
approved("approved"),
delivered("delivered");
}
}

View File

@ -37,19 +37,14 @@ data class Pet (
companion object {
private const val serialVersionUID: Long = 123
}
/**
* pet status in the store
* Values: available,pending,sold
*/
enum class Status(val value: kotlin.String){
available("available"),
pending("pending"),
sold("sold");
}
}