From 24b234bdbb09e974fd498637b773e9acfa1cdf9b Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 17 Sep 2018 23:18:52 +0800 Subject: [PATCH] Minor improvement to Dart generators (#1042) --- .../codegen/languages/DartClientCodegen.java | 6 +- .../languages/DartJaguarClientCodegen.java | 25 +- .../codegen/dart/DartModelTest.java | 316 ++++++++++++++++++ 3 files changed, 325 insertions(+), 22 deletions(-) create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java index f142d21f45e..4366549596e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java @@ -28,14 +28,12 @@ import org.openapitools.codegen.SupportingFile; import org.openapitools.codegen.utils.ModelUtils; import io.swagger.v3.oas.models.media.*; -import io.swagger.v3.parser.util.SchemaTypeUtil; import org.apache.commons.lang3.StringUtils; import org.apache.commons.io.FilenameUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -200,7 +198,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig { additionalProperties.put("modelDocPath", modelDocPath); final Object isSupportDart2 = additionalProperties.get(SUPPORT_DART2); - if (Boolean.FALSE.equals(isSupportDart2) || (isSupportDart2 instanceof String && !Boolean.parseBoolean((String)isSupportDart2))) { + if (Boolean.FALSE.equals(isSupportDart2) || (isSupportDart2 instanceof String && !Boolean.parseBoolean((String) isSupportDart2))) { // dart 1.x LOGGER.info("Dart version: 1.x"); supportingFiles.add(new SupportingFile("analysis_options.mustache", "", ".analysis_options")); @@ -531,7 +529,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig { return; } - // only process files with dart extension + // only process files with dart extension if ("dart".equals(FilenameUtils.getExtension(file.toString()))) { // currently only support "dartfmt -w yourcode.dart" String command = dartFmtPath + " -w " + file.toString(); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartJaguarClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartJaguarClientCodegen.java index f90ad474f45..9ca833b5f31 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartJaguarClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartJaguarClientCodegen.java @@ -16,17 +16,9 @@ package org.openapitools.codegen.languages; -import com.samskivert.mustache.Mustache; -import com.samskivert.mustache.Template; -import io.swagger.models.Model; -import org.openapitools.codegen.CliOption; -import org.openapitools.codegen.CodegenConfig; import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.CodegenProperty; -import org.openapitools.codegen.CodegenType; -import org.openapitools.codegen.DefaultCodegen; import org.openapitools.codegen.SupportingFile; import org.openapitools.codegen.utils.ModelUtils; @@ -35,9 +27,6 @@ import io.swagger.v3.oas.models.media.*; import org.apache.commons.lang3.StringUtils; import java.io.File; -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -46,12 +35,14 @@ import java.util.Set; public class DartJaguarClientCodegen extends DartClientCodegen { private static Set modelToIgnore = new HashSet<>(); + static { modelToIgnore.add("datetime"); - modelToIgnore.add("list"); modelToIgnore.add("map"); + modelToIgnore.add("list"); modelToIgnore.add("file"); } + public DartJaguarClientCodegen() { super(); browserClient = false; @@ -133,7 +124,6 @@ public class DartJaguarClientCodegen extends DartClientCodegen { supportingFiles.add(new SupportingFile("auth/auth.mustache", authFolder, "auth.dart")); } - @Override public Map postProcessModels(Map objs) { objs = super.postProcessModels(objs); @@ -143,14 +133,13 @@ public class DartJaguarClientCodegen extends DartClientCodegen { Set modelImports = new HashSet<>(); CodegenModel cm = (CodegenModel) mo.get("model"); for (String modelImport : cm.imports) { - if(!modelToIgnore.contains(modelImport.toLowerCase(Locale.ROOT))) { + if (!modelToIgnore.contains(modelImport.toLowerCase(Locale.ROOT))) { modelImports.add(underscore(modelImport)); } } cm.imports = modelImports; cm.vendorExtensions.put("hasVars", cm.vars.size() > 0); } - //objs.put("modelImports", modelImports); return objs; } @@ -167,7 +156,7 @@ public class DartJaguarClientCodegen extends DartClientCodegen { boolean isJson = true; //default to JSON boolean isForm = false; boolean isMultipart = false; - if(op.consumes != null) { + if (op.consumes != null) { for (Map consume : op.consumes) { if (consume.containsKey("mediaType")) { String type = consume.get("mediaType"); @@ -185,7 +174,7 @@ public class DartJaguarClientCodegen extends DartClientCodegen { Set imports = new HashSet<>(); for (String item : op.imports) { - if(!modelToIgnore.contains(item.toLowerCase(Locale.ROOT))) { + if (!modelToIgnore.contains(item.toLowerCase(Locale.ROOT))) { imports.add(underscore(item)); } } @@ -202,7 +191,7 @@ public class DartJaguarClientCodegen extends DartClientCodegen { jaguarPath = jaguarPath + items[i]; } - if (i != items.length -1) { + if (i != items.length - 1) { jaguarPath = jaguarPath + "/"; } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java new file mode 100644 index 00000000000..18f88f2f323 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java @@ -0,0 +1,316 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * Copyright 2018 SmartBear Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.dart; + +import io.swagger.parser.OpenAPIParser; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.*; +import io.swagger.v3.parser.core.models.ParseOptions; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenProperty; +import org.openapitools.codegen.DefaultCodegen; +import org.openapitools.codegen.languages.DartClientCodegen; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("static-method") +public class DartModelTest { + + @Test(description = "convert a simple php model") + public void simpleModelTest() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("id", new IntegerSchema()) + .addProperties("name", new StringSchema()) + .addProperties("createdAt", new DateTimeSchema()) + .addRequiredItem("id") + .addRequiredItem("name"); + final DefaultCodegen codegen = new DartClientCodegen(); + final CodegenModel cm = codegen.fromModel("sample", model, Collections.singletonMap("sample", model)); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 3); + // {{imports}} is not used in template + //Assert.assertEquals(cm.imports.size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "id"); + Assert.assertEquals(property1.dataType, "int"); + Assert.assertEquals(property1.name, "id"); + Assert.assertEquals(property1.defaultValue, "null"); + Assert.assertEquals(property1.baseType, "int"); + Assert.assertTrue(property1.hasMore); + Assert.assertTrue(property1.required); + Assert.assertTrue(property1.isPrimitiveType); + Assert.assertTrue(property1.isNotContainer); + + final CodegenProperty property2 = cm.vars.get(1); + Assert.assertEquals(property2.baseName, "name"); + Assert.assertEquals(property2.dataType, "String"); + Assert.assertEquals(property2.name, "name"); + Assert.assertEquals(property2.defaultValue, "null"); + Assert.assertEquals(property2.baseType, "String"); + Assert.assertTrue(property2.hasMore); + Assert.assertTrue(property2.required); + Assert.assertTrue(property2.isPrimitiveType); + Assert.assertTrue(property2.isNotContainer); + + final CodegenProperty property3 = cm.vars.get(2); + Assert.assertEquals(property3.baseName, "createdAt"); + Assert.assertEquals(property3.complexType, "DateTime"); + Assert.assertEquals(property3.dataType, "DateTime"); + Assert.assertEquals(property3.name, "createdAt"); + Assert.assertEquals(property3.defaultValue, "null"); + Assert.assertEquals(property3.baseType, "DateTime"); + Assert.assertFalse(property3.hasMore); + Assert.assertFalse(property3.required); + Assert.assertTrue(property3.isNotContainer); + } + + @Test(description = "convert a model with list property") + public void listPropertyTest() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("id", new IntegerSchema()) + .addProperties("urls", new ArraySchema() + .items(new StringSchema())) + .addRequiredItem("id"); + final DefaultCodegen codegen = new DartClientCodegen(); + final CodegenModel cm = codegen.fromModel("sample", model, Collections.singletonMap("sample", model)); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 2); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "id"); + Assert.assertEquals(property1.dataType, "int"); + Assert.assertEquals(property1.name, "id"); + Assert.assertEquals(property1.defaultValue, "null"); + Assert.assertEquals(property1.baseType, "int"); + Assert.assertTrue(property1.hasMore); + Assert.assertTrue(property1.required); + Assert.assertTrue(property1.isPrimitiveType); + Assert.assertTrue(property1.isNotContainer); + + final CodegenProperty property2 = cm.vars.get(1); + Assert.assertEquals(property2.baseName, "urls"); + Assert.assertEquals(property2.dataType, "List"); + Assert.assertEquals(property2.name, "urls"); + Assert.assertEquals(property2.baseType, "List"); + Assert.assertFalse(property2.hasMore); + Assert.assertEquals(property2.containerType, "array"); + Assert.assertFalse(property2.required); + Assert.assertTrue(property2.isPrimitiveType); + Assert.assertTrue(property2.isContainer); + } + + @Test(description = "convert a model with a map property") + public void mapPropertyTest() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("translations", new MapSchema() + .additionalProperties(new StringSchema())) + .addRequiredItem("id"); + final DefaultCodegen codegen = new DartClientCodegen(); + final CodegenModel cm = codegen.fromModel("sample", model, Collections.singletonMap("sample", model)); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "translations"); + Assert.assertEquals(property1.dataType, "Map"); + Assert.assertEquals(property1.name, "translations"); + Assert.assertEquals(property1.baseType, "Map"); + Assert.assertEquals(property1.containerType, "map"); + Assert.assertFalse(property1.required); + Assert.assertTrue(property1.isContainer); + Assert.assertTrue(property1.isPrimitiveType); + } + + @Test(description = "convert a model with complex property") + public void complexPropertyTest() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("children", new Schema().$ref("#/definitions/Children")); + final DefaultCodegen codegen = new DartClientCodegen(); + final CodegenModel cm = codegen.fromModel("sample", model, Collections.singletonMap("sample", model)); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "children"); + Assert.assertEquals(property1.dataType, "Children"); + Assert.assertEquals(property1.name, "children"); + Assert.assertEquals(property1.baseType, "Children"); + Assert.assertFalse(property1.required); + Assert.assertTrue(property1.isNotContainer); + } + + @Test(description = "convert a model with complex list property") + public void complexListProperty() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("children", new ArraySchema() + .items(new Schema().$ref("#/definitions/Children"))); + final DefaultCodegen codegen = new DartClientCodegen(); + final CodegenModel cm = codegen.fromModel("sample", model, Collections.singletonMap("sample", model)); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "children"); + Assert.assertEquals(property1.dataType, "List"); + Assert.assertEquals(property1.name, "children"); + Assert.assertEquals(property1.baseType, "List"); + Assert.assertEquals(property1.containerType, "array"); + Assert.assertFalse(property1.required); + Assert.assertTrue(property1.isContainer); + } + + @Test(description = "convert a model with complex map property") + public void complexMapSchema() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("children", new MapSchema() + .additionalProperties(new Schema().$ref("#/definitions/Children"))); + final DefaultCodegen codegen = new DartClientCodegen(); + final CodegenModel cm = codegen.fromModel("sample", model, Collections.singletonMap("sample", model)); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 1); + // {{imports}} is not used in template + //Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Children")).size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "children"); + Assert.assertEquals(property1.complexType, "Children"); + Assert.assertEquals(property1.dataType, "Map"); + Assert.assertEquals(property1.name, "children"); + Assert.assertEquals(property1.baseType, "Map"); + Assert.assertEquals(property1.containerType, "map"); + Assert.assertFalse(property1.required); + Assert.assertTrue(property1.isContainer); + Assert.assertFalse(property1.isNotContainer); + } + + @Test(description = "convert an array model") + public void arrayModelTest() { + final Schema model = new ArraySchema() + .items(new Schema().$ref("#/definitions/Children")) + .description("an array model"); + final DefaultCodegen codegen = new DartClientCodegen(); + final CodegenModel cm = codegen.fromModel("sample", model, Collections.singletonMap("sample", model)); + + Assert.assertEquals(model.getDescription(), "an array model"); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertTrue(cm.isArrayModel); + Assert.assertEquals(cm.description, "an array model"); + Assert.assertEquals(cm.vars.size(), 0); + // skip import test as import is not used by PHP codegen + } + + @Test(description = "convert a map model") + public void mapModelTest() { + final Schema model = new Schema() + .description("a map model") + .additionalProperties(new Schema().$ref("#/definitions/Children")); + final DefaultCodegen codegen = new DartClientCodegen(); + final CodegenModel cm = codegen.fromModel("sample", model, Collections.singletonMap("sample", model)); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a map model"); + Assert.assertEquals(cm.vars.size(), 0); + // {{imports}} is not used in template + //Assert.assertEquals(cm.imports.size(), 2); + //Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Children")).size(), 1); + } + + @DataProvider(name = "modelNames") + public static Object[][] primeNumbers() { + return new Object[][] { + {"sample", "Sample"}, + {"sample_name", "SampleName"}, + {"sample__name", "SampleName"}, + {"/sample", "Sample"}, + {"\\sample", "\\Sample"}, + {"sample.name", "SampleName"}, + {"_sample", "Sample"}, + }; + } + + @Test(dataProvider = "modelNames", description = "avoid inner class") + public void modelNameTest(String name, String expectedName) { + final Schema model = new Schema(); + final DefaultCodegen codegen = new DartClientCodegen(); + final CodegenModel cm = codegen.fromModel(name, model, Collections.singletonMap(name, model)); + + Assert.assertEquals(cm.name, name); + Assert.assertEquals(cm.classname, expectedName); + } + + @Test(description = "test enum variable names for reserved words") + public void testReservedWord() throws Exception { + final DefaultCodegen codegen = new DartClientCodegen(); + Assert.assertEquals(codegen.toEnumVarName("public", null), "public_"); + Assert.assertEquals(codegen.toEnumVarName("Private", null), "private_"); + Assert.assertEquals(codegen.toEnumVarName("IF", null), "iF_"); + // should not escape non-reserved + Assert.assertEquals(codegen.toEnumVarName("hello", null), "hello_"); + } + + // datetime (or primitive type) not yet supported in HTTP request body + @Test(description = "returns DateTime when using `--model-name-prefix`") + public void dateTest() { + final OpenAPI model = new OpenAPIParser().readLocation("src/test/resources/2_0/datePropertyTest.json", null, new ParseOptions()).getOpenAPI(); + final DefaultCodegen codegen = new DartClientCodegen(); + codegen.setModelNamePrefix("foo"); + + final String path = "/tests/dateResponse"; + final Operation p = model.getPaths().get(path).getPost(); + final CodegenOperation op = codegen.fromOperation(path, "post", p, model.getComponents().getSchemas()); + + Assert.assertEquals(op.returnType, "DateTime"); + Assert.assertEquals(op.bodyParam.dataType, "DateTime"); + } +}