Issue-19220: processing schema name is added to the list with names checked at recursing processing, so it prevent to endless recursive execution (#19221)

This commit is contained in:
Pavel Miller 2024-08-07 12:48:14 +03:00 committed by GitHub
parent 539aab05a7
commit 908eddea0b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 263 additions and 2 deletions

View File

@ -466,6 +466,7 @@ public class DefaultGenerator implements Generator {
// process models only
for (String name : modelKeys) {
processedModels.add(name);
try {
//don't generate models that have an import mapping
if (config.schemaMapping().containsKey(name)) {
@ -604,7 +605,7 @@ public class DefaultGenerator implements Generator {
} else if (variable.getComplexType() != null && variable.getComposedSchemas() == null) {
String ref = variable.getHasItems() ? variable.getItems().getRef() : variable.getRef();
final String key = calculateModelKey(variable.getComplexType(), ref);
if (allSchemas.containsKey(key)) {
if (!processedModels.contains(key) && allSchemas.containsKey(key)) {
generateModels(files, allModels, unusedModels, aliasModels, processedModels, () -> Set.of(key));
} else {
LOGGER.info("Type " + variable.getComplexType()+" of variable " + variable.getName() + " could not be resolve because it is not declared as a model.");

View File

@ -789,10 +789,18 @@ public class DefaultGeneratorTest {
return generator;
}
private ClientOptInput createOptInputIssue19220(Path target) {
return createOptInputIssue("19220", target);
}
private ClientOptInput createOptInputIssue18444(Path target) {
return createOptInputIssue("18444", target);
}
private ClientOptInput createOptInputIssue(String issueNumber, Path target) {
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("spring")
.setInputSpec("src/test/resources/bugs/issue_18444.json")
.setInputSpec("src/test/resources/bugs/issue_"+issueNumber+".json")
.setOutputDir(target.toAbsolutePath().toString());
return configurator.toClientOptInput();
}
@ -907,4 +915,59 @@ public class DefaultGeneratorTest {
}
}
@Test
public void testGenerateRecursiveDependentModelsIssue19220() throws IOException {
Path target = Files.createTempDirectory("test");
File output = target.toFile();
String oldModelsProp = GlobalSettings.getProperty("models");
try {
DefaultGenerator generator = generatorGenerateRecursiveDependentModelsBackwardCompatibility("true");
GlobalSettings.setProperty("models", "RQ1,RS1");
ClientOptInput clientOptInput = createOptInputIssue19220(target);
List<File> files = generator.opts(clientOptInput ).generate();
Assert.assertEquals(files.size(), 21);
// Check expected generated files
// api sanity check
String apiJavaFileName = "src/main/java/org/openapitools/api/ApiApi.java";
TestUtils.ensureContainsFile(files, output, apiJavaFileName);
Assert.assertTrue(new File(output, apiJavaFileName).exists());
// model sanity check
String rq1FileName = "src/main/java/org/openapitools/model/RQ1.java";
TestUtils.ensureContainsFile(files, output, rq1FileName);
Assert.assertTrue(new File(output, rq1FileName).exists());
String rs1FileName = "src/main/java/org/openapitools/model/RS1.java";
TestUtils.ensureContainsFile(files, output, rs1FileName );
Assert.assertTrue(new File(output, rs1FileName).exists());
// Check generated cause RQ1 and RS1 dependents of FT1,FT2,FT3 files
String ft1FileName = "src/main/java/org/openapitools/model/FT1.java";
TestUtils.ensureContainsFile(files, output, ft1FileName);
Assert.assertTrue(new File(output, ft1FileName).exists());
String ft2FileName = "src/main/java/org/openapitools/model/FT2.java";
TestUtils.ensureContainsFile(files, output, ft2FileName);
Assert.assertTrue(new File(output, ft2FileName).exists());
String ft3FileName = "src/main/java/org/openapitools/model/FT3.java";
TestUtils.ensureContainsFile(files, output, ft3FileName);
Assert.assertTrue(new File(output, ft3FileName).exists());
String bttFileName = "src/main/java/org/openapitools/model/BTT.java";
TestUtils.ensureContainsFile(files, output, bttFileName);
Assert.assertTrue(new File(output, bttFileName).exists());
} finally {
output.deleteOnExit();
if (oldModelsProp != null) {
GlobalSettings.setProperty("models", oldModelsProp);
} else {
GlobalSettings.clearProperty("models");
}
}
}
}

View File

@ -0,0 +1,197 @@
{
"openapi": "3.0.1",
"info": {
"title": "OpenAPI definition",
"version": "v0"
},
"servers": [
{
"url": "http://localhost/service",
"description": "Generated server url"
}
],
"paths": {
"/api/v1/subservice/m1": {
"post": {
"tags": [
"subservice"
],
"summary": "subservice",
"operationId": "m1",
"parameters": [
{
"name": "n1",
"in": "header",
"description": "n1 description",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RQ1"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RS1"
}
}
}
},
"403": {
"description": "Forbidden"
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BadRequestError"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"B_TT": {
"discriminator": {
"propertyName": "otype"
},
"required": [
"ident",
"otype"
],
"type": "object",
"properties": {
"ident": {
"type": "integer",
"format": "int32"
},
"otype": {
"type": "object"
}
}
},
"BadRequestError": {
"allOf": [
{ "$ref": "#/components/schemas/B_TT" },
{
"type": "object",
"properties": {
"status": {
"type": "integer",
"format": "int32",
"default": 400
},
"error": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
]
},
"RQ1": {
"allOf": [
{ "$ref": "#/components/schemas/B_TT" },
{ "type": "object",
"properties": {
"f1": {
"$ref": "#/components/schemas/FT1"
},
"f2": {
"$ref": "#/components/schemas/FT2"
}
}
}
]
},
"FT1": {
"required": [
"code"
],
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"ft" : {
"$ref": "#/components/schemas/FT1"
}
}
},
"FT2": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"readOnly": true
},
"date": {
"type": "string",
"format": "date-time",
"readOnly": true
}
}
},
"RS1": {
"type": "object",
"properties": {
"f1": {
"type": "array",
"items": {
"$ref": "#/components/schemas/FT3"
}
},
"f2": {
"type": "integer",
"format": "int32"
}
}
},
"FT3": {
"required": [
"f1",
"f2"
],
"type": "object",
"properties": {
"f2": {
"type": "string",
"enum": [
"E1",
"E2"
]
},
"f1": {
"type": "integer",
"format": "int64"
}
}
}
}
}
}