forked from loafle/openapi-generator-original
Bugfix swift5 code generation 2966 (#7301)
* Bugfix StackOverflow Crash in Swift5 Code Generation (#2966) * Bugfix StackOverflow Crash in Swift5 Code Generation (#2966) * Bugfix StackOverflow Crash in Swift5 Code Generation (#2966)
This commit is contained in:
@@ -1003,15 +1003,15 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
|
||||
for (CodegenOperation operation : operations) {
|
||||
for (CodegenParameter cp : operation.allParams) {
|
||||
cp.vendorExtensions.put("x-swift-example", constructExampleCode(cp, modelMaps));
|
||||
cp.vendorExtensions.put("x-swift-example", constructExampleCode(cp, modelMaps, new ExampleCodeGenerationContext()));
|
||||
}
|
||||
}
|
||||
return objs;
|
||||
}
|
||||
|
||||
public String constructExampleCode(CodegenParameter codegenParameter, HashMap<String, CodegenModel> modelMaps) {
|
||||
public String constructExampleCode(CodegenParameter codegenParameter, HashMap<String, CodegenModel> modelMaps, ExampleCodeGenerationContext context) {
|
||||
if (codegenParameter.isListContainer) { // array
|
||||
return "[" + constructExampleCode(codegenParameter.items, modelMaps) + "]";
|
||||
return "[" + constructExampleCode(codegenParameter.items, modelMaps, context) + "]";
|
||||
} else if (codegenParameter.isMapContainer) { // TODO: map, file type
|
||||
return "\"TODO\"";
|
||||
} else if (languageSpecificPrimitives.contains(codegenParameter.dataType)) { // primitive type
|
||||
@@ -1041,7 +1041,7 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
} else { // model
|
||||
// look up the model
|
||||
if (modelMaps.containsKey(codegenParameter.dataType)) {
|
||||
return constructExampleCode(modelMaps.get(codegenParameter.dataType), modelMaps);
|
||||
return constructExampleCode(modelMaps.get(codegenParameter.dataType), modelMaps, context);
|
||||
} else {
|
||||
//LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenParameter.dataType);
|
||||
return "TODO";
|
||||
@@ -1049,9 +1049,9 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
}
|
||||
}
|
||||
|
||||
public String constructExampleCode(CodegenProperty codegenProperty, HashMap<String, CodegenModel> modelMaps) {
|
||||
private String constructExampleCode(CodegenProperty codegenProperty, HashMap<String, CodegenModel> modelMaps, ExampleCodeGenerationContext context) {
|
||||
if (codegenProperty.isListContainer) { // array
|
||||
return "[" + constructExampleCode(codegenProperty.items, modelMaps) + "]";
|
||||
return "[" + constructExampleCode(codegenProperty.items, modelMaps, context) + "]";
|
||||
} else if (codegenProperty.isMapContainer) { // TODO: map, file type
|
||||
return "\"TODO\"";
|
||||
} else if (languageSpecificPrimitives.contains(codegenProperty.dataType)) { // primitive type
|
||||
@@ -1081,7 +1081,7 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
} else {
|
||||
// look up the model
|
||||
if (modelMaps.containsKey(codegenProperty.dataType)) {
|
||||
return constructExampleCode(modelMaps.get(codegenProperty.dataType), modelMaps);
|
||||
return constructExampleCode(modelMaps.get(codegenProperty.dataType), modelMaps, context);
|
||||
} else {
|
||||
//LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenProperty.dataType);
|
||||
return "\"TODO\"";
|
||||
@@ -1089,15 +1089,51 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
}
|
||||
}
|
||||
|
||||
public String constructExampleCode(CodegenModel codegenModel, HashMap<String, CodegenModel> modelMaps) {
|
||||
String example;
|
||||
example = codegenModel.name + "(";
|
||||
List<String> propertyExamples = new ArrayList<>();
|
||||
for (CodegenProperty codegenProperty : codegenModel.vars) {
|
||||
propertyExamples.add(codegenProperty.name + ": " + constructExampleCode(codegenProperty, modelMaps));
|
||||
private String constructExampleCode(CodegenModel codegenModel, HashMap<String, CodegenModel> modelMaps, ExampleCodeGenerationContext context) {
|
||||
if (context.isTypeVisted(codegenModel.dataType)) {
|
||||
String exampleCode = context.getExampleCode(codegenModel.dataType);
|
||||
if (exampleCode != null) {
|
||||
// Reuse already generated exampleCode
|
||||
return exampleCode;
|
||||
} else {
|
||||
// Visited but no Example Code. Circuit Breaker --> No StackOverflow
|
||||
return "{...}";
|
||||
}
|
||||
} else {
|
||||
context.visitType(codegenModel.dataType);
|
||||
String example = codegenModel.name + "(";
|
||||
List<String> propertyExamples = new ArrayList<>();
|
||||
for (CodegenProperty codegenProperty : codegenModel.vars) {
|
||||
String propertyExample = constructExampleCode(codegenProperty, modelMaps, context);
|
||||
propertyExamples.add(codegenProperty.name + ": " + propertyExample);
|
||||
}
|
||||
example += StringUtils.join(propertyExamples, ", ");
|
||||
example += ")";
|
||||
|
||||
context.setExampleCode(codegenModel.dataType, example);
|
||||
return example;
|
||||
}
|
||||
example += StringUtils.join(propertyExamples, ", ");
|
||||
example += ")";
|
||||
return example;
|
||||
}
|
||||
|
||||
private static class ExampleCodeGenerationContext {
|
||||
|
||||
private Map<String, String> modelExampleCode = new HashMap<>();
|
||||
|
||||
public boolean isTypeVisted(String type) {
|
||||
return modelExampleCode.containsKey(type);
|
||||
}
|
||||
|
||||
public void visitType(String type) {
|
||||
modelExampleCode.put(type, null);
|
||||
}
|
||||
|
||||
public void setExampleCode(String type, String code) {
|
||||
modelExampleCode.put(type, code);
|
||||
}
|
||||
|
||||
public String getExampleCode(String type) {
|
||||
return modelExampleCode.get(type);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,21 @@ import io.swagger.v3.oas.models.Operation;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.DefaultCodegen;
|
||||
import org.openapitools.codegen.TestUtils;
|
||||
import org.openapitools.codegen.*;
|
||||
import org.openapitools.codegen.config.CodegenConfigurator;
|
||||
import org.openapitools.codegen.languages.Swift5ClientCodegen;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class Swift5ClientCodegenTest {
|
||||
|
||||
@@ -118,6 +129,38 @@ public class Swift5ClientCodegenTest {
|
||||
Assert.assertEquals(op.bodyParam.dataType, "Date");
|
||||
}
|
||||
|
||||
@Test(description = "Bug example code generation", enabled = true)
|
||||
public void crashSwift5ExampleCodeGenerationStackOverflowTest() throws IOException {
|
||||
//final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/bugs/Swift5CodeGenerationStackOverflow#2966.yaml");
|
||||
Path target = Files.createTempDirectory("test");
|
||||
File output = target.toFile();
|
||||
try {
|
||||
final CodegenConfigurator configurator = new CodegenConfigurator()
|
||||
.setGeneratorName("swift5")
|
||||
.setValidateSpec(false)
|
||||
.setInputSpec("src/test/resources/bugs/Swift5CodeGenerationStackOverflow#2966.yaml")
|
||||
.setEnablePostProcessFile(true)
|
||||
.setOutputDir(target.toAbsolutePath().toString());
|
||||
|
||||
final ClientOptInput clientOptInput = configurator.toClientOptInput();
|
||||
DefaultGenerator generator = new DefaultGenerator(false);
|
||||
|
||||
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
|
||||
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "true");
|
||||
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "true");
|
||||
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
|
||||
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "true");
|
||||
generator.setGeneratorPropertyDefault(CodegenConstants.API_DOCS, "true");
|
||||
generator.setGeneratorPropertyDefault(CodegenConstants.ENABLE_POST_PROCESS_FILE, "true");
|
||||
|
||||
List<File> files = generator.opts(clientOptInput).generate();
|
||||
Assert.assertTrue(files.size() > 0, "No files generated");
|
||||
} finally {
|
||||
output.delete();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testDefaultPodAuthors() throws Exception {
|
||||
// Given
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
description: This spec is mainly for testing Petstore server
|
||||
version: 1.0.0
|
||||
title: OpenAPI Petstore
|
||||
license:
|
||||
name: Apache-2.0
|
||||
url: http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
tags:
|
||||
- name: pet
|
||||
description: Everything about your Pets
|
||||
paths:
|
||||
/pet:
|
||||
post:
|
||||
tags:
|
||||
- pet
|
||||
summary: Add a new pet to the store
|
||||
description: ""
|
||||
operationId: addPet
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Pet"
|
||||
description: Pet object that needs to be added to the store
|
||||
required: true
|
||||
responses:
|
||||
"400":
|
||||
description: Invalid input
|
||||
servers:
|
||||
- url: http://petstore.swagger.io:80/v2
|
||||
components:
|
||||
schemas:
|
||||
Pet:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
x-is-unique: true
|
||||
name:
|
||||
type: string
|
||||
example: doggie
|
||||
pets:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Pet"
|
||||
Reference in New Issue
Block a user