From 0823665acc0f9931f205b5afa5e3e7889febd6a0 Mon Sep 17 00:00:00 2001 From: Philzen Date: Tue, 28 May 2024 19:46:25 +0200 Subject: [PATCH 01/13] Remove debug output during test execution --- .../openapitools/codegen/go/GoClientCodegenTest.java | 4 ---- .../codegen/postman/PostmanCollectionCodegenTest.java | 11 ----------- .../test/java/org/openapitools/client/JSONTest.java | 1 - .../test/java/org/openapitools/client/JSONTest.java | 1 - .../test/java/org/openapitools/client/JSONTest.java | 1 - 5 files changed, 18 deletions(-) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java index 188cba014ffc..4e1f1e4b0162 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java @@ -130,7 +130,6 @@ public void testPrimitiveTypeInOneOf() throws IOException { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(configurator.toClientOptInput()).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path modelFile = Paths.get(output + "/model_example.go"); @@ -170,7 +169,6 @@ public void testMultipleRequiredPropertiesHasSameOneOfObject() throws IOExceptio DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(configurator.toClientOptInput()).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path docFile = Paths.get(output + "/docs/PetAPI.md"); @@ -366,7 +364,6 @@ public void testAdditionalPropertiesWithGoMod() throws Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(configurator.toClientOptInput()).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path goModFile = Paths.get(output + "/go.mod"); @@ -388,7 +385,6 @@ public void testAdditionalPropertiesWithoutGoMod() throws Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(configurator.toClientOptInput()).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path goModFile = Paths.get(output + "/go.mod"); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/postman/PostmanCollectionCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/postman/PostmanCollectionCodegenTest.java index e2ac9ea6c893..0840ef864d41 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/postman/PostmanCollectionCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/postman/PostmanCollectionCodegenTest.java @@ -98,7 +98,6 @@ public void testBasicGenerationJson() throws IOException { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(clientOptInput).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path path = Paths.get(output + "/postman.json"); @@ -185,7 +184,6 @@ public void testVariablesInRequestExample() throws Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(clientOptInput).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path path = Paths.get(output + "/postman.json"); @@ -223,7 +221,6 @@ public void testSkipPostmanVariables() throws Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(clientOptInput).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path path = Paths.get(output + "/postman.json"); @@ -250,7 +247,6 @@ public void testGenerateWithoutPathParamsVariables() throws Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(configurator.toClientOptInput()).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); assertFileExists(Paths.get(output + "/postman.json")); @@ -277,7 +273,6 @@ public void testComponentExamples() throws Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(clientOptInput).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path path = Paths.get(output + "/postman.json"); @@ -303,7 +298,6 @@ public void testNamingRequestsWithUrl() throws Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(clientOptInput).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path path = Paths.get(output + "/postman.json"); @@ -330,7 +324,6 @@ public void testExampleFromSchema() throws IOException, Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(configurator.toClientOptInput()).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path path = Paths.get(output + "/postman.json"); @@ -355,7 +348,6 @@ public void testSecuritySchemes() throws Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(clientOptInput).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path path = Paths.get(output + "/postman.json"); @@ -395,7 +387,6 @@ public void testJsonExampleIncludingValueWithCommas() throws Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(clientOptInput).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path path = Paths.get(output + "/postman.json"); @@ -419,7 +410,6 @@ public void testGeneratedVariables() throws Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(clientOptInput).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path path = Paths.get(output + "/postman.json"); @@ -447,7 +437,6 @@ public void testSkipGeneratedVariables() throws IOException, Exception { DefaultGenerator generator = new DefaultGenerator(); List files = generator.opts(clientOptInput).generate(); - System.out.println(files); files.forEach(File::deleteOnExit); Path path = Paths.get(output + "/postman.json"); diff --git a/samples/client/petstore/java/jersey2-java8/src/test/java/org/openapitools/client/JSONTest.java b/samples/client/petstore/java/jersey2-java8/src/test/java/org/openapitools/client/JSONTest.java index bd01fa26adbd..3418b5cdb0e7 100644 --- a/samples/client/petstore/java/jersey2-java8/src/test/java/org/openapitools/client/JSONTest.java +++ b/samples/client/petstore/java/jersey2-java8/src/test/java/org/openapitools/client/JSONTest.java @@ -48,7 +48,6 @@ public void testRFC3339DateFormatDate() throws Exception { RFC3339DateFormat df = new RFC3339DateFormat(); StringBuffer sb = new StringBuffer(); String s = df.format(date); - System.out.println("DATE: " + s); assertEquals("2011-01-18T00:00:00.000+00:00", s); } { diff --git a/samples/client/petstore/java/jersey3/src/test/java/org/openapitools/client/JSONTest.java b/samples/client/petstore/java/jersey3/src/test/java/org/openapitools/client/JSONTest.java index b5e9d7872a0e..81897683e31c 100644 --- a/samples/client/petstore/java/jersey3/src/test/java/org/openapitools/client/JSONTest.java +++ b/samples/client/petstore/java/jersey3/src/test/java/org/openapitools/client/JSONTest.java @@ -46,7 +46,6 @@ public void testRFC3339DateFormatDate() throws Exception { RFC3339DateFormat df = new RFC3339DateFormat(); StringBuffer sb = new StringBuffer(); String s = df.format(date); - System.out.println("DATE: " + s); assertEquals("2011-01-18T00:00:00.000+00:00", s); } { diff --git a/samples/openapi3/client/petstore/java/jersey2-java8/src/test/java/org/openapitools/client/JSONTest.java b/samples/openapi3/client/petstore/java/jersey2-java8/src/test/java/org/openapitools/client/JSONTest.java index b5e9d7872a0e..81897683e31c 100644 --- a/samples/openapi3/client/petstore/java/jersey2-java8/src/test/java/org/openapitools/client/JSONTest.java +++ b/samples/openapi3/client/petstore/java/jersey2-java8/src/test/java/org/openapitools/client/JSONTest.java @@ -46,7 +46,6 @@ public void testRFC3339DateFormatDate() throws Exception { RFC3339DateFormat df = new RFC3339DateFormat(); StringBuffer sb = new StringBuffer(); String s = df.format(date); - System.out.println("DATE: " + s); assertEquals("2011-01-18T00:00:00.000+00:00", s); } { From 0f402924d00fbecc6a61a138842ee8f8d0404836 Mon Sep 17 00:00:00 2001 From: Philzen Date: Tue, 28 May 2024 21:33:46 +0200 Subject: [PATCH 02/13] Move Test into matching namespace --- .../codegen/{go => languages}/GoClientCodegenTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename modules/openapi-generator/src/test/java/org/openapitools/codegen/{go => languages}/GoClientCodegenTest.java (99%) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/GoClientCodegenTest.java similarity index 99% rename from modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java rename to modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/GoClientCodegenTest.java index 4e1f1e4b0162..5b836f15ac7b 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/GoClientCodegenTest.java @@ -15,13 +15,12 @@ * limitations under the License. */ -package org.openapitools.codegen.go; +package org.openapitools.codegen.languages; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import org.openapitools.codegen.*; import org.openapitools.codegen.config.CodegenConfigurator; -import org.openapitools.codegen.languages.GoClientCodegen; import org.testng.Assert; import org.testng.annotations.Test; From 2fa712976b2aa36522b4b8d151ec160aeb021203 Mon Sep 17 00:00:00 2001 From: Philzen Date: Tue, 28 May 2024 21:15:37 +0200 Subject: [PATCH 03/13] Add test for lib fmt being added for enum models --- .../languages/GoClientCodegenTest.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/GoClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/GoClientCodegenTest.java index 5b836f15ac7b..a7508f7f04b4 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/GoClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/GoClientCodegenTest.java @@ -17,10 +17,15 @@ package org.openapitools.codegen.languages; +import io.swagger.parser.OpenAPIParser; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; +import org.assertj.core.api.Assertions; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; import org.openapitools.codegen.*; import org.openapitools.codegen.config.CodegenConfigurator; +import org.openapitools.codegen.model.ModelsMap; import org.testng.Assert; import org.testng.annotations.Test; @@ -33,6 +38,8 @@ import java.util.List; import java.util.Map; +import static org.assertj.core.api.Assertions.assertThat; + public class GoClientCodegenTest { @@ -391,4 +398,55 @@ public void testAdditionalPropertiesWithoutGoMod() throws Exception { Path goSumFile = Paths.get(output + "/go.sum"); TestUtils.assertFileNotExists(goSumFile); } + + @Test + public void addsFmtImports_whenModelIsEnum() throws IOException { + ArgumentCaptor captor = ArgumentCaptor.forClass(ModelsMap.class); + + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final OpenAPI testSpec = new OpenAPIParser().readLocation("src/test/resources/3_0/enum.yaml", null, null).getOpenAPI(); + final GoClientCodegen codegen = Mockito.spy(new GoClientCodegen()); + codegen.setOutputDir(output.getAbsolutePath().replace("\\", "/")); + codegen.additionalProperties().put(GoClientCodegen.WITH_GO_MOD, false); + + DefaultGenerator generator = new DefaultGenerator(); + generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true"); + generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false"); + generator.setGenerateMetadata(false); + generator.opts(new ClientOptInput().config(codegen).openAPI(testSpec)).generate(); + + // postProcessModelsEnum is called for every model, hence expecting atLeast(2) + Mockito.verify(codegen, Mockito.atLeast(2)).postProcessModelsEnum(captor.capture()); + assertThat(captor.getAllValues()).extracting(ModelsMap::getImports) + .satisfiesExactly( + importList -> assertThat(importList).doesNotContain(Map.of("import", "fmt")), + importList -> assertThat(importList).contains(Map.of("import", "fmt")) + ); + } + + @Test + public void doesNotAddFmtImports_whenModelIsNotEnum() throws IOException { + ArgumentCaptor captor = ArgumentCaptor.forClass(ModelsMap.class); + + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final OpenAPI testSpec = new OpenAPIParser().readLocation("src/test/resources/3_0/arrayRefBody.yaml", null, null).getOpenAPI(); + final GoClientCodegen codegen = Mockito.spy(new GoClientCodegen()); + codegen.setOutputDir(output.getAbsolutePath().replace("\\", "/")); + codegen.additionalProperties().put(GoClientCodegen.WITH_GO_MOD, false); + final DefaultGenerator generator = new DefaultGenerator(); + generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true"); + generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false"); + generator.setGenerateMetadata(false); + + generator.opts(new ClientOptInput().config(codegen).openAPI(testSpec)).generate(); + + // postProcessModelsEnum is called for every model, hence expecting atLeast(1) + Mockito.verify(codegen, Mockito.atLeastOnce()).postProcessModelsEnum(captor.capture()); + assertThat(captor.getAllValues()).flatExtracting(ModelsMap::getImports) + .doesNotContain(Map.of("import", "fmt")); + } } From 5bd203217659051baabd074a6e914911803ffa4f Mon Sep 17 00:00:00 2001 From: Philzen Date: Wed, 29 May 2024 01:16:53 +0200 Subject: [PATCH 04/13] Add test for Arrays import being added for jersey, native and okhttp_gson libraries --- .../codegen/java/JavaClientCodegenTest.java | 48 ++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java index e28c05b52896..d23c4c0bf449 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java @@ -17,7 +17,7 @@ package org.openapitools.codegen.java; -import static org.junit.Assert.assertNotNull; +import static org.assertj.core.api.Assertions.assertThat; import static org.openapitools.codegen.TestUtils.assertFileContains; import static org.openapitools.codegen.TestUtils.assertFileNotContains; import static org.openapitools.codegen.TestUtils.validateJavaSourceFiles; @@ -49,16 +49,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; @@ -3474,4 +3465,39 @@ void testBuilderJavaClient() throws IOException { "hasLegs(getHasLegs())"); } + @DataProvider(name = "Libraries which add Arrays import independent of datatype") + public String[] libsRequiringArraysImport() { + return new String[] {"jersey2", "jersey3", "native", "okhttp-gson"}; + } + + @DataProvider(name = "Libraries which do not add Arrays import independent of datatype") + public String[] libsNotRequiringArraysImport() { + var supportedLibraries = new JavaClientCodegen().supportedLibraries().keySet(); + List.of(libsRequiringArraysImport()).forEach(supportedLibraries::remove); + return supportedLibraries.toArray(new String[0]); + } + + @Test(dataProvider = "Libraries which add Arrays import independent of datatype") + void importFmtAddedTo_libsRequiringArraysImport(String library) { + var model = new CodegenModel(); + model.setImports(new TreeSet<>()); + var codegen = new JavaClientCodegen(); + codegen.setLibrary(library); + + codegen.postProcessModelProperty(model, new CodegenProperty()); + + assertThat(model.getImports()).contains("Arrays"); + } + + @Test(dataProvider = "Libraries which do not add Arrays import independent of datatype") + void importFmtNotAddedTo_libsNotRequiringArraysImport(String library) { + var model = new CodegenModel(); + model.setImports(new TreeSet<>()); + var codegen = new JavaClientCodegen(); + codegen.setLibrary(library); + + codegen.postProcessModelProperty(model, new CodegenProperty()); + + assertThat(model.getImports()).doesNotContain("Arrays"); + } } From 32bdcb05a98cdb3ba5b5267cc95d6a20f1e759ab Mon Sep 17 00:00:00 2001 From: Philzen Date: Tue, 28 May 2024 22:51:29 +0200 Subject: [PATCH 05/13] Move implementation specific behavior into implementing class It is a violation of inheritance rules that a base class knows about its specific child behavior (except maybe in a sealed class scenario). --- .../codegen/languages/AbstractGoCodegen.java | 3 --- .../codegen/languages/AbstractJavaCodegen.java | 9 --------- .../openapitools/codegen/languages/GoClientCodegen.java | 1 + .../codegen/languages/JavaClientCodegen.java | 7 +++++++ 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java index 49269a51a425..d2155639233f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java @@ -760,9 +760,6 @@ public ModelsMap postProcessModels(ModelsMap objs) { addedOSImport = true; } } - if (this instanceof GoClientCodegen && model.isEnum) { - imports.add(createMapping("import", "fmt")); - } // if oneOf contains "null" type if (model.oneOf != null && !model.oneOf.isEmpty() && model.oneOf.contains("nil")) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index 0ca8bcc2b360..7c45152ba2f5 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -1790,15 +1790,6 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert } } - // hard-coded Arrays import in Java client as it has been removed from the templates - if (this instanceof JavaClientCodegen && - ("jersey2".equals(library) || - "jersey3".equals(library) || - "native".equals(library) || - "okhttp-gson".equals(library))) { - model.imports.add("Arrays"); - } - if ("array".equals(property.containerType)) { model.imports.add("ArrayList"); model.imports.add("Arrays"); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java index 060dfc277d73..4614b161fbd7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java @@ -478,6 +478,7 @@ public ModelsMap postProcessModels(ModelsMap objs) { for (ModelMap m : objs.getModels()) { CodegenModel model = m.getModel(); if (model.isEnum) { + imports.add(createMapping("import", "fmt")); continue; } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java index d50685efd69f..95fe28c39fbe 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java @@ -996,6 +996,13 @@ private static boolean isMultipartType(List> consumes) { @Override public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { super.postProcessModelProperty(model, property); + + // hard-coded Arrays import in Java client as it has been removed from the templates + final List libsRequiringArrayImport = List.of("jersey2", "jersey3", "native", "okhttp-gson"); + if (libsRequiringArrayImport.contains(library)) { + model.imports.add("Arrays"); + } + if (!BooleanUtils.toBoolean(model.isEnum)) { //final String lib = getLibrary(); //Needed imports for Jackson based libraries From 79dc2f297f69ccde0161b703dd334ed958231b91 Mon Sep 17 00:00:00 2001 From: Philzen Date: Wed, 29 May 2024 00:34:18 +0200 Subject: [PATCH 06/13] Simplify code by centralizing import fmt mapping --- .../codegen/languages/GoClientCodegen.java | 39 +++++++------------ .../echo_api/go-external-refs/model_pet.go | 2 +- samples/client/echo_api/go/model_pet.go | 2 +- .../model_additional_data.go | 2 +- .../model_base_item.go | 2 +- .../model_final_item.go | 2 +- .../model_nested_object1.go | 2 +- .../model_nested_object2.go | 2 +- .../petstore/go/go-petstore/model_animal.go | 2 +- .../petstore/go/go-petstore/model_big_cat.go | 2 +- .../petstore/go/go-petstore/model_cat.go | 2 +- .../petstore/go/go-petstore/model_category.go | 2 +- .../petstore/go/go-petstore/model_dog.go | 2 +- .../go/go-petstore/model_enum_test_.go | 2 +- .../go/go-petstore/model_format_test_.go | 2 +- .../petstore/go/go-petstore/model_name.go | 2 +- .../petstore/go/go-petstore/model_pet.go | 2 +- .../go-petstore/model_type_holder_default.go | 2 +- .../go-petstore/model_type_holder_example.go | 2 +- 19 files changed, 31 insertions(+), 44 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java index 4614b161fbd7..da275c38c20e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java @@ -477,8 +477,15 @@ public ModelsMap postProcessModels(ModelsMap objs) { for (ModelMap m : objs.getModels()) { CodegenModel model = m.getModel(); - if (model.isEnum) { + + if (model.isEnum + || model.hasRequired + || (model.oneOf != null && !model.oneOf.isEmpty()) + || (model.anyOf != null && !model.anyOf.isEmpty())) { imports.add(createMapping("import", "fmt")); + } + + if (model.isEnum) { continue; } @@ -500,31 +507,11 @@ public ModelsMap postProcessModels(ModelsMap objs) { } } - // additional import for different cases - boolean addedFmtImport = false; - - // oneOf - if (model.oneOf != null && !model.oneOf.isEmpty()) { - imports.add(createMapping("import", "fmt")); - addedFmtImport = true; - } - - // anyOf - if (model.anyOf != null && !model.anyOf.isEmpty()) { - imports.add(createMapping("import", "fmt")); - addedFmtImport = true; - } - - if (model.hasRequired) { - if (!model.isAdditionalPropertiesTrue && - (model.oneOf == null || model.oneOf.isEmpty()) && - (model.anyOf == null || model.anyOf.isEmpty())) { - imports.add(createMapping("import", "bytes")); - } - - if (!addedFmtImport) { - imports.add(createMapping("import", "fmt")); - } + if (model.hasRequired + && !model.isAdditionalPropertiesTrue + && (model.oneOf == null || model.oneOf.isEmpty()) + && (model.anyOf == null || model.anyOf.isEmpty())) { + imports.add(createMapping("import", "bytes")); } // additionalProperties: true and parent diff --git a/samples/client/echo_api/go-external-refs/model_pet.go b/samples/client/echo_api/go-external-refs/model_pet.go index 13f24706dfd5..8e6d06eda1cf 100644 --- a/samples/client/echo_api/go-external-refs/model_pet.go +++ b/samples/client/echo_api/go-external-refs/model_pet.go @@ -13,8 +13,8 @@ package openapi import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the Pet type satisfies the MappedNullable interface at compile time diff --git a/samples/client/echo_api/go/model_pet.go b/samples/client/echo_api/go/model_pet.go index 13f24706dfd5..8e6d06eda1cf 100644 --- a/samples/client/echo_api/go/model_pet.go +++ b/samples/client/echo_api/go/model_pet.go @@ -13,8 +13,8 @@ package openapi import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the Pet type satisfies the MappedNullable interface at compile time diff --git a/samples/client/others/go/allof_multiple_ref_and_discriminator/model_additional_data.go b/samples/client/others/go/allof_multiple_ref_and_discriminator/model_additional_data.go index a7186d87f51f..45335c8c57e3 100644 --- a/samples/client/others/go/allof_multiple_ref_and_discriminator/model_additional_data.go +++ b/samples/client/others/go/allof_multiple_ref_and_discriminator/model_additional_data.go @@ -12,8 +12,8 @@ package openapi import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the AdditionalData type satisfies the MappedNullable interface at compile time diff --git a/samples/client/others/go/allof_multiple_ref_and_discriminator/model_base_item.go b/samples/client/others/go/allof_multiple_ref_and_discriminator/model_base_item.go index 96d4179808c9..ad5fbcace114 100644 --- a/samples/client/others/go/allof_multiple_ref_and_discriminator/model_base_item.go +++ b/samples/client/others/go/allof_multiple_ref_and_discriminator/model_base_item.go @@ -12,8 +12,8 @@ package openapi import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the BaseItem type satisfies the MappedNullable interface at compile time diff --git a/samples/client/others/go/allof_multiple_ref_and_discriminator/model_final_item.go b/samples/client/others/go/allof_multiple_ref_and_discriminator/model_final_item.go index d3845f84998f..46af8b705c1e 100644 --- a/samples/client/others/go/allof_multiple_ref_and_discriminator/model_final_item.go +++ b/samples/client/others/go/allof_multiple_ref_and_discriminator/model_final_item.go @@ -12,8 +12,8 @@ package openapi import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the FinalItem type satisfies the MappedNullable interface at compile time diff --git a/samples/client/others/go/oneof-anyof-required/model_nested_object1.go b/samples/client/others/go/oneof-anyof-required/model_nested_object1.go index f403748a8968..8d27d02f5f5f 100644 --- a/samples/client/others/go/oneof-anyof-required/model_nested_object1.go +++ b/samples/client/others/go/oneof-anyof-required/model_nested_object1.go @@ -12,8 +12,8 @@ package openapi import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the NestedObject1 type satisfies the MappedNullable interface at compile time diff --git a/samples/client/others/go/oneof-anyof-required/model_nested_object2.go b/samples/client/others/go/oneof-anyof-required/model_nested_object2.go index c3f9468bc15c..9acea6f75d51 100644 --- a/samples/client/others/go/oneof-anyof-required/model_nested_object2.go +++ b/samples/client/others/go/oneof-anyof-required/model_nested_object2.go @@ -12,8 +12,8 @@ package openapi import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the NestedObject2 type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_animal.go b/samples/client/petstore/go/go-petstore/model_animal.go index e23baa88fcc6..96cad2ca160f 100644 --- a/samples/client/petstore/go/go-petstore/model_animal.go +++ b/samples/client/petstore/go/go-petstore/model_animal.go @@ -12,8 +12,8 @@ package petstore import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the Animal type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_big_cat.go b/samples/client/petstore/go/go-petstore/model_big_cat.go index 4000f2096d9d..b4048057a9c0 100644 --- a/samples/client/petstore/go/go-petstore/model_big_cat.go +++ b/samples/client/petstore/go/go-petstore/model_big_cat.go @@ -12,8 +12,8 @@ package petstore import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the BigCat type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_cat.go b/samples/client/petstore/go/go-petstore/model_cat.go index b3937685f6af..26e3c51a36da 100644 --- a/samples/client/petstore/go/go-petstore/model_cat.go +++ b/samples/client/petstore/go/go-petstore/model_cat.go @@ -12,8 +12,8 @@ package petstore import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the Cat type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_category.go b/samples/client/petstore/go/go-petstore/model_category.go index d19362640391..f13401a120b6 100644 --- a/samples/client/petstore/go/go-petstore/model_category.go +++ b/samples/client/petstore/go/go-petstore/model_category.go @@ -12,8 +12,8 @@ package petstore import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the Category type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_dog.go b/samples/client/petstore/go/go-petstore/model_dog.go index 92d5dece9e79..a232089dc421 100644 --- a/samples/client/petstore/go/go-petstore/model_dog.go +++ b/samples/client/petstore/go/go-petstore/model_dog.go @@ -12,8 +12,8 @@ package petstore import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the Dog type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_enum_test_.go b/samples/client/petstore/go/go-petstore/model_enum_test_.go index cf858376f48b..6302e7c0aaf2 100644 --- a/samples/client/petstore/go/go-petstore/model_enum_test_.go +++ b/samples/client/petstore/go/go-petstore/model_enum_test_.go @@ -12,8 +12,8 @@ package petstore import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the EnumTest type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_format_test_.go b/samples/client/petstore/go/go-petstore/model_format_test_.go index d2cb7e88a331..c03b63c2a7dc 100644 --- a/samples/client/petstore/go/go-petstore/model_format_test_.go +++ b/samples/client/petstore/go/go-petstore/model_format_test_.go @@ -14,8 +14,8 @@ import ( "encoding/json" "os" "time" - "bytes" "fmt" + "bytes" ) // checks if the FormatTest type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_name.go b/samples/client/petstore/go/go-petstore/model_name.go index 7e009e1cf0b5..7138d25d4913 100644 --- a/samples/client/petstore/go/go-petstore/model_name.go +++ b/samples/client/petstore/go/go-petstore/model_name.go @@ -12,8 +12,8 @@ package petstore import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the Name type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_pet.go b/samples/client/petstore/go/go-petstore/model_pet.go index de782511daa3..54818f21f053 100644 --- a/samples/client/petstore/go/go-petstore/model_pet.go +++ b/samples/client/petstore/go/go-petstore/model_pet.go @@ -12,8 +12,8 @@ package petstore import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the Pet type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_type_holder_default.go b/samples/client/petstore/go/go-petstore/model_type_holder_default.go index 8a67e9f7a2df..a52e10d62d33 100644 --- a/samples/client/petstore/go/go-petstore/model_type_holder_default.go +++ b/samples/client/petstore/go/go-petstore/model_type_holder_default.go @@ -12,8 +12,8 @@ package petstore import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the TypeHolderDefault type satisfies the MappedNullable interface at compile time diff --git a/samples/client/petstore/go/go-petstore/model_type_holder_example.go b/samples/client/petstore/go/go-petstore/model_type_holder_example.go index a08223070828..2e02490f3c62 100644 --- a/samples/client/petstore/go/go-petstore/model_type_holder_example.go +++ b/samples/client/petstore/go/go-petstore/model_type_holder_example.go @@ -12,8 +12,8 @@ package petstore import ( "encoding/json" - "bytes" "fmt" + "bytes" ) // checks if the TypeHolderExample type satisfies the MappedNullable interface at compile time From e1bd9eb956799b1352a57eba43c8554b7f2ec279 Mon Sep 17 00:00:00 2001 From: Philzen Date: Wed, 29 May 2024 05:13:27 +0200 Subject: [PATCH 07/13] Inline variable which is only used once --- .../main/java/org/openapitools/codegen/DefaultCodegen.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 0682fe7c099b..04f532cd0d93 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -7156,8 +7156,6 @@ public List fromRequestBodyToFormParameters(RequestBody body, // https://github.com/OpenAPITools/openapi-generator/issues/10415 addProperties(properties, allRequired, schema, new HashSet<>()); - boolean isOneOfOrAnyOf = ModelUtils.isOneOf(schema) || ModelUtils.isAnyOf(schema); - if (!properties.isEmpty()) { for (Map.Entry entry : properties.entrySet()) { CodegenParameter codegenParameter; @@ -7167,7 +7165,7 @@ public List fromRequestBodyToFormParameters(RequestBody body, Schema propertySchema = entry.getValue(); codegenParameter = fromFormProperty(propertyName, propertySchema, imports); - if (isOneOfOrAnyOf) { + if (ModelUtils.isOneOf(schema) || ModelUtils.isAnyOf(schema)) { // for oneOf/anyOf, mark all the properties collected from the sub-schemas as optional // so that users can choose which property to include in the form parameters codegenParameter.required = false; From 3840787f1c815a1ebb326d85759899b4aad854e8 Mon Sep 17 00:00:00 2001 From: Philzen Date: Wed, 29 May 2024 14:08:42 +0200 Subject: [PATCH 08/13] Add test for parameter reference resolution --- .../codegen/DefaultCodegenTest.java | 32 +++++++++++ .../languages/RustServerCodegenTest.java | 57 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/RustServerCodegenTest.java diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index 8560323b31f5..6d7795095c16 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -31,6 +31,7 @@ import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.media.*; +import io.swagger.v3.oas.models.parameters.PathParameter; import io.swagger.v3.oas.models.parameters.QueryParameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; @@ -47,6 +48,7 @@ import org.openapitools.codegen.utils.SemVer; import org.slf4j.LoggerFactory; import org.testng.Assert; +import org.testng.annotations.BeforeTest; import org.testng.annotations.Ignore; import org.testng.annotations.Test; @@ -57,6 +59,7 @@ import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.InstanceOfAssertFactories.type; import static org.testng.Assert.*; public class DefaultCodegenTest { @@ -4933,4 +4936,33 @@ public void testAllVars_issue_18340() { CodegenModel springCat2 = springCodegen.fromModel("Cat2", cat2Model); assertThat(getNames(springCat2.allVars)).isEqualTo(List.of("petType", "name")); } + + @SuppressWarnings("NewClassNamingConvention") + public static class fromParameter { + + DefaultCodegen codegen = new DefaultCodegen(); + + @BeforeTest void setOpenAPI() { + codegen.setOpenAPI(new OpenAPI().components(new Components().addSchemas("SampleRequestInput", new ObjectSchema().addProperty("FormProp1", new StringSchema())))); + } + + @Test public void resolvesReferencedSchema() { + var parameter = new PathParameter() + .name("input") + .schema(new Schema<>().$ref("SampleRequestInput")); + + CodegenParameter result = codegen.fromParameter(parameter, new HashSet<>()); + + assertThat(result.getSchema()) + .returns("object", CodegenProperty::getBaseType) + .returns("Object", CodegenProperty::getDataType) + .returns(null, CodegenProperty::getRef) + .returns(true, CodegenProperty::getHasVars) + + .extracting(CodegenProperty::getVars).asList().hasSize(1) + .first(type(CodegenProperty.class)) + .returns("FormProp1", CodegenProperty::getName) + .returns("String", CodegenProperty::getDataType); + } + } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/RustServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/RustServerCodegenTest.java new file mode 100644 index 000000000000..8d9351150ca4 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/RustServerCodegenTest.java @@ -0,0 +1,57 @@ +package org.openapitools.codegen.languages; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.ObjectSchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.media.StringSchema; +import io.swagger.v3.oas.models.parameters.PathParameter; +import org.assertj.core.api.Assertions; +import org.openapitools.codegen.CodegenParameter; +import org.openapitools.codegen.CodegenProperty; +import org.openapitools.codegen.GeneratorLanguage; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RustServerCodegenTest { + + @Test public void generatorLanguageIsRust() { + Assertions.assertThat(new RustServerCodegen().generatorLanguage()) + .isSameAs(GeneratorLanguage.RUST); + } + + @SuppressWarnings("NewClassNamingConvention") + public static class fromParameter { + + RustServerCodegen codegen = new RustServerCodegen(); + + @BeforeTest void setOpenAPI() { + codegen.setOpenAPI(new OpenAPI().components(new Components().addSchemas( + "SampleRequestInput", + new ObjectSchema().addProperty( + "FormProp1", + new StringSchema() + ) + ))); + } + + + @Test public void doesNotResolveReferencedSchema() { + var parameter = new PathParameter() + .name("input") + .schema(new Schema<>().$ref("SampleRequestInput")); + + CodegenParameter result = codegen.fromParameter(parameter, new HashSet<>()); + + assertThat(result.getSchema()) + .returns("SampleRequestInput", CodegenProperty::getBaseType) + .returns("models::SampleRequestInput", CodegenProperty::getDataType) + .returns(false, CodegenProperty::getHasVars) + .extracting(CodegenProperty::getRef).asString().endsWith("SampleRequestInput"); + } + } +} \ No newline at end of file From efafbb50781331591f3fb0bf74e874249e076d56 Mon Sep 17 00:00:00 2001 From: Philzen Date: Wed, 29 May 2024 14:21:46 +0200 Subject: [PATCH 09/13] Move RustServerCodegen specific behaviour into class --- .../java/org/openapitools/codegen/DefaultCodegen.java | 8 ++------ .../openapitools/codegen/languages/RustServerCodegen.java | 7 +++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 04f532cd0d93..cdb8242183c0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -5276,11 +5276,7 @@ public CodegenParameter fromParameter(Parameter parameter, Set imports) parameterSchema = unaliasSchema(parameter.getSchema()); parameterModelName = getParameterDataType(parameter, parameterSchema); CodegenProperty prop; - if (this instanceof RustServerCodegen) { - // for rust server, we need to do somethings special as it uses - // $ref (e.g. #components/schemas/Pet) to determine whether it's a model - prop = fromProperty(parameter.getName(), parameterSchema, false); - } else if (getUseInlineModelResolver()) { + if (getUseInlineModelResolver()) { prop = fromProperty(parameter.getName(), getReferencedSchemaWhenNotEnum(parameterSchema), false); } else { prop = fromProperty(parameter.getName(), parameterSchema, false); @@ -5327,7 +5323,7 @@ public CodegenParameter fromParameter(Parameter parameter, Set imports) return codegenParameter; } - if (getUseInlineModelResolver() && !(this instanceof RustServerCodegen)) { + if (getUseInlineModelResolver()) { // for rust server, we cannot run the following as it uses // $ref (e.g. #components/schemas/Pet) to determine whether it's a model parameterSchema = getReferencedSchemaWhenNotEnum(parameterSchema); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java index 215af9d7e0ee..e0e2d4dcab85 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java @@ -1480,4 +1480,11 @@ protected String getParameterDataType(Parameter parameter, Schema schema) { } return null; } + + @Override + public boolean getUseInlineModelResolver() { + // for rust server, we need to do something special as it uses + // $ref (e.g. #components/schemas/Pet) to determine whether it's a model + return false; + } } From a4501cbcca12c5111a4678498bf206bec29fdee4 Mon Sep 17 00:00:00 2001 From: Philzen Date: Wed, 29 May 2024 14:40:11 +0200 Subject: [PATCH 10/13] Add individual setup parameters test --- .../micronaut/MicronautClientCodegenTest.java | 32 ++++++++++++++++++ .../micronaut/MicronautServerCodegenTest.java | 33 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/micronaut/MicronautClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/micronaut/MicronautClientCodegenTest.java index 2c449e9bfee9..0f3d5886d1da 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/micronaut/MicronautClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/micronaut/MicronautClientCodegenTest.java @@ -3,8 +3,10 @@ import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.servers.Server; +import org.assertj.core.api.Assertions; import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.languages.JavaMicronautAbstractCodegen; import org.openapitools.codegen.languages.JavaMicronautClientCodegen; import org.testng.Assert; import org.testng.annotations.Test; @@ -310,4 +312,34 @@ public void testConfigurePathSeparator() { // Micronaut declarative http client should use the provided path separator assertFileContains(outputPath + "/src/main/java/org/openapitools/api/PetApi.java", "@Client(\"${openapi-micronaut-client.base-path}\")"); } + + @Test + public void generateOperationOnlyForFirstTag_isFalse() { + JavaMicronautClientCodegen codegen = new JavaMicronautClientCodegen(); + + Assertions.assertThat(codegen).hasFieldOrPropertyWithValue("generateOperationOnlyForFirstTag", false); + } + + @Test + public void generateSwaggerAnnotations_isFalseString() { + JavaMicronautClientCodegen codegen = new JavaMicronautClientCodegen(); + + Assertions.assertThat(codegen).hasFieldOrPropertyWithValue( + "generateSwaggerAnnotations", JavaMicronautAbstractCodegen.OPT_GENERATE_SWAGGER_ANNOTATIONS_FALSE + ); + } + + @Test + public void outputFolder_endsWithMicronautClient() { + JavaMicronautClientCodegen codegen = new JavaMicronautClientCodegen(); + + Assertions.assertThat(codegen.outputFolder()).endsWith("java-micronaut-client"); + } + + @Test + public void artifactId_isOpenapiMicronautClient() { + JavaMicronautClientCodegen codegen = new JavaMicronautClientCodegen(); + + Assertions.assertThat(codegen.getArtifactId()).isEqualTo("openapi-micronaut-client"); + } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/micronaut/MicronautServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/micronaut/MicronautServerCodegenTest.java index 4b1ad1db749c..ceadb542231d 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/micronaut/MicronautServerCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/micronaut/MicronautServerCodegenTest.java @@ -3,9 +3,12 @@ import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.servers.Server; +import org.assertj.core.api.Assertions; import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.TestUtils; +import org.openapitools.codegen.languages.JavaMicronautAbstractCodegen; +import org.openapitools.codegen.languages.JavaMicronautClientCodegen; import org.openapitools.codegen.languages.JavaMicronautServerCodegen; import org.testng.Assert; import org.testng.annotations.Test; @@ -341,4 +344,34 @@ public void doRepeatOperationForAllTags() { assertFileContains(controllerPath + "SearchController.java", "authorSearchGet", "bookSearchGet"); } + + @Test + public void generateOperationOnlyForFirstTag_isTrue() { + JavaMicronautServerCodegen codegen = new JavaMicronautServerCodegen(); + + Assertions.assertThat(codegen).hasFieldOrPropertyWithValue("generateOperationOnlyForFirstTag", true); + } + + @Test + public void generateSwaggerAnnotations_isSwagger2() { + JavaMicronautServerCodegen codegen = new JavaMicronautServerCodegen(); + + Assertions.assertThat(codegen).hasFieldOrPropertyWithValue( + "generateSwaggerAnnotations", JavaMicronautAbstractCodegen.OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2 + ); + } + + @Test + public void outputFolder_endsWithMicronaut() { + JavaMicronautServerCodegen codegen = new JavaMicronautServerCodegen(); + + Assertions.assertThat(codegen.outputFolder()).endsWith("java-micronaut"); + } + + @Test + public void artifactId_isOpenapiMicronaut() { + JavaMicronautServerCodegen codegen = new JavaMicronautServerCodegen(); + + Assertions.assertThat(codegen.getArtifactId()).isEqualTo("openapi-micronaut"); + } } From 148ac85d91ba066d6126f855fa768d9fdd52703d Mon Sep 17 00:00:00 2001 From: Philzen Date: Wed, 29 May 2024 14:47:45 +0200 Subject: [PATCH 11/13] Move implementation specific behavior into implementing class --- .../codegen/languages/JavaMicronautAbstractCodegen.java | 7 ------- .../codegen/languages/JavaMicronautClientCodegen.java | 4 ++++ .../codegen/languages/JavaMicronautServerCodegen.java | 4 ++++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautAbstractCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautAbstractCodegen.java index e169a653e8d8..08857d59624a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautAbstractCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautAbstractCodegen.java @@ -89,13 +89,9 @@ public JavaMicronautAbstractCodegen() { visitable = false; buildTool = OPT_BUILD_ALL; testTool = OPT_TEST_JUNIT; - outputFolder = this instanceof JavaMicronautClientCodegen ? - "generated-code/java-micronaut-client" : "generated-code/java-micronaut"; apiPackage = "org.openapitools.api"; modelPackage = "org.openapitools.model"; invokerPackage = "org.openapitools"; - artifactId = this instanceof JavaMicronautClientCodegen ? - "openapi-micronaut-client" : "openapi-micronaut"; embeddedTemplateDir = templateDir = "java-micronaut"; apiDocPath = "docs/apis"; modelDocPath = "docs/models"; @@ -104,9 +100,6 @@ public JavaMicronautAbstractCodegen() { reactive = true; wrapInHttpResponse = false; appName = artifactId; - generateSwaggerAnnotations = this instanceof JavaMicronautClientCodegen ? - OPT_GENERATE_SWAGGER_ANNOTATIONS_FALSE : OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2; - generateOperationOnlyForFirstTag = this instanceof JavaMicronautServerCodegen; // Set implemented features for user information modifyFeatureSet(features -> features diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautClientCodegen.java index cdf8b8a1fcf1..4ec93e7d7920 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautClientCodegen.java @@ -32,7 +32,11 @@ public JavaMicronautClientCodegen() { super(); title = "OpenAPI Micronaut Client"; + artifactId = "openapi-micronaut-client"; configureAuthorization = false; + generateOperationOnlyForFirstTag = false; + generateSwaggerAnnotations = OPT_GENERATE_SWAGGER_ANNOTATIONS_FALSE; + outputFolder = "generated-code/java-micronaut-client"; generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata) .stability(Stability.BETA) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautServerCodegen.java index 7ff2fb2a1f35..d917a6bf061f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaMicronautServerCodegen.java @@ -46,6 +46,10 @@ public JavaMicronautServerCodegen() { title = "OpenAPI Micronaut Server"; apiPackage = "org.openapitools.api"; apiDocPath = "docs/controllers"; + artifactId = "openapi-micronaut"; + generateOperationOnlyForFirstTag = true; + generateSwaggerAnnotations = OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2; + outputFolder = "generated-code/java-micronaut"; generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata) .stability(Stability.BETA) From fac1fa3233ca4cff403164730d4d34ab9ab606fb Mon Sep 17 00:00:00 2001 From: Philzen Date: Wed, 29 May 2024 09:25:19 +0200 Subject: [PATCH 12/13] Add test for form parameter handling based on requestType --- .../codegen/DefaultCodegenTest.java | 58 ++++++++++++++- .../languages/RustAxumServerCodegenTest.java | 71 +++++++++++++++++++ 2 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/RustAxumServerCodegenTest.java diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index 6d7795095c16..ff7f04fd50a8 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -17,7 +17,6 @@ package org.openapitools.codegen; - import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.spi.ILoggingEvent; @@ -4943,7 +4942,13 @@ public static class fromParameter { DefaultCodegen codegen = new DefaultCodegen(); @BeforeTest void setOpenAPI() { - codegen.setOpenAPI(new OpenAPI().components(new Components().addSchemas("SampleRequestInput", new ObjectSchema().addProperty("FormProp1", new StringSchema())))); + codegen.setOpenAPI(new OpenAPI().components(new Components().addSchemas( + "SampleRequestInput", + new ObjectSchema().addProperty( + "FormProp1", + new StringSchema() + ) + ))); } @Test public void resolvesReferencedSchema() { @@ -4958,11 +4963,58 @@ public static class fromParameter { .returns("Object", CodegenProperty::getDataType) .returns(null, CodegenProperty::getRef) .returns(true, CodegenProperty::getHasVars) - + .extracting(CodegenProperty::getVars).asList().hasSize(1) .first(type(CodegenProperty.class)) .returns("FormProp1", CodegenProperty::getName) .returns("String", CodegenProperty::getDataType); } } + + @SuppressWarnings("NewClassNamingConvention") + public static class fromOperation { + + DefaultCodegen codegen = new DefaultCodegen(); + + @BeforeTest void setOpenAPI() { + codegen.setOpenAPI(new OpenAPI().components(new Components().addSchemas("SampleRequestInput", new ObjectSchema().addProperty("FormProp1", new StringSchema())))); + } + + + @Test public void addsFormParametersFromRequestProperties_forFormContentType() { + var operation = new Operation() + .parameters(List.of()) + .operationId("foobar") + .requestBody(new RequestBody().content(new Content().addMediaType( + "application/x-www-form-urlencoded", + new MediaType().schema(new Schema<>().$ref("SampleRequestInput")) + ))); + + CodegenOperation result = codegen.fromOperation("/", "GET", operation, List.of()); + + assertThat(result.bodyParams).isEmpty(); + assertThat(result.formParams).hasSize(1).first() + .hasFieldOrPropertyWithValue("baseName", "FormProp1") + .hasFieldOrPropertyWithValue("dataType", "String") + .hasFieldOrPropertyWithValue("paramName", "formProp1"); + } + + @Test public void doesNotAddFormParametersFromRequestProperties_forJsonContentType() { + var operation = new Operation() + .parameters(List.of()) + .operationId("foobar") + .requestBody(new RequestBody().content(new Content().addMediaType( + "application/json", + new MediaType().schema(new Schema<>().$ref("SampleRequestInput")) + ))); + + CodegenOperation result = codegen.fromOperation("", "GET", operation, List.of()); + + assertThat(result.formParams).isEmpty(); + assertThat(result.bodyParams).hasSize(1).first() + .hasFieldOrPropertyWithValue("baseName", "SampleRequestInput") + .hasFieldOrPropertyWithValue("dataType", "SampleRequestInput") + .hasFieldOrPropertyWithValue("paramName", "sampleRequestInput"); + } + } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/RustAxumServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/RustAxumServerCodegenTest.java new file mode 100644 index 000000000000..a883d867e404 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/RustAxumServerCodegenTest.java @@ -0,0 +1,71 @@ +package org.openapitools.codegen.languages; + +import io.swagger.v3.oas.models.Components; +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.oas.models.parameters.RequestBody; +import org.assertj.core.api.Assertions; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.GeneratorLanguage; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RustAxumServerCodegenTest { + + @Test public void generatorLanguageIsRust() { + Assertions.assertThat(new RustAxumServerCodegen().generatorLanguage()) + .isSameAs(GeneratorLanguage.RUST); + } + + @SuppressWarnings("NewClassNamingConvention") + public static class fromOperation { + + RustAxumServerCodegen codegen = new RustAxumServerCodegen(); + + @BeforeTest void setOpenAPI() { + codegen.setOpenAPI(new OpenAPI().components(new Components().addSchemas("SampleRequestInput", new ObjectSchema().addProperty("FormProp1", new StringSchema())))); + } + + + @Test public void addsFormParametersFromRequestProperties_forFormContentType() { + var operation = new Operation() + .parameters(List.of()) + .operationId("foobar") + .requestBody(new RequestBody().content(new Content().addMediaType( + "application/x-www-form-urlencoded", + new MediaType().schema(new Schema<>().$ref("SampleRequestInput")) + ))); + + CodegenOperation result = codegen.fromOperation("/", "GET", operation, List.of()); + + assertThat(result.formParams).isEmpty(); + assertThat(result.bodyParams).hasSize(1).first() + .hasFieldOrPropertyWithValue("baseName", "SampleRequestInput") + .hasFieldOrPropertyWithValue("dataType", "models::SampleRequestInput") + .hasFieldOrPropertyWithValue("paramName", "sample_request_input"); + } + + @Test public void doesNotAddFormParametersFromRequestProperties_forJsonContentType() { + var operation = new Operation() + .parameters(List.of()) + .operationId("foobar") + .requestBody(new RequestBody().content(new Content().addMediaType( + "application/json", + new MediaType().schema(new Schema<>().$ref("SampleRequestInput")) + ))); + + CodegenOperation result = codegen.fromOperation("", "GET", operation, List.of()); + + assertThat(result.formParams).isEmpty(); + assertThat(result.bodyParams).hasSize(1).first() + .hasFieldOrPropertyWithValue("baseName", "SampleRequestInput") + .hasFieldOrPropertyWithValue("dataType", "models::SampleRequestInput") + .hasFieldOrPropertyWithValue("paramName", "sample_request_input"); + } + } +} \ No newline at end of file From 22b3720379e0382f7e46385c3f97a1543acc523b Mon Sep 17 00:00:00 2001 From: Philzen Date: Wed, 29 May 2024 12:16:31 +0200 Subject: [PATCH 13/13] Move implementation specific behavior into implementing class --- .../openapitools/codegen/DefaultCodegen.java | 18 ++++++++++++------ .../languages/RustAxumServerCodegen.java | 5 +++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index cdb8242183c0..a34904331a3b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -4746,9 +4746,7 @@ public CodegenOperation fromOperation(String path, if (contentType != null) { contentType = contentType.toLowerCase(Locale.ROOT); } - if (contentType != null && - ((!(this instanceof RustAxumServerCodegen) && contentType.startsWith("application/x-www-form-urlencoded")) || - contentType.startsWith("multipart"))) { + if (isFormMimeType(contentType)) { // process form parameters formParams = fromRequestBodyToFormParameters(requestBody, imports); op.isMultipart = contentType.startsWith("multipart"); @@ -7007,9 +7005,7 @@ public boolean hasFormParameter(Operation operation) { } for (String consume : consumesInfo) { - if (consume != null && - (consume.toLowerCase(Locale.ROOT).startsWith("application/x-www-form-urlencoded") || - consume.toLowerCase(Locale.ROOT).startsWith("multipart"))) { + if (isFormMimeType(consume)) { return true; } } @@ -8339,6 +8335,16 @@ public int hashCode() { } } + protected boolean isFormMimeType(String mime) { + if (mime == null) { + return false; + } + + mime = mime.toLowerCase(Locale.ROOT); + return mime.startsWith("application/x-www-form-urlencoded") + || mime.startsWith("multipart"); // ← maybe multipart/form-data would be more accurate? + } + /** * Check if the given MIME is a JSON MIME. * JSON MIME examples: diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustAxumServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustAxumServerCodegen.java index 4b36b305c097..5a94b29c2cff 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustAxumServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustAxumServerCodegen.java @@ -414,6 +414,11 @@ boolean isMimetypePlain(String mimetype) { isMimetypeMultipartRelated(mimetype)); } + @Override protected boolean isFormMimeType(String mime) { + return mime != null + && mime.toLowerCase(Locale.ROOT).startsWith("multipart"); // ← maybe multipart/form-data would be more accurate? + } + @Override public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List servers) { CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers);