diff --git a/src/main/java/io/swagger/codegen/languages/kotlin/AbstractKotlinCodegen.java b/src/main/java/io/swagger/codegen/languages/kotlin/AbstractKotlinCodegen.java index 7b2ffa8a4a..502cf0555c 100644 --- a/src/main/java/io/swagger/codegen/languages/kotlin/AbstractKotlinCodegen.java +++ b/src/main/java/io/swagger/codegen/languages/kotlin/AbstractKotlinCodegen.java @@ -16,10 +16,16 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Set; public abstract class AbstractKotlinCodegen extends DefaultCodegenConfig { + private static Logger LOGGER = LoggerFactory.getLogger(AbstractKotlinCodegen.class); + private Set instantiationLibraryFunction; + + + protected String artifactId; protected String artifactVersion = "1.0.0"; protected String groupId = "io.swagger"; @@ -47,7 +53,7 @@ public AbstractKotlinCodegen() { "kotlin.Boolean", "kotlin.Char", "kotlin.String", - "kotlin.Array", + "kotlin.Array", "kotlin.collections.List", "kotlin.collections.Map", "kotlin.collections.Set" @@ -136,6 +142,11 @@ public AbstractKotlinCodegen() { "kotlin.collections.Map" )); + instantiationLibraryFunction = new HashSet(Arrays.asList( + "arrayOf", + "mapOf" + )); + typeMapping = new HashMap(); typeMapping.put("string", "kotlin.String"); typeMapping.put("boolean", "kotlin.Boolean"); @@ -250,7 +261,7 @@ public void setEnumPropertyNaming(final String enumPropertyNamingType) { } throw new RuntimeException(sb.toString()); } - } + } /** * Output the type declaration of the property @@ -270,8 +281,8 @@ public String getTypeDeclaration(Schema propertySchema) { return null; } // Maps will be keyed only by primitive Kotlin string - return String.format("%s", getSchemaType(propertySchema), getTypeDeclaration(inner)); - } + return String.format("%s", getSchemaType(propertySchema), getTypeDeclaration(inner)); + } return super.getTypeDeclaration(propertySchema); } @@ -287,8 +298,6 @@ public String getAlias(String name) { public String getSchemaType(Schema schema) { String schemaType = super.getSchemaType(schema); - schemaType = getAlias(schemaType); - // don't apply renaming on types from the typeMapping if (typeMapping.containsKey(schemaType)) { return toModelName(typeMapping.get(schemaType)); @@ -301,7 +310,7 @@ public String getSchemaType(Schema schema) { } else { return toModelName("kotlin.Any"); } - } + } return toModelName(schemaType); } @@ -496,9 +505,9 @@ public String toModelName(final String name) { @Override public String toVarName(String name) { - return super.toVarName(sanitizeKotlinSpecificNames(name)); + return super.toVarName(sanitizeKotlinSpecificNames(name)); } - + /** * Provides a strongly typed declaration for simple arrays of some type and arrays of arrays of some type. * @@ -515,7 +524,7 @@ private String getArrayTypeDeclaration(ArraySchema arraySchema) { // TODO: We may want to differentiate here between generics and primitive arrays. instantiationType.append("<").append(nestedType).append(">"); return instantiationType.toString(); - } + } /** * Sanitize against Kotlin specific naming conventions, which may differ from those required by {@link DefaultCodegen#sanitizeName}. @@ -566,7 +575,13 @@ protected boolean isReservedWord(String word) { @Override protected boolean needToImport(String type) { // provides extra protection against improperly trying to import language primitives and java types - boolean imports = !type.startsWith("kotlin.") && !type.startsWith("java.") && !defaultIncludes.contains(type) && !languageSpecificPrimitives.contains(type); + boolean imports = + !type.startsWith("kotlin.") && + !type.startsWith("java.") && + !defaultIncludes.contains(type) && + !languageSpecificPrimitives.contains(type) && + !instantiationLibraryFunction.contains(type); + return imports; } } diff --git a/src/main/java/io/swagger/codegen/languages/kotlin/KotlinServerCodegen.java b/src/main/java/io/swagger/codegen/languages/kotlin/KotlinServerCodegen.java index dc5c228c9d..40f3840858 100644 --- a/src/main/java/io/swagger/codegen/languages/kotlin/KotlinServerCodegen.java +++ b/src/main/java/io/swagger/codegen/languages/kotlin/KotlinServerCodegen.java @@ -3,12 +3,15 @@ import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; -import io.swagger.codegen.CodegenOperation; +import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.codegen.CliOption; import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenType; +import io.swagger.codegen.CodegenModel; +import io.swagger.codegen.CodegenProperty; +import io.swagger.codegen.CodegenOperation; import io.swagger.codegen.SupportingFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,15 +38,15 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen { private Boolean compressionFeatureEnabled = true; // This is here to potentially warn the user when an option is not supoprted by the target framework. - private Map> optionsSupportedPerFramework = - singletonMap(Constants.KTOR, + private Map> optionsSupportedPerFramework = + singletonMap(Constants.KTOR, Arrays.asList( Constants.AUTOMATIC_HEAD_REQUESTS, Constants.CONDITIONAL_HEADERS, Constants.HSTS, Constants.CORS, Constants.COMPRESSION - )); + )); /** * Constructs an instance of `KotlinServerCodegen`. @@ -128,9 +131,21 @@ public CodegenType getTag() { return CodegenType.SERVER; } + /** + * Handle typealias for schema of Array type + */ + @Override + public CodegenModel fromModel(String name, Schema schema, Map allDefinitions) { + CodegenModel codegenModel = super.fromModel(name, schema, allDefinitions); + + if (schema instanceof ArraySchema) { + codegenModel.dataType = getTypeDeclaration(schema); + } + return codegenModel; + } + @Override public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map schemas, OpenAPI openAPI) { - // Ensure that the parameter names in the path are valid kotlin names // they need to match the names in the generated data class, this is required by ktor Location String modifiedPath = path; @@ -198,7 +213,6 @@ public void processOpts() { String packageFolder = (sourceFolder + File.separator + packageName).replace(".", File.separator); String resourcesFolder = "src/main/resources"; // not sure this can be user configurable. - Boolean generateApis = additionalProperties.containsKey(GENERATE_APIS) && (Boolean)additionalProperties.get(GENERATE_APIS); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); @@ -210,9 +224,9 @@ public void processOpts() { supportingFiles.add(new SupportingFile("AppMain.kt.mustache", packageFolder, "AppMain.kt")); supportingFiles.add(new SupportingFile("Configuration.kt.mustache", packageFolder, "Configuration.kt")); - + if (generateApis) { - supportingFiles.add(new SupportingFile("Paths.kt.mustache", packageFolder, "Paths.kt")); + supportingFiles.add(new SupportingFile("Paths.kt.mustache", packageFolder, "Paths.kt")); } supportingFiles.add(new SupportingFile("application.conf.mustache", resourcesFolder, "application.conf")); diff --git a/src/main/resources/v2/kotlin-server/model.mustache b/src/main/resources/v2/kotlin-server/model.mustache index 852d62cdbd..6f0f576000 100644 --- a/src/main/resources/v2/kotlin-server/model.mustache +++ b/src/main/resources/v2/kotlin-server/model.mustache @@ -9,6 +9,6 @@ import org.threeten.bp.LocalDateTime {{#models}} {{#model}} -{{#is this 'alias'}}typealias {{classname}} = {{dataType}}{{/is}}{{#isNot this 'alias'}}{{#is this 'enum'}}{{>enum_class}}{{/is}}{{#isNot this 'enum'}}{{>data_class}}{{/isNot}}{{/isNot}} +{{#is this 'alias'}}typealias {{classname}} = {{{dataType}}}{{/is}}{{#isNot this 'alias'}}{{#is this 'enum'}}{{>enum_class}}{{/is}}{{#isNot this 'enum'}}{{>data_class}}{{/isNot}}{{/isNot}} {{/model}} {{/models}}