From cf29908ff2909e3c8a880a7a3f584db664354e7c Mon Sep 17 00:00:00 2001 From: SAnDAnGE Date: Thu, 31 Oct 2019 20:55:29 +0200 Subject: [PATCH] typescript-angular: fix oneOf and anyOf generates incorrect model for primitive types (#4341) * [typescript-angular] Fix importMapping; https://github.com/OpenAPITools/openapi-generator/issues/3149 * [typescript] Fix oneOf/anyOf/allOf; https://github.com/OpenAPITools/openapi-generator/issues/4130 * [typescript] remove unneeded mapping https://github.com/OpenAPITools/openapi-generator/issues/3149 * [typescript] fix import paths and export https://github.com/OpenAPITools/openapi-generator/issues/3149 --- .../AbstractTypeScriptClientCodegen.java | 61 ++++++++++++++++-- .../TypeScriptAngularClientCodegen.java | 38 ++++------- .../typescript-angular/model.mustache | 2 +- .../typescript-angular/models.mustache | 2 +- .../TypeScriptAngularClientCodegenTest.java | 2 +- .../TypeScriptAngularModelTest.java | 63 +++++++++++++++++++ 6 files changed, 135 insertions(+), 33 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java index 1500a1405ce..0676c8f2413 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractTypeScriptClientCodegen.java @@ -34,6 +34,7 @@ import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import static org.openapitools.codegen.utils.StringUtils.camelize; import static org.openapitools.codegen.utils.StringUtils.underscore; @@ -441,12 +442,16 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp public String getSchemaType(Schema p) { String openAPIType = super.getSchemaType(p); String type = null; - if (typeMapping.containsKey(openAPIType)) { + if (ModelUtils.isComposedSchema(p)) { + return openAPIType; + } else if (typeMapping.containsKey(openAPIType)) { type = typeMapping.get(openAPIType); - if (languageSpecificPrimitives.contains(type)) + if (languageSpecificPrimitives.contains(type)) { return type; - } else + } + } else { type = openAPIType; + } return toModelName(type); } @@ -560,6 +565,20 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp } } + @Override + protected void addImport(CodegenModel m, String type) { + if (type == null) { + return; + } + + String[] parts = type.split("( [|&] )|[<>]"); + for (String s : parts) { + if (needToImport(s)) { + m.imports.add(s); + } + } + } + @Override public Map postProcessModels(Map objs) { // process enum in models @@ -701,11 +720,43 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp @Override public String toAnyOfName(List names, ComposedSchema composedSchema) { - return String.join(" | ", names); + List types = composedSchema.getAnyOf().stream().map(schema -> { + String schemaType = getSchemaType(schema); + if (ModelUtils.isArraySchema(schema)) { + ArraySchema ap = (ArraySchema) schema; + Schema inner = ap.getItems(); + schemaType = schemaType + "<" + getSchemaType(inner) + ">"; + } + return schemaType; + }).distinct().collect(Collectors.toList()); + return String.join(" | ", types); } @Override public String toOneOfName(List names, ComposedSchema composedSchema) { - return String.join(" | ", names); + List types = composedSchema.getOneOf().stream().map(schema -> { + String schemaType = getSchemaType(schema); + if (ModelUtils.isArraySchema(schema)) { + ArraySchema ap = (ArraySchema) schema; + Schema inner = ap.getItems(); + schemaType = schemaType + "<" + getSchemaType(inner) + ">"; + } + return schemaType; + }).distinct().collect(Collectors.toList()); + return String.join(" | ", types); + } + + @Override + public String toAllOfName(List names, ComposedSchema composedSchema) { + List types = composedSchema.getAllOf().stream().map(schema -> { + String schemaType = getSchemaType(schema); + if (ModelUtils.isArraySchema(schema)) { + ArraySchema ap = (ArraySchema) schema; + Schema inner = ap.getItems(); + schemaType = schemaType + "<" + getSchemaType(inner) + ">"; + } + return schemaType; + }).distinct().collect(Collectors.toList()); + return String.join(" & ", types); } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java index 5470f9ca917..c4cc372e35a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java @@ -40,6 +40,8 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode private static String CLASS_NAME_SUFFIX_PATTERN = "^[a-zA-Z0-9]*$"; private static String FILE_NAME_SUFFIX_PATTERN = "^[a-zA-Z0-9.-]*$"; + private static final String DEFAULT_IMPORT_PREFIX = "./"; + public static final String NPM_REPOSITORY = "npmRepository"; public static final String WITH_INTERFACES = "withInterfaces"; public static final String TAGGED_UNIONS = "taggedUnions"; @@ -330,16 +332,6 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode } - @Override - public String getSchemaType(Schema p) { - String openAPIType = super.getSchemaType(p); - if (isLanguagePrimitive(openAPIType) || isLanguageGenericType(openAPIType)) { - return openAPIType; - } - applyLocalTypeMapping(openAPIType); - return openAPIType; - } - private String applyLocalTypeMapping(String type) { if (typeMapping.containsKey(type)) { type = typeMapping.get(type); @@ -347,19 +339,6 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode return type; } - private boolean isLanguagePrimitive(String type) { - return languageSpecificPrimitives.contains(type); - } - - private boolean isLanguageGenericType(String type) { - for (String genericType : languageGenericTypes) { - if (type.startsWith(genericType + "<")) { - return true; - } - } - return false; - } - @Override public void postProcessParameter(CodegenParameter parameter) { super.postProcessParameter(parameter); @@ -567,17 +546,26 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode @Override public String toApiImport(String name) { + if (importMapping.containsKey(name)) { + return importMapping.get(name); + } return apiPackage() + "/" + toApiFilename(name); } @Override public String toModelFilename(String name) { - return this.convertUsingFileNamingConvention(this.sanitizeName(name)) + modelFileSuffix; + if (importMapping.containsKey(name)) { + return importMapping.get(name); + } + return DEFAULT_IMPORT_PREFIX + this.convertUsingFileNamingConvention(this.sanitizeName(name)) + modelFileSuffix; } @Override public String toModelImport(String name) { - return modelPackage() + "/" + toModelFilename(name); + if (importMapping.containsKey(name)) { + return importMapping.get(name); + } + return modelPackage() + "/" + toModelFilename(name).substring(DEFAULT_IMPORT_PREFIX.length()); } public String getNpmRepository() { diff --git a/modules/openapi-generator/src/main/resources/typescript-angular/model.mustache b/modules/openapi-generator/src/main/resources/typescript-angular/model.mustache index 0afee532731..461d2e6a89f 100644 --- a/modules/openapi-generator/src/main/resources/typescript-angular/model.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-angular/model.mustache @@ -2,7 +2,7 @@ {{#models}} {{#model}} {{#tsImports}} -import { {{classname}} } from './{{filename}}'; +import { {{classname}} } from '{{filename}}'; {{/tsImports}} diff --git a/modules/openapi-generator/src/main/resources/typescript-angular/models.mustache b/modules/openapi-generator/src/main/resources/typescript-angular/models.mustache index 02a39c248c4..995ffee1621 100644 --- a/modules/openapi-generator/src/main/resources/typescript-angular/models.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-angular/models.mustache @@ -1,5 +1,5 @@ {{#models}} {{#model}} -export * from './{{{ classFilename }}}'; +export * from '{{{ classFilename }}}'; {{/model}} {{/models}} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java index 8adc9328ec5..b0489ac2218 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java @@ -22,7 +22,7 @@ public class TypeScriptAngularClientCodegenTest { codegen.additionalProperties().put("modelSuffix", "MySuffix"); codegen.processOpts(); - Assert.assertEquals("testNameMySuffix", codegen.toModelFilename("testName")); + Assert.assertEquals("./testNameMySuffix", codegen.toModelFilename("testName")); } @Test diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularModelTest.java index 77f89e537de..c12fed813de 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularModelTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularModelTest.java @@ -196,6 +196,69 @@ public class TypeScriptAngularModelTest { Assert.assertEquals(cm.vars.size(), 0); } + @Test(description = "convert an array oneof model") + public void arrayOneOfModelTest() { + final Schema schema = new ArraySchema() + .items(new ComposedSchema() + .addOneOfItem(new StringSchema()) + .addOneOfItem(new IntegerSchema().format("int64"))) + .description("an array oneof model"); + final DefaultCodegen codegen = new TypeScriptAngularClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", schema); + + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "an array oneof model"); + Assert.assertEquals(cm.arrayModelType, "string | number"); + Assert.assertEquals(cm.vars.size(), 0); + } + + @Test(description = "convert an any of with array oneof model") + public void objectPropertyAnyOfWithArrayOneOfModelTest() { + final Schema schema = new ObjectSchema().addProperties("value", + new ComposedSchema().addAnyOfItem(new StringSchema()).addAnyOfItem(new ArraySchema() + .items(new ComposedSchema() + .addOneOfItem(new StringSchema()) + .addOneOfItem(new IntegerSchema().format("int64"))))) + .description("an any of with array oneof model"); + final DefaultCodegen codegen = new TypeScriptAngularClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", schema); + + String s = codegen.getSchemaType((Schema)schema.getProperties().get("value")); + + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "an any of with array oneof model"); + Assert.assertEquals(cm.vars.size(), 1); + Assert.assertEquals(s, "string | Array"); + } + + @Test(description = "import a typemapping") + public void importTypeMappingModelTest() { + final Schema schema = new ArraySchema() + .items(new Schema().$ref("Children")) + .description("a typemapping array model"); + final DefaultCodegen codegen = new TypeScriptAngularClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema); + codegen.setOpenAPI(openAPI); + codegen.typeMapping().put("Children", "Test"); + codegen.importMapping().put("Test", "@myTest/package"); + final CodegenModel cm = codegen.fromModel("sample", schema); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a typemapping array model"); + Assert.assertEquals(cm.vars.size(), 0); + Assert.assertEquals(cm.imports.size(), 1); + Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Test")).size(), 1); + } + @Test(description = "convert a map model") public void mapModelTest() { final Schema schema = new Schema()