Skip to content

Commit 84ce2bf

Browse files
authored
[BUG][C++][cpp-pistache-server] An api receiving a std::optional parameter generates a org::openapitools::server::model::std::optional<...> that doesn't compile #18792 (#18793)
Solving this issue has for goal to reduce the amount of work required to resolve the [[C++] Error making the cpprestsdk generated files](#6726) and to put the `cpp-pistache-server` generator a the "same compilation problems" level than the `cpp-restsdk` generator in font of the #6726.
1 parent 8783ad8 commit 84ce2bf

File tree

10 files changed

+10653
-14
lines changed

10 files changed

+10653
-14
lines changed

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ public class CodegenModel implements IJsonSchemaValidationProperties {
104104
public boolean isArray;
105105
public boolean hasChildren;
106106
public boolean isMap;
107+
/** datatype is the generic inner parameter of a std::optional for C++, or Optional (Java) */
108+
public boolean isOptional;
107109
public boolean isNull;
108110
public boolean isVoid = false;
109111
/**
@@ -741,6 +743,16 @@ public void setIsMap(boolean isMap) {
741743
this.isMap = isMap;
742744
}
743745

746+
@Override
747+
public boolean getIsOptional() {
748+
return isOptional;
749+
}
750+
751+
@Override
752+
public void setIsOptional(boolean isOptional) {
753+
this.isOptional = isOptional;
754+
}
755+
744756
@Override
745757
public boolean getIsArray() {
746758
return isArray;
@@ -1128,6 +1140,7 @@ public boolean equals(Object o) {
11281140
isArray == that.isArray &&
11291141
hasChildren == that.hasChildren &&
11301142
isMap == that.isMap &&
1143+
isOptional == that.isOptional &&
11311144
isDeprecated == that.isDeprecated &&
11321145
hasReadOnly == that.hasReadOnly &&
11331146
hasOnlyReadOnly == that.hasOnlyReadOnly &&
@@ -1221,7 +1234,7 @@ public int hashCode() {
12211234
getVars(), getAllVars(), getNonNullableVars(), getRequiredVars(), getOptionalVars(), getReadOnlyVars(), getReadWriteVars(),
12221235
getParentVars(), getAllowableValues(), getMandatory(), getAllMandatory(), getImports(), hasVars,
12231236
isEmptyVars(), hasMoreModels, hasEnums, isEnum, isNullable, hasRequired, hasOptional, isArray,
1224-
hasChildren, isMap, isDeprecated, hasReadOnly, hasOnlyReadOnly, getExternalDocumentation(), getVendorExtensions(),
1237+
hasChildren, isMap, isOptional, isDeprecated, hasReadOnly, hasOnlyReadOnly, getExternalDocumentation(), getVendorExtensions(),
12251238
getAdditionalPropertiesType(), getMaxProperties(), getMinProperties(), getUniqueItems(), getMaxItems(),
12261239
getMinItems(), getMaxLength(), getMinLength(), getExclusiveMinimum(), getExclusiveMaximum(), getMinimum(),
12271240
getMaximum(), getPattern(), getMultipleOf(), getItems(), getAdditionalProperties(), getIsModel(),
@@ -1296,6 +1309,7 @@ public String toString() {
12961309
sb.append(", isArray=").append(isArray);
12971310
sb.append(", hasChildren=").append(hasChildren);
12981311
sb.append(", isMap=").append(isMap);
1312+
sb.append(", isOptional=").append(isOptional);
12991313
sb.append(", isDeprecated=").append(isDeprecated);
13001314
sb.append(", hasReadOnly=").append(hasReadOnly);
13011315
sb.append(", hasOnlyReadOnly=").append(hasOnlyReadOnly);

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
4848
public boolean isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBinary,
4949
isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isPassword, isFreeFormObject, isAnyType, isShort, isUnboundedInteger;
5050
public boolean isArray, isMap;
51+
/** datatype is the generic inner parameter of a std::optional for C++, or Optional (Java) */
52+
public boolean isOptional;
5153
public boolean isFile;
5254
public boolean isEnum;
5355
public boolean isEnumRef; // true if the enum is a ref (model) but not defined inline
@@ -261,6 +263,7 @@ public CodegenParameter copy() {
261263
output.isAnyType = this.isAnyType;
262264
output.isArray = this.isArray;
263265
output.isMap = this.isMap;
266+
output.isOptional = this.isOptional;
264267
output.isExplode = this.isExplode;
265268
output.style = this.style;
266269
output.isDeepObject = this.isDeepObject;
@@ -280,7 +283,7 @@ public int hashCode() {
280283
enumDefaultValue, enumName, style, isDeepObject, isMatrix, isAllowEmptyValue, example, examples,
281284
jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal,
282285
isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isPassword,
283-
isFreeFormObject, isAnyType, isArray, isMap, isFile, isEnum, isEnumRef, _enum, allowableValues,
286+
isFreeFormObject, isAnyType, isArray, isMap, isOptional, isFile, isEnum, isEnumRef, _enum, allowableValues,
284287
items, mostInnerItems, additionalProperties, vars, requiredVars, vendorExtensions, hasValidation,
285288
getMaxProperties(), getMinProperties(), isNullable, isDeprecated, required, getMaximum(),
286289
getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(),
@@ -330,6 +333,7 @@ public boolean equals(Object o) {
330333
isAnyType == that.isAnyType &&
331334
isArray == that.isArray &&
332335
isMap == that.isMap &&
336+
isOptional == that.isOptional &&
333337
isFile == that.isFile &&
334338
isEnum == that.isEnum &&
335339
isEnumRef == that.isEnumRef &&
@@ -463,6 +467,7 @@ public String toString() {
463467
sb.append(", isAnyType=").append(isAnyType);
464468
sb.append(", isArray=").append(isArray);
465469
sb.append(", isMap=").append(isMap);
470+
sb.append(", isOptional=").append(isOptional);
466471
sb.append(", isFile=").append(isFile);
467472
sb.append(", isEnum=").append(isEnum);
468473
sb.append(", isEnumRef=").append(isEnumRef);
@@ -755,6 +760,16 @@ public void setIsMap(boolean isMap) {
755760
this.isMap = isMap;
756761
}
757762

763+
@Override
764+
public boolean getIsOptional() {
765+
return isOptional;
766+
}
767+
768+
@Override
769+
public void setIsOptional(boolean isOptional) {
770+
this.isOptional = isOptional;
771+
}
772+
758773
@Override
759774
public boolean getIsArray() {
760775
return isArray;

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
157157
public boolean isAnyType;
158158
public boolean isArray;
159159
public boolean isMap;
160+
/** datatype is the generic inner parameter of a std::optional for C++, or Optional (Java) */
161+
public boolean isOptional;
160162
public boolean isEnum; // true if the enum is defined inline
161163
public boolean isInnerEnum; // Enums declared inline will be located inside the generic model, changing how the enum is referenced in some cases.
162164
public boolean isEnumRef; // true if it's a reference to an enum
@@ -625,6 +627,16 @@ public void setIsMap(boolean isMap) {
625627
this.isMap = isMap;
626628
}
627629

630+
@Override
631+
public boolean getIsOptional() {
632+
return isOptional;
633+
}
634+
635+
@Override
636+
public void setIsOptional(boolean isOptional) {
637+
this.isOptional = isOptional;
638+
}
639+
628640
@Override
629641
public boolean getIsArray() {
630642
return isArray;
@@ -1200,6 +1212,7 @@ public String toString() {
12001212
sb.append(", isFreeFormObject=").append(isFreeFormObject);
12011213
sb.append(", isArray=").append(isArray);
12021214
sb.append(", isMap=").append(isMap);
1215+
sb.append(", isOptional=").append(isOptional);
12031216
sb.append(", isEnum=").append(isEnum);
12041217
sb.append(", isInnerEnum=").append(isInnerEnum);
12051218
sb.append(", isEnumRef=").append(isEnumRef);
@@ -1295,6 +1308,7 @@ public boolean equals(Object o) {
12951308
isFreeFormObject == that.isFreeFormObject &&
12961309
isArray == that.isArray &&
12971310
isMap == that.isMap &&
1311+
isOptional == that.isOptional &&
12981312
isEnum == that.isEnum &&
12991313
isInnerEnum == that.isInnerEnum &&
13001314
isEnumRef == that.isEnumRef &&
@@ -1386,7 +1400,7 @@ public int hashCode() {
13861400
hasMoreNonReadOnly, isPrimitiveType, isModel, isContainer, isString, isNumeric,
13871401
isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBinary, isFile,
13881402
isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isPassword, isFreeFormObject,
1389-
isArray, isMap, isEnum, isInnerEnum, isEnumRef, isAnyType, isReadOnly, isWriteOnly, isNullable, isShort,
1403+
isArray, isMap, isOptional, isEnum, isInnerEnum, isEnumRef, isAnyType, isReadOnly, isWriteOnly, isNullable, isShort,
13901404
isUnboundedInteger, isSelfReference, isCircularReference, isDiscriminator, isNew, isOverridden, _enum,
13911405
allowableValues, items, mostInnerItems, additionalProperties, vars, requiredVars,
13921406
vendorExtensions, hasValidation, isInherited, discriminatorValue, nameInPascalCase, nameInCamelCase,

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
5959
public boolean simpleType;
6060
public boolean primitiveType;
6161
public boolean isMap;
62+
/** datatype is the generic inner parameter of a std::optional for C++, or Optional (Java) */
63+
public boolean isOptional;
6264
public boolean isArray;
6365
public boolean isBinary = false;
6466
public boolean isFile = false;
@@ -103,7 +105,7 @@ public int hashCode() {
103105
return Objects.hash(headers, code, message, examples, dataType, baseType, containerType, containerTypeMapped, hasHeaders,
104106
isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBoolean, isDate,
105107
isDateTime, isUuid, isEmail, isPassword, isModel, isFreeFormObject, isAnyType, isDefault, simpleType, primitiveType,
106-
isMap, isArray, isBinary, isFile, schema, jsonSchema, vendorExtensions, items, additionalProperties,
108+
isMap, isOptional, isArray, isBinary, isFile, schema, jsonSchema, vendorExtensions, items, additionalProperties,
107109
vars, requiredVars, isNull, isVoid, hasValidation, isShort, isUnboundedInteger,
108110
getMaxProperties(), getMinProperties(), uniqueItems, getMaxItems(), getMinItems(), getMaxLength(),
109111
getMinLength(), exclusiveMinimum, exclusiveMaximum, getMinimum(), getMaximum(), getPattern(),
@@ -142,6 +144,7 @@ public boolean equals(Object o) {
142144
simpleType == that.simpleType &&
143145
primitiveType == that.primitiveType &&
144146
isMap == that.isMap &&
147+
isOptional == that.isOptional &&
145148
isArray == that.isArray &&
146149
isBinary == that.isBinary &&
147150
isFile == that.isFile &&
@@ -503,6 +506,16 @@ public void setIsMap(boolean isMap) {
503506
this.isMap = isMap;
504507
}
505508

509+
@Override
510+
public boolean getIsOptional() {
511+
return isOptional;
512+
}
513+
514+
@Override
515+
public void setIsOptional(boolean isOptional) {
516+
this.isOptional = isOptional;
517+
}
518+
506519
@Override
507520
public CodegenProperty getAdditionalProperties() {
508521
return additionalProperties;
@@ -594,6 +607,7 @@ public String toString() {
594607
sb.append(", simpleType=").append(simpleType);
595608
sb.append(", primitiveType=").append(primitiveType);
596609
sb.append(", isMap=").append(isMap);
610+
sb.append(", isOptional=").append(isOptional);
597611
sb.append(", isArray=").append(isArray);
598612
sb.append(", isBinary=").append(isBinary);
599613
sb.append(", isFile=").append(isFile);

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ public interface IJsonSchemaValidationProperties {
105105

106106
void setIsMap(boolean isMap);
107107

108+
/**
109+
* Tells if the datatype is a generic inner parameter of a <code>std::optional</code> for C++, or <code>Optional</code> (Java)<br>
110+
* to resolve cases (detected in issue #6726) where :<br>
111+
* - <code>categoryOneOf</code> is a parameter of class <code>GetAccountVideos_categoryOneOf_parameter</code>, a model parameter that correctly prefixed by its namespace: <code>org::openapitools::server::model::GetAccountVideos_categoryOneOf_parameter</code><br>
112+
* - but that <code>GetAccountVideos_categoryOneOf_parameter</code> class is inside an <code>std::optional</code><br>
113+
* <br>
114+
* Then a correct generation of that parameter can be (for C++) <code>const std::optional<org::openapitools::server::model::GetAccountVideos_categoryOneOf_parameter> &categoryOneOf</code><br>
115+
* but using #isModel alone without #isOptional in mustache might produce <code>const org::openapitools::server::model::std::optional<org::openapitools::server::model::GetAccountVideos_categoryOneOf_parameter> &categoryOneOf</code> instead, that do not compile.
116+
*/
117+
boolean getIsOptional();
118+
void setIsOptional(boolean isOptional);
119+
108120
boolean getIsArray();
109121

110122
void setIsArray(boolean isShort);

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,13 +356,17 @@ private void postProcessSingleOperation(OperationMap operations, CodegenOperatio
356356
* data types for Header and Query parameters.
357357
* @param param CodegenParameter to be modified.
358358
*/
359-
private static void postProcessSingleParam(CodegenParameter param) {
359+
private void postProcessSingleParam(CodegenParameter param) {
360360
//TODO: This changes the info about the real type but it is needed to parse the header params
361361
if (param.isHeaderParam) {
362362
param.dataType = "std::optional<Pistache::Http::Header::Raw>";
363363
param.baseType = "std::optional<Pistache::Http::Header::Raw>";
364364
} else if (param.isQueryParam) {
365-
param.dataType = "std::optional<" + param.dataType + ">";
365+
String dataTypeWithNamespace = param.isPrimitiveType ? param.dataType : prefixWithNameSpaceIfNeeded(param.dataType);
366+
367+
param.dataType = "std::optional<" + dataTypeWithNamespace + ">";
368+
param.isOptional = true;
369+
366370
if (!param.isPrimitiveType) {
367371
param.baseType = "std::optional<" + param.baseType + ">";
368372
}
@@ -434,8 +438,17 @@ public String getTypeDeclaration(Schema p) {
434438
return toModelName(openAPIType);
435439
}
436440

441+
return prefixWithNameSpaceIfNeeded(openAPIType);
442+
}
443+
444+
/**
445+
* Prefix an open API type with a namespace or not, depending of its current type and if it is on a list to avoid it.
446+
* @param openAPIType Open API Type.
447+
* @return type prefixed with the namespace or not.
448+
*/
449+
private String prefixWithNameSpaceIfNeeded(String openAPIType) {
437450
// Some types might not support namespace
438-
if (this.openAPITypesWithoutModelNamespace.contains(openAPIType)) {
451+
if (this.openAPITypesWithoutModelNamespace.contains(openAPIType) || openAPIType.startsWith("std::")) {
439452
return openAPIType;
440453
}
441454
else {

modules/openapi-generator/src/main/resources/cpp-pistache-server/api-header.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ private:
6565
{{#allParams}}
6666
/// <param name="{{paramName}}">{{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}</param>
6767
{{/allParams}}
68-
virtual void {{operationIdSnakeCase}}({{#allParams}}const {{#isModel}}{{modelNamespace}}::{{/isModel}}{{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response) = 0;
68+
virtual void {{operationIdSnakeCase}}({{#allParams}}const {{#isModel}}{{^isOptional}}{{modelNamespace}}::{{/isOptional}}{{/isModel}}{{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response) = 0;
6969
{{/vendorExtensions.x-codegen-pistache-is-parsing-supported}}
7070
{{^vendorExtensions.x-codegen-pistache-is-parsing-supported}}
7171
virtual void {{operationIdSnakeCase}}(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response) = 0;

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class ObjectAnyTypeSetTest extends AbstractGeneratorsTest {
3232

3333
/** A Petstore inputspec with abstract properties added in the Pet */
3434
private static final String INPUT_SPEC = "src/test/resources/3_0/issues-anytype-object-set-petstore-everything.yaml";
35+
private static final String ISSUE_6726 = "src/test/resources/3_0/issue_6726.yaml";
3536

3637
/** Soft assert to check all the generators before eventually failing a test */
3738
private final SoftAssert softAssert = new SoftAssert();
@@ -44,19 +45,20 @@ public class ObjectAnyTypeSetTest extends AbstractGeneratorsTest {
4445
public void testSomeWithPetstoreWithAbstract() throws IOException {
4546
// assertGeneratedFiles("c");
4647
// assertGeneratedFiles("cpp-restsdk");
47-
generateFiles("cpp-pistache-server");
48+
generateFiles("cpp-pistache-server", ISSUE_6726);
4849
// assertGeneratedFiles("typescript");
4950
this.softAssert.assertAll();
5051
}
5152

5253
/**
5354
* Asserts that a generator has produced some files
5455
* @param generatorName The generator name to test
56+
* @param inputSpec The inputspec to use.
5557
* @return List of files generated
5658
* @throws IOException if the test folder cannot be created
5759
*/
58-
private List<File> generateFiles(String generatorName) throws IOException {
60+
private List<File> generateFiles(String generatorName, String inputSpec) throws IOException {
5961
Objects.requireNonNull(generatorName, "A generator name is expected for this assertion");
60-
return oneWith(generatorName, INPUT_SPEC);
62+
return oneWith(generatorName, inputSpec);
6163
}
6264
}

0 commit comments

Comments
 (0)