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
This commit is contained in:
SAnDAnGE 2019-10-31 20:55:29 +02:00 committed by Esteban Gehring
parent cd11cc2615
commit cf29908ff2
6 changed files with 135 additions and 33 deletions

View File

@ -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<String, Object> postProcessModels(Map<String, Object> objs) {
// process enum in models
@ -701,11 +720,43 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
@Override
public String toAnyOfName(List<String> names, ComposedSchema composedSchema) {
return String.join(" | ", names);
List<String> 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<String> names, ComposedSchema composedSchema) {
return String.join(" | ", names);
List<String> 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<String> names, ComposedSchema composedSchema) {
List<String> 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);
}
}

View File

@ -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() {

View File

@ -2,7 +2,7 @@
{{#models}}
{{#model}}
{{#tsImports}}
import { {{classname}} } from './{{filename}}';
import { {{classname}} } from '{{filename}}';
{{/tsImports}}

View File

@ -1,5 +1,5 @@
{{#models}}
{{#model}}
export * from './{{{ classFilename }}}';
export * from '{{{ classFilename }}}';
{{/model}}
{{/models}}

View File

@ -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

View File

@ -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<string | number>");
}
@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()