Skip to content

Commit 22ef4b9

Browse files
Adjust array TypeDeclaration parsing order to fix deep inline aliases
1 parent 90001d4 commit 22ef4b9

File tree

9 files changed

+302
-59
lines changed

9 files changed

+302
-59
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6024,10 +6024,8 @@ protected Map<String, Schema> unaliasPropertySchema(Map<String, Schema> properti
60246024
if (properties != null) {
60256025
for (String key : properties.keySet()) {
60266026
properties.put(key, unaliasSchema(properties.get(key)));
6027-
60286027
}
60296028
}
6030-
60316029
return properties;
60326030
}
60336031

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import java.util.stream.Collectors;
4848

4949
import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER;
50+
import static org.openapitools.codegen.utils.ModelUtils.getSchemaItems;
5051
import static org.openapitools.codegen.utils.StringUtils.camelize;
5152
import static org.openapitools.codegen.utils.StringUtils.underscore;
5253

@@ -1543,33 +1544,28 @@ public String getSchemaType(Schema p) {
15431544
/**
15441545
* Provides C# strongly typed declaration for simple arrays of some type and arrays of arrays of some type.
15451546
*
1546-
* @param arr The input array property
1547+
* @param items The input array property
15471548
* @return The type declaration when the type is an array of arrays.
15481549
*/
1549-
private String getArrayTypeDeclaration(Schema arr) {
1550-
// TODO: collection type here should be fully qualified namespace to avoid model conflicts
1551-
// This supports arrays of arrays.
1552-
String arrayType = typeMapping.get("array");
1553-
StringBuilder instantiationType = new StringBuilder(arrayType);
1554-
Schema<?> items = ModelUtils.getSchemaItems(arr);
1555-
String nestedType = getTypeDeclaration(items);
1556-
// TODO: We may want to differentiate here between generics and primitive arrays.
1557-
instantiationType.append("<").append(nestedType).append(">");
1558-
return instantiationType.toString();
1550+
private String getTypeDeclarationForArray(Schema<?> items) {
1551+
return getTypeDeclaration(items);
15591552
}
15601553

15611554
@Override
15621555
public String toInstantiationType(Schema p) {
15631556
if (ModelUtils.isArraySchema(p)) {
1564-
return getArrayTypeDeclaration(p);
1557+
return getTypeDeclarationForArray(p);
15651558
}
15661559
return super.toInstantiationType(p);
15671560
}
15681561

15691562
@Override
15701563
public String getTypeDeclaration(Schema p) {
1571-
if (ModelUtils.isArraySchema(p)) {
1572-
return getArrayTypeDeclaration(p);
1564+
Schema<?> schema = unaliasSchema(p);
1565+
Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema;
1566+
if (ModelUtils.isArraySchema(target)) {
1567+
Schema<?> items = getSchemaItems(schema);
1568+
return getSchemaType(target) + "<" + getTypeDeclarationForArray(items) + ">";
15731569
} else if (ModelUtils.isMapSchema(p)) {
15741570
// Should we also support maps of maps?
15751571
Schema<?> inner = ModelUtils.getAdditionalProperties(p);

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1748,7 +1748,7 @@ public void postProcess() {
17481748

17491749
@Override
17501750
protected void updateModelForObject(CodegenModel m, Schema schema) {
1751-
/**
1751+
/*
17521752
* we have a custom version of this function so we only set isMap to true if
17531753
* ModelUtils.isMapSchema
17541754
* In other generators, isMap is true for all type object schemas

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpReducedClientCodegen.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,7 @@ protected void configureAdditionalPropertiesForFrameworks(final Map<String, Obje
10581058
@Override
10591059
public String toInstantiationType(Schema schema) {
10601060
if (ModelUtils.isMapSchema(schema)) {
1061-
Schema additionalProperties = ModelUtils.getAdditionalProperties(schema);
1061+
Schema<?> additionalProperties = ModelUtils.getAdditionalProperties(schema);
10621062
String inner = getSchemaType(additionalProperties);
10631063
if (ModelUtils.isMapSchema(additionalProperties)) {
10641064
inner = toInstantiationType(additionalProperties);

modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,15 +1799,6 @@ public void testAllOfParent() {
17991799
assertEquals(getRequiredVars(personForUpdateModel), Collections.emptyList());
18001800
}
18011801

1802-
private List<String> getRequiredVars(CodegenModel model) {
1803-
return getNames(model.getRequiredVars());
1804-
}
1805-
1806-
private List<String> getNames(List<CodegenProperty> props) {
1807-
if (props == null) return null;
1808-
return props.stream().map(v -> v.name).collect(Collectors.toList());
1809-
}
1810-
18111802
@Test
18121803
public void testCallbacks() {
18131804
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/callbacks.yaml");
@@ -5006,4 +4997,13 @@ public void testSingleRequestParameter_hasSingleParamTrue() {
50064997
// When & Then
50074998
assertThat(codegenOperation.getHasSingleParam()).isTrue();
50084999
}
5000+
5001+
private List<String> getRequiredVars(CodegenModel model) {
5002+
return getNames(model.getRequiredVars());
5003+
}
5004+
5005+
private List<String> getNames(List<CodegenProperty> props) {
5006+
if (props == null) return null;
5007+
return props.stream().map(v -> v.name).collect(Collectors.toList());
5008+
}
50095009
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -775,36 +775,6 @@ public void testRecursionBug4650() {
775775
// all fine, we have passed
776776
}
777777

778-
779-
private DefaultGenerator generatorGenerateRecursiveDependentModelsBackwardCompatibility(String recursively) throws IOException {
780-
DefaultGenerator generator = new DefaultGenerator(false);
781-
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
782-
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "true");
783-
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
784-
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
785-
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "true");
786-
generator.setGeneratorPropertyDefault(CodegenConstants.API_DOCS, "false");
787-
generator.setGeneratorPropertyDefault(CodegenConstants.API_TESTS, "false");
788-
generator.setGeneratorPropertyDefault(CodegenConstants.GENERATE_RECURSIVE_DEPENDENT_MODELS, recursively);
789-
return generator;
790-
}
791-
792-
private ClientOptInput createOptInputIssue19220(Path target) {
793-
return createOptInputIssue("19220", target);
794-
}
795-
796-
private ClientOptInput createOptInputIssue18444(Path target) {
797-
return createOptInputIssue("18444", target);
798-
}
799-
800-
private ClientOptInput createOptInputIssue(String issueNumber, Path target) {
801-
final CodegenConfigurator configurator = new CodegenConfigurator()
802-
.setGeneratorName("spring")
803-
.setInputSpec("src/test/resources/bugs/issue_" + issueNumber + ".json")
804-
.setOutputDir(target.toAbsolutePath().toString());
805-
return configurator.toClientOptInput();
806-
}
807-
808778
@Test
809779
public void testGenerateRecursiveDependentModelsBackwardCompatibilityIssue18444() throws IOException {
810780
Path target = Files.createTempDirectory("test");
@@ -1041,6 +1011,34 @@ public void testGenerateMultiLinePropertiesIssue19628() throws IOException {
10411011
GlobalSettings.reset();
10421012
output.deleteOnExit();
10431013
}
1014+
}
1015+
1016+
private DefaultGenerator generatorGenerateRecursiveDependentModelsBackwardCompatibility(String recursively) throws IOException {
1017+
DefaultGenerator generator = new DefaultGenerator(false);
1018+
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
1019+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "true");
1020+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
1021+
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
1022+
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "true");
1023+
generator.setGeneratorPropertyDefault(CodegenConstants.API_DOCS, "false");
1024+
generator.setGeneratorPropertyDefault(CodegenConstants.API_TESTS, "false");
1025+
generator.setGeneratorPropertyDefault(CodegenConstants.GENERATE_RECURSIVE_DEPENDENT_MODELS, recursively);
1026+
return generator;
1027+
}
10441028

1029+
private ClientOptInput createOptInputIssue19220(Path target) {
1030+
return createOptInputIssue("19220", target);
1031+
}
1032+
1033+
private ClientOptInput createOptInputIssue18444(Path target) {
1034+
return createOptInputIssue("18444", target);
1035+
}
1036+
1037+
private ClientOptInput createOptInputIssue(String issueNumber, Path target) {
1038+
final CodegenConfigurator configurator = new CodegenConfigurator()
1039+
.setGeneratorName("spring")
1040+
.setInputSpec("src/test/resources/bugs/issue_" + issueNumber + ".json")
1041+
.setOutputDir(target.toAbsolutePath().toString());
1042+
return configurator.toClientOptInput();
10451043
}
10461044
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/csharpnetcore/CSharpClientCodegenTest.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,28 @@
2020
import io.swagger.v3.oas.models.media.Schema;
2121
import org.openapitools.codegen.*;
2222
import org.openapitools.codegen.languages.CSharpClientCodegen;
23+
import org.openapitools.codegen.utils.ModelUtils;
2324
import org.testng.Assert;
2425
import org.testng.annotations.Test;
2526

2627
import java.io.File;
2728
import java.io.IOException;
2829
import java.nio.file.Files;
2930
import java.nio.file.Paths;
31+
import java.util.List;
3032
import java.util.Map;
3133
import java.util.function.Function;
3234
import java.util.stream.Collectors;
3335

36+
import static org.assertj.core.api.Assertions.assertThat;
3437
import static org.junit.jupiter.api.Assertions.assertNotNull;
3538
import static org.openapitools.codegen.TestUtils.assertFileContains;
3639
import static org.openapitools.codegen.TestUtils.assertFileNotContains;
3740

3841
public class CSharpClientCodegenTest {
3942

4043
@Test
41-
public void testToEnumVarName() throws Exception {
44+
public void testToEnumVarName() {
4245
final CSharpClientCodegen codegen = new CSharpClientCodegen();
4346
codegen.setLibrary("restsharp");
4447
codegen.processOpts();
@@ -211,4 +214,50 @@ public void testAnyOfDiscriminatorCreatesCompilableCode() throws IOException {
211214
// Should not contain this as the constructor will have two parameters instead of one
212215
assertFileNotContains(file.toPath(), "return new FruitAnyOfDisc(appleAnyOfDisc);");
213216
}
217+
218+
@Test
219+
public void testDoubleDepthArrayAliasCSharp() {
220+
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/bugs/issue_21585.yaml");
221+
String schemaName = "GeoJSON_MultiLineString";
222+
String modelName = "GeoJSONMultiLineString";
223+
Schema schema = ModelUtils.getSchema(openAPI, schemaName);
224+
225+
CSharpClientCodegen codegen = new CSharpClientCodegen();
226+
codegen.setOpenAPI(openAPI);
227+
CodegenModel concreteModel = codegen.fromModel(modelName, schema);
228+
assertThat(getNames(concreteModel.vars)).isEqualTo(List.of("Type", "Coordinates", "Bbox"));
229+
assertThat(concreteModel.vars.get(1).getDataType()).isEqualTo("List<List<List<BigDecimal>>>");
230+
}
231+
232+
@Test
233+
public void testDeepArrayAlias() throws IOException {
234+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
235+
output.deleteOnExit();
236+
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/bugs/issue_21585.yaml");
237+
final DefaultGenerator defaultGenerator = new DefaultGenerator();
238+
final ClientOptInput clientOptInput = new ClientOptInput();
239+
clientOptInput.openAPI(openAPI);
240+
CSharpClientCodegen cSharpClientCodegen = new CSharpClientCodegen();
241+
cSharpClientCodegen.setLibrary("httpclient");
242+
cSharpClientCodegen.setOutputDir(output.getAbsolutePath());
243+
cSharpClientCodegen.setAutosetConstants(true);
244+
clientOptInput.config(cSharpClientCodegen);
245+
defaultGenerator.opts(clientOptInput);
246+
247+
Map<String, File> files = defaultGenerator.generate().stream()
248+
.collect(Collectors.toMap(File::getPath, Function.identity()));
249+
250+
String modelName = "GeoJSONMultiLineString";
251+
File file = files.get(Paths
252+
.get(output.getAbsolutePath(), "src", "Org.OpenAPITools", "Model", modelName + ".cs")
253+
.toString()
254+
);
255+
assertNotNull(file, "Could not find file for model: " + modelName);
256+
assertFileContains(file.toPath(), "public List<List<List<decimal>>> Coordinates { get; set; }");
257+
}
258+
259+
private List<String> getNames(List<CodegenProperty> props) {
260+
if (props == null) return null;
261+
return props.stream().map(v -> v.name).collect(Collectors.toList());
262+
}
214263
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/csharpnetcore/CSharpModelTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ public void nullablePropertyWithNullableReferenceTypesTest() {
398398

399399
final CodegenProperty property2 = cm.vars.get(1);
400400
Assert.assertEquals(property2.baseName, "urls");
401-
Assert.assertEquals(property2.dataType, "List<string>");
401+
Assert.assertEquals(property2.dataType, "List?<string>");
402402
Assert.assertEquals(property2.name, "Urls");
403403
Assert.assertNull(property2.defaultValue);
404404
Assert.assertEquals(property2.baseType, "List?");

0 commit comments

Comments
 (0)