Skip to content

Commit fde8c77

Browse files
authored
[BUG] [C++][Pistache] cpp-pistache-server generating API include unde… (OpenAPITools#18553)
* [BUG] [C++][Pistache] cpp-pistache-server generating API include undefined "Object.h" (OpenAPITools#2769) Should handle Object.h, AnyType.h correctly. Set.h also tested. - #include Object.h removed and replaced by a typeMapping.put(object, nlohmann::json) like suggested in other issues - object had an invalid syntax: ':' instead of '::' in types with namespace - extra include of #include nlohmann/json.h removed when there's already #include <nlohmann/json.hpp> - nlohmann::json is excluded from model namespace Tested with custom petstore played, with suggested openapi specs coming from issues OpenAPITools#2769, OpenAPITools#10266, OpenAPITools#14234 ```bash rm -rf samples/server/petstore/cpp-pistache-everything/ && ./bin/generate-samples.sh ./bin/configs/cpp-pistache-server-cpp-pistache-everything.yaml && cd samples/server/petstore/cpp-pistache-everything/ && mkdir build && cd build && cmake .. && cmake --build . --parallel ``` * - Adding to samples/server/petstore cpp-pistache-everything * - .md and FILES missing
1 parent d3b156d commit fde8c77

43 files changed

Lines changed: 5331 additions & 33 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
generatorName: cpp-pistache-server
2+
outputDir: samples/server/petstore/cpp-pistache-everything
3+
inputSpec: modules/openapi-generator/src/test/resources/3_0/issues-anytype-object-set-petstore-everything.yaml
4+
templateDir: modules/openapi-generator/src/main/resources/cpp-pistache-server
5+
additionalProperties:
6+
useStructModel: "false"
7+
addExternalLibs: "true"

docs/generators/cpp-pistache-server.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
2828

2929
| Type/Alias | Imports |
3030
| ---------- | ------- |
31-
|Object|#include &quot;Object.h&quot;|
3231
|nlohmann::json|#include &lt;nlohmann/json.hpp&gt;|
3332
|std::map|#include &lt;map&gt;|
3433
|std::string|#include &lt;string&gt;|

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

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
package org.openapitools.codegen.languages;
1919

2020
import io.swagger.v3.oas.models.Operation;
21-
import io.swagger.v3.oas.models.media.ArraySchema;
2221
import io.swagger.v3.oas.models.media.Schema;
2322
import io.swagger.v3.oas.models.responses.ApiResponse;
2423
import io.swagger.v3.oas.models.servers.Server;
@@ -53,6 +52,27 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
5352
protected final String PREFIX = "";
5453
protected String helpersPackage = "";
5554

55+
/** OpenApi types that shouldn't have a namespace added with getTypeDeclaration() at generation time (for nlohmann::json) */
56+
private final Set<String> openAPITypesWithoutModelNamespace = new HashSet<>();
57+
58+
/** int32_t (for integer) */
59+
private static final String INT32_T = "int32_t";
60+
61+
/** int64_t (for long) */
62+
private static final String INT64_T = "int64_t";
63+
64+
/** nlohmann::json (for object, AnyType) */
65+
private static final String NLOHMANN_JSON = "nlohmann::json";
66+
67+
/** std:string (for date, DateTime, string, file, binary, UUID, URI, ByteArray) */
68+
private static final String STD_STRING = "std::string";
69+
70+
/** std:map (for map) */
71+
private static final String STD_MAP = "std::map";
72+
73+
/** std:vector (for array, set) */
74+
private static final String STD_VECTOR = "std::vector";
75+
5676
@Override
5777
public CodegenType getTag() {
5878
return CodegenType.SERVER;
@@ -117,33 +137,35 @@ public CppPistacheServerCodegen() {
117137
setupSupportingFiles();
118138

119139
languageSpecificPrimitives = new HashSet<>(
120-
Arrays.asList("int", "char", "bool", "long", "float", "double", "int32_t", "int64_t"));
140+
Arrays.asList("int", "char", "bool", "long", "float", "double", INT32_T, INT64_T));
121141

122142
typeMapping = new HashMap<>();
123-
typeMapping.put("date", "std::string");
124-
typeMapping.put("DateTime", "std::string");
125-
typeMapping.put("string", "std::string");
126-
typeMapping.put("integer", "int32_t");
127-
typeMapping.put("long", "int64_t");
143+
typeMapping.put("date", STD_STRING);
144+
typeMapping.put("DateTime", STD_STRING);
145+
typeMapping.put("string", STD_STRING);
146+
typeMapping.put("integer", INT32_T);
147+
typeMapping.put("long", INT64_T);
128148
typeMapping.put("boolean", "bool");
129-
typeMapping.put("array", "std::vector");
130-
typeMapping.put("map", "std::map");
131-
typeMapping.put("set", "std::vector");
132-
typeMapping.put("file", "std::string");
133-
typeMapping.put("object", "Object");
134-
typeMapping.put("binary", "std::string");
149+
typeMapping.put("array", STD_VECTOR);
150+
typeMapping.put("map", STD_MAP);
151+
typeMapping.put("set", STD_VECTOR);
152+
typeMapping.put("file", STD_STRING);
153+
typeMapping.put("object", NLOHMANN_JSON);
154+
typeMapping.put("binary", STD_STRING);
135155
typeMapping.put("number", "double");
136-
typeMapping.put("UUID", "std::string");
137-
typeMapping.put("URI", "std::string");
138-
typeMapping.put("ByteArray", "std::string");
139-
typeMapping.put("AnyType", "nlohmann::json");
156+
typeMapping.put("UUID", STD_STRING);
157+
typeMapping.put("URI", STD_STRING);
158+
typeMapping.put("ByteArray", STD_STRING);
159+
typeMapping.put("AnyType", NLOHMANN_JSON);
140160

141161
super.importMapping = new HashMap<>();
142-
importMapping.put("std::vector", "#include <vector>");
143-
importMapping.put("std::map", "#include <map>");
144-
importMapping.put("std::string", "#include <string>");
145-
importMapping.put("Object", "#include \"Object.h\"");
146-
importMapping.put("nlohmann::json", "#include <nlohmann/json.hpp>");
162+
importMapping.put(STD_VECTOR, "#include <vector>");
163+
importMapping.put(STD_MAP, "#include <map>");
164+
importMapping.put(STD_STRING, "#include <string>");
165+
importMapping.put(NLOHMANN_JSON, "#include <nlohmann/json.hpp>");
166+
167+
// nlohmann:json doesn't belong to model package
168+
this.openAPITypesWithoutModelNamespace.add(NLOHMANN_JSON);
147169
}
148170

149171
private void setupSupportingFiles() {
@@ -202,8 +224,16 @@ private void setupModelTemplate() {
202224
}
203225
}
204226

227+
/**
228+
* {@inheritDoc}
229+
*/
205230
@Override
206231
public String toModelImport(String name) {
232+
// Do not reattempt to add #include on an already solved #include
233+
if (name.startsWith("#include")) {
234+
return null;
235+
}
236+
207237
if (importMapping.containsKey(name)) {
208238
return importMapping.get(name);
209239
} else {
@@ -214,20 +244,23 @@ public String toModelImport(String name) {
214244

215245
@Override
216246
public CodegenModel fromModel(String name, Schema model) {
247+
// Exchange import directives from core model with ours
217248
CodegenModel codegenModel = super.fromModel(name, model);
218249

219250
Set<String> oldImports = codegenModel.imports;
220251
codegenModel.imports = new HashSet<>();
252+
221253
for (String imp : oldImports) {
222254
String newImp = toModelImport(imp);
223-
if (!newImp.isEmpty()) {
255+
256+
if (newImp != null && !newImp.isEmpty()) {
224257
codegenModel.imports.add(newImp);
225258
}
226259
}
227260

228261
if(!codegenModel.isEnum
229262
&& codegenModel.anyOf.size()>1
230-
&& codegenModel.anyOf.contains("std::string")
263+
&& codegenModel.anyOf.contains(STD_STRING)
231264
&& !codegenModel.anyOf.contains("AnyType")
232265
&& codegenModel.interfaces.size()==1
233266
){
@@ -388,7 +421,7 @@ public String getTypeDeclaration(Schema p) {
388421
Schema inner = ModelUtils.getAdditionalProperties(p);
389422
return getSchemaType(p) + "<std::string, " + getTypeDeclaration(inner) + ">";
390423
} else if (ModelUtils.isByteArraySchema(p)) {
391-
return "std::string";
424+
return STD_STRING;
392425
}
393426
if (ModelUtils.isStringSchema(p)
394427
|| ModelUtils.isDateSchema(p)
@@ -397,8 +430,14 @@ public String getTypeDeclaration(Schema p) {
397430
return toModelName(openAPIType);
398431
}
399432

400-
String namespace = (String)additionalProperties.get("modelNamespace");
401-
return namespace + "::" + openAPIType;
433+
// Some types might not support namespace
434+
if (this.openAPITypesWithoutModelNamespace.contains(openAPIType)) {
435+
return openAPIType;
436+
}
437+
else {
438+
String namespace = (String) additionalProperties.get("modelNamespace");
439+
return namespace + "::" + openAPIType;
440+
}
402441
}
403442

404443
@Override
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.openapitools.codegen.cpppistache;
18+
19+
import java.io.*;
20+
import java.nio.file.Files;
21+
import java.util.*;
22+
23+
import org.openapitools.codegen.*;
24+
import org.openapitools.codegen.config.CodegenConfigurator;
25+
26+
/**
27+
* Abstract test class to make one or multiple generators generate files for one specific input spec
28+
*/
29+
public abstract class AbstractGeneratorsTest {
30+
/**
31+
* Test each with a given input spec
32+
* @param inputSpec The input spec to use
33+
* @return Map of generator and files
34+
* @throws IOException if the test directory cannot be created
35+
*/
36+
protected Map<String, List<File>> eachWith(String inputSpec) throws IOException {
37+
Objects.requireNonNull(inputSpec, "Specify an inputspec to run that test");
38+
Map<String, List<File>> generatedFilesByGenerator = new HashMap<>();
39+
40+
for (final CodegenConfig codegenConfig : CodegenConfigLoader.getAll()) {
41+
generatedFilesByGenerator.put(codegenConfig.getName(), oneWith(codegenConfig.getName(), inputSpec));
42+
}
43+
44+
return generatedFilesByGenerator;
45+
}
46+
47+
/**
48+
* Test each with a given input spec
49+
* @param generatorName the generator name to use
50+
* @param inputSpec The input spec to use
51+
* @return List of generated files
52+
* @throws IOException if the test directory cannot be created
53+
*/
54+
protected List<File> oneWith(String generatorName, String inputSpec) throws IOException {
55+
Objects.requireNonNull(generatorName, "Specify a generatorName to run that test");
56+
Objects.requireNonNull(inputSpec, "Specify an inputspec to run that test");
57+
58+
File output = Files.createTempDirectory("test").toFile();
59+
output.deleteOnExit();
60+
61+
final CodegenConfigurator configurator = new CodegenConfigurator()
62+
.setGeneratorName(generatorName)
63+
.setInputSpec(inputSpec)
64+
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
65+
66+
final ClientOptInput clientOptInput = configurator.toClientOptInput();
67+
DefaultGenerator generator = new DefaultGenerator();
68+
return generator.opts(clientOptInput).generate();
69+
}
70+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.openapitools.codegen.cpppistache;
18+
19+
import java.io.*;
20+
import java.util.*;
21+
22+
import org.slf4j.*;
23+
import org.testng.annotations.Test;
24+
import org.testng.asserts.SoftAssert;
25+
26+
/**
27+
* Generate from an input spec containing various abstract objects and sets
28+
*/
29+
public class ObjectAnyTypeSetTest extends AbstractGeneratorsTest {
30+
/** Logger. */
31+
private static final Logger LOGGER = LoggerFactory.getLogger(ObjectAnyTypeSetTest.class);
32+
33+
/** A Petstore inputspec with abstract properties added in the Pet */
34+
private static final String INPUT_SPEC = "src/test/resources/3_0/issues-anytype-object-set-petstore-everything.yaml";
35+
36+
/** Soft assert to check all the generators before eventually failing a test */
37+
private final SoftAssert softAssert = new SoftAssert();
38+
39+
/**
40+
* Test some generators with an input spec requiring generation of abstract properties
41+
* @throws IOException if the test folder cannot be created
42+
*/
43+
@Test
44+
public void testSomeWithPetstoreWithAbstract() throws IOException {
45+
// assertGeneratedFiles("c");
46+
// assertGeneratedFiles("cpp-restsdk");
47+
generateFiles("cpp-pistache-server");
48+
// assertGeneratedFiles("typescript");
49+
this.softAssert.assertAll();
50+
}
51+
52+
/**
53+
* Asserts that a generator has produced some files
54+
* @param generatorName The generator name to test
55+
* @return List of files generated
56+
* @throws IOException if the test folder cannot be created
57+
*/
58+
private List<File> generateFiles(String generatorName) throws IOException {
59+
Objects.requireNonNull(generatorName, "A generator name is expected for this assertion");
60+
return oneWith(generatorName, INPUT_SPEC);
61+
}
62+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
These test aren't useful yet
2+
they only run the generator for a single case

0 commit comments

Comments
 (0)