quicktype-core 20.0.27 → 21.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/language/CPlusPlus.d.ts +11 -1
- package/dist/language/CPlusPlus.js +167 -52
- package/package.json +1 -1
|
@@ -120,12 +120,22 @@ export declare class CPlusPlusRenderer extends ConvenienceRenderer {
|
|
|
120
120
|
private readonly _memberNamingFunction;
|
|
121
121
|
private _stringType;
|
|
122
122
|
private _optionalType;
|
|
123
|
+
private _optionalFactory;
|
|
123
124
|
private _nulloptType;
|
|
124
125
|
private _variantType;
|
|
125
126
|
private _variantIndexMethodName;
|
|
126
127
|
protected readonly typeNamingStyle: NamingStyle;
|
|
127
128
|
protected readonly enumeratorNamingStyle: NamingStyle;
|
|
128
129
|
constructor(targetLanguage: TargetLanguage, renderContext: RenderContext, _options: OptionValues<typeof cPlusPlusOptions>);
|
|
130
|
+
isUnion(t: Type | UnionType): t is UnionType;
|
|
131
|
+
isOptionalAsValuePossible(t: Type): boolean;
|
|
132
|
+
isImplicitCycleBreaker(t: Type): boolean;
|
|
133
|
+
optionalTypeStack(): string;
|
|
134
|
+
optionalFactoryStack(): string;
|
|
135
|
+
optionalTypeHeap(): string;
|
|
136
|
+
optionalFactoryHeap(): string;
|
|
137
|
+
optionalType(t: Type): string;
|
|
138
|
+
optionalTypeLabel(t: Type): string;
|
|
129
139
|
protected getConstraintMembers(): ConstraintMember[];
|
|
130
140
|
protected lookupGlobalName(type: GlobalNames): string;
|
|
131
141
|
protected lookupMemberName(type: MemberNames): string;
|
|
@@ -154,7 +164,7 @@ export declare class CPlusPlusRenderer extends ConvenienceRenderer {
|
|
|
154
164
|
protected variantType(u: UnionType, inJsonNamespace: boolean): Sourcelike;
|
|
155
165
|
protected ourQualifier(inJsonNamespace: boolean): Sourcelike;
|
|
156
166
|
protected jsonQualifier(inJsonNamespace: boolean): Sourcelike;
|
|
157
|
-
protected variantIndirection(needIndirection: boolean, typeSrc: Sourcelike): Sourcelike;
|
|
167
|
+
protected variantIndirection(type: Type, needIndirection: boolean, typeSrc: Sourcelike): Sourcelike;
|
|
158
168
|
protected cppType(t: Type, ctx: TypeContext, withIssues: boolean, forceNarrowString: boolean, isOptional: boolean): Sourcelike;
|
|
159
169
|
/**
|
|
160
170
|
* similar to cppType, it practically gathers all the generated types within
|
|
@@ -216,19 +216,10 @@ const keywords = [
|
|
|
216
216
|
"transaction_safe_dynamic",
|
|
217
217
|
"NULL"
|
|
218
218
|
];
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
* forward declarability.
|
|
224
|
-
* The next question, why isn't unique_ptr is enough here?
|
|
225
|
-
* That problem relates to getter/setter. If using getter/setters we
|
|
226
|
-
* can't/mustn't return a unique_ptr out of the class -> as that is the
|
|
227
|
-
* sole reason why we have declared that as unique_ptr, so that only
|
|
228
|
-
* the class owns it. We COULD return unique_ptr references, which practically
|
|
229
|
-
* kills the uniqueness of the smart pointer -> hence we use shared_ptrs.
|
|
230
|
-
*/
|
|
231
|
-
const optionalType = "std::shared_ptr";
|
|
219
|
+
/// Type to use as an optional if cycle breaking is required
|
|
220
|
+
const optionalAsSharedType = "std::shared_ptr";
|
|
221
|
+
/// Factory to use when creating an optional if cycle breaking is required
|
|
222
|
+
const optionalFactoryAsSharedType = "std::make_shared";
|
|
232
223
|
/**
|
|
233
224
|
* To be able to support circles in multiple files -
|
|
234
225
|
* e.g. class#A using class#B using class#A (obviously not directly,
|
|
@@ -434,18 +425,124 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
434
425
|
}
|
|
435
426
|
if (_options.boost) {
|
|
436
427
|
this._optionalType = "boost::optional";
|
|
428
|
+
this._optionalFactory = "boost::optional";
|
|
437
429
|
this._nulloptType = "boost::none";
|
|
438
430
|
this._variantType = "boost::variant";
|
|
439
431
|
this._variantIndexMethodName = "which";
|
|
440
432
|
}
|
|
441
433
|
else {
|
|
442
434
|
this._optionalType = "std::optional";
|
|
435
|
+
this._optionalFactory = "std::make_optional";
|
|
443
436
|
this._nulloptType = "std::nullopt";
|
|
444
437
|
this._variantType = "std::variant";
|
|
445
438
|
this._variantIndexMethodName = "index";
|
|
446
439
|
}
|
|
447
440
|
this.setupGlobalNames();
|
|
448
441
|
}
|
|
442
|
+
// union typeguard
|
|
443
|
+
isUnion(t) {
|
|
444
|
+
return t.kind === "union";
|
|
445
|
+
}
|
|
446
|
+
// Returns true if the type can be stored in
|
|
447
|
+
// a stack based optional type. This requires
|
|
448
|
+
// that the type does not require forward declaration.
|
|
449
|
+
isOptionalAsValuePossible(t) {
|
|
450
|
+
if (this.isForwardDeclaredType(t))
|
|
451
|
+
return false;
|
|
452
|
+
if (this.isUnion(t)) {
|
|
453
|
+
// There is something stinky about this test.
|
|
454
|
+
// There is special handling somewhere that if you
|
|
455
|
+
// have the following schema
|
|
456
|
+
// {
|
|
457
|
+
// "$schema": "http://json-schema.org/draft-06/schema#",
|
|
458
|
+
// "$ref": "#/definitions/List",
|
|
459
|
+
// "definitions": {
|
|
460
|
+
// "List": {
|
|
461
|
+
// "type": "object",
|
|
462
|
+
// "additionalProperties": false,
|
|
463
|
+
// "properties": {
|
|
464
|
+
// "data": {
|
|
465
|
+
// "type": "string"
|
|
466
|
+
// },
|
|
467
|
+
// "next": {
|
|
468
|
+
// "anyOf": [
|
|
469
|
+
// {
|
|
470
|
+
// "$ref": "#/definitions/List"
|
|
471
|
+
// }
|
|
472
|
+
// {
|
|
473
|
+
// "type": "null"
|
|
474
|
+
// }
|
|
475
|
+
// ]
|
|
476
|
+
// }
|
|
477
|
+
// },
|
|
478
|
+
// "required": [],
|
|
479
|
+
// "title": "List"
|
|
480
|
+
// }
|
|
481
|
+
// }
|
|
482
|
+
// }
|
|
483
|
+
// Then a variant is not output but the single item inlined
|
|
484
|
+
//
|
|
485
|
+
// struct TopLevel {
|
|
486
|
+
// std::optional<std::string> data;
|
|
487
|
+
// std::optional<TopLevel> next;
|
|
488
|
+
// };
|
|
489
|
+
//
|
|
490
|
+
// instead of
|
|
491
|
+
// struct TopLevel {
|
|
492
|
+
// std::optional<std::string> data;
|
|
493
|
+
// std::shared_ptr<TopLevel> next;
|
|
494
|
+
// };
|
|
495
|
+
//
|
|
496
|
+
// checking to see if the collapse of the variant has
|
|
497
|
+
// occured and then doing the isCycleBreakerType check
|
|
498
|
+
// on the single type the variant would contain seems
|
|
499
|
+
// to solve the problem. But does this point to a problem
|
|
500
|
+
// with the core library or with the CPlusPlus package
|
|
501
|
+
const [, nonNulls] = (0, TypeUtils_1.removeNullFromUnion)(t);
|
|
502
|
+
if (nonNulls.size === 1) {
|
|
503
|
+
const tt = (0, Support_1.defined)((0, collection_utils_1.iterableFirst)(nonNulls));
|
|
504
|
+
return !this.isCycleBreakerType(tt);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return !this.isCycleBreakerType(t);
|
|
508
|
+
}
|
|
509
|
+
isImplicitCycleBreaker(t) {
|
|
510
|
+
const kind = t.kind;
|
|
511
|
+
return kind === "array" || kind === "map";
|
|
512
|
+
}
|
|
513
|
+
// Is likely to return std::optional or boost::optional
|
|
514
|
+
optionalTypeStack() {
|
|
515
|
+
return this._optionalType;
|
|
516
|
+
}
|
|
517
|
+
// Is likely to return std::make_optional or boost::optional
|
|
518
|
+
optionalFactoryStack() {
|
|
519
|
+
return this._optionalFactory;
|
|
520
|
+
}
|
|
521
|
+
// Is likely to return std::shared_ptr
|
|
522
|
+
optionalTypeHeap() {
|
|
523
|
+
return optionalAsSharedType;
|
|
524
|
+
}
|
|
525
|
+
// Is likely to return std::make_shared
|
|
526
|
+
optionalFactoryHeap() {
|
|
527
|
+
return optionalFactoryAsSharedType;
|
|
528
|
+
}
|
|
529
|
+
// Returns the optional type most suitable for the given type.
|
|
530
|
+
// Classes that don't require forward declarations can be stored
|
|
531
|
+
// in std::optional ( or boost::optional )
|
|
532
|
+
optionalType(t) {
|
|
533
|
+
if (this.isOptionalAsValuePossible(t))
|
|
534
|
+
return this.optionalTypeStack();
|
|
535
|
+
else
|
|
536
|
+
return this.optionalTypeHeap();
|
|
537
|
+
}
|
|
538
|
+
// Returns a label that can be used to distinguish between
|
|
539
|
+
// heap and stack based optional handling methods
|
|
540
|
+
optionalTypeLabel(t) {
|
|
541
|
+
if (this.isOptionalAsValuePossible(t))
|
|
542
|
+
return "stack";
|
|
543
|
+
else
|
|
544
|
+
return "heap";
|
|
545
|
+
}
|
|
449
546
|
getConstraintMembers() {
|
|
450
547
|
return [
|
|
451
548
|
{
|
|
@@ -672,7 +769,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
672
769
|
if (!indirection) {
|
|
673
770
|
return variant;
|
|
674
771
|
}
|
|
675
|
-
return [optionalType, "<", variant, ">"];
|
|
772
|
+
return [this.optionalType(u), "<", variant, ">"];
|
|
676
773
|
}
|
|
677
774
|
ourQualifier(inJsonNamespace) {
|
|
678
775
|
return inJsonNamespace ? [(0, collection_utils_1.arrayIntercalate)("::", this._namespaceNames), "::"] : [];
|
|
@@ -680,10 +777,10 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
680
777
|
jsonQualifier(inJsonNamespace) {
|
|
681
778
|
return inJsonNamespace ? [] : "nlohmann::";
|
|
682
779
|
}
|
|
683
|
-
variantIndirection(needIndirection, typeSrc) {
|
|
780
|
+
variantIndirection(type, needIndirection, typeSrc) {
|
|
684
781
|
if (!needIndirection)
|
|
685
782
|
return typeSrc;
|
|
686
|
-
return [optionalType, "<", typeSrc, ">"];
|
|
783
|
+
return [this.optionalType(type), "<", typeSrc, ">"];
|
|
687
784
|
}
|
|
688
785
|
cppType(t, ctx, withIssues, forceNarrowString, isOptional) {
|
|
689
786
|
const inJsonNamespace = ctx.inJsonNamespace;
|
|
@@ -719,7 +816,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
719
816
|
"std::vector<",
|
|
720
817
|
this.cppType(arrayType.items, { needsForwardIndirection: false, needsOptionalIndirection: true, inJsonNamespace }, withIssues, forceNarrowString, false),
|
|
721
818
|
">"
|
|
722
|
-
], classType => this.variantIndirection(ctx.needsForwardIndirection && this.isForwardDeclaredType(classType) && !isOptional, [this.ourQualifier(inJsonNamespace), this.nameForNamedType(classType)]), mapType => {
|
|
819
|
+
], classType => this.variantIndirection(classType, ctx.needsForwardIndirection && this.isForwardDeclaredType(classType) && !isOptional, [this.ourQualifier(inJsonNamespace), this.nameForNamedType(classType)]), mapType => {
|
|
723
820
|
let keyType = this._stringType.getType();
|
|
724
821
|
if (forceNarrowString) {
|
|
725
822
|
keyType = "std::string";
|
|
@@ -733,14 +830,17 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
733
830
|
];
|
|
734
831
|
}, enumType => [this.ourQualifier(inJsonNamespace), this.nameForNamedType(enumType)], unionType => {
|
|
735
832
|
const nullable = (0, TypeUtils_1.nullableFromUnion)(unionType);
|
|
736
|
-
if (nullable
|
|
833
|
+
if (nullable !== null) {
|
|
834
|
+
isOptional = true;
|
|
835
|
+
return this.cppType(nullable, { needsForwardIndirection: false, needsOptionalIndirection: false, inJsonNamespace }, withIssues, forceNarrowString, false);
|
|
836
|
+
}
|
|
837
|
+
else {
|
|
737
838
|
return [this.ourQualifier(inJsonNamespace), this.nameForNamedType(unionType)];
|
|
738
|
-
|
|
739
|
-
return this.cppType(nullable, { needsForwardIndirection: false, needsOptionalIndirection: false, inJsonNamespace }, withIssues, forceNarrowString, false);
|
|
839
|
+
}
|
|
740
840
|
});
|
|
741
841
|
if (!isOptional)
|
|
742
842
|
return typeSource;
|
|
743
|
-
return [optionalType, "<", typeSource, ">"];
|
|
843
|
+
return [this.optionalType(t), "<", typeSource, ">"];
|
|
744
844
|
}
|
|
745
845
|
/**
|
|
746
846
|
* similar to cppType, it practically gathers all the generated types within
|
|
@@ -938,8 +1038,8 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
938
1038
|
// Forward declarations for std::map<std::wstring, Key> (need to convert UTF16 <-> UTF8)
|
|
939
1039
|
if (t instanceof Type_1.MapType && this._stringType !== this.NarrowString) {
|
|
940
1040
|
const ourQualifier = this.ourQualifier(true);
|
|
941
|
-
this.emitLine("template <>");
|
|
942
1041
|
this.emitBlock(["struct adl_serializer<", ourQualifier, className, ">"], true, () => {
|
|
1042
|
+
this.emitLine("template <>");
|
|
943
1043
|
this.emitLine("static void from_json(", this.withConst("json"), " & j, ", ourQualifier, className, " & x);");
|
|
944
1044
|
this.emitLine("static void to_json(json & j, ", this.withConst([ourQualifier, className]), " & x);");
|
|
945
1045
|
});
|
|
@@ -1045,9 +1145,9 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
1045
1145
|
inJsonNamespace: false
|
|
1046
1146
|
}, false, false);
|
|
1047
1147
|
this.emitLine(assignment.wrap([], [
|
|
1048
|
-
this._stringType.wrapEncodingChange([ourQualifier], [optionalType, "<", cppType, ">"], [optionalType, "<", toType, ">"], [
|
|
1148
|
+
this._stringType.wrapEncodingChange([ourQualifier], [this.optionalType(t), "<", cppType, ">"], [this.optionalType(t), "<", toType, ">"], [
|
|
1049
1149
|
ourQualifier,
|
|
1050
|
-
|
|
1150
|
+
`get_${this.optionalTypeLabel(t)}_optional<`,
|
|
1051
1151
|
cppType,
|
|
1052
1152
|
">(j, ",
|
|
1053
1153
|
this._stringType.wrapEncodingChange([ourQualifier], this._stringType.getType(), this.NarrowString.getType(), [this._stringType.createStringLiteral([(0, Strings_1.stringEscape)(json)])]),
|
|
@@ -1276,16 +1376,20 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
1276
1376
|
this.emitLine("#ifndef NLOHMANN_OPT_HELPER");
|
|
1277
1377
|
this.emitLine("#define NLOHMANN_OPT_HELPER");
|
|
1278
1378
|
this.emitNamespaces(["nlohmann"], () => {
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
this.emitBlock(["
|
|
1282
|
-
this.
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
this.
|
|
1379
|
+
const emitAdlStruct = (optType, factory) => {
|
|
1380
|
+
this.emitLine("template <typename T>");
|
|
1381
|
+
this.emitBlock(["struct adl_serializer<", optType, "<T>>"], true, () => {
|
|
1382
|
+
this.emitBlock(["static void to_json(json & j, ", this.withConst([optType, "<T>"]), " & opt)"], false, () => {
|
|
1383
|
+
this.emitLine("if (!opt) j = nullptr; else j = *opt;");
|
|
1384
|
+
});
|
|
1385
|
+
this.ensureBlankLine();
|
|
1386
|
+
this.emitBlock(["static ", optType, "<T> from_json(", this.withConst("json"), " & j)"], false, () => {
|
|
1387
|
+
this.emitLine(`if (j.is_null()) return ${factory}<T>(); else return ${factory}<T>(j.get<T>());`);
|
|
1388
|
+
});
|
|
1287
1389
|
});
|
|
1288
|
-
}
|
|
1390
|
+
};
|
|
1391
|
+
emitAdlStruct(this.optionalTypeHeap(), this.optionalFactoryHeap());
|
|
1392
|
+
emitAdlStruct(this.optionalTypeStack(), this.optionalFactoryStack());
|
|
1289
1393
|
});
|
|
1290
1394
|
this.emitLine("#endif");
|
|
1291
1395
|
}
|
|
@@ -1481,26 +1585,37 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
1481
1585
|
this.ensureBlankLine();
|
|
1482
1586
|
this.emitLine("#ifndef " + optionalMacroName);
|
|
1483
1587
|
this.emitLine("#define " + optionalMacroName);
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
this.emitLine("
|
|
1588
|
+
const emitGetOptional = (optionalType, label) => {
|
|
1589
|
+
this.emitLine("template <typename T>");
|
|
1590
|
+
this.emitBlock([
|
|
1591
|
+
"inline ",
|
|
1592
|
+
optionalType,
|
|
1593
|
+
`<T> get_${label}_optional(`,
|
|
1594
|
+
this.withConst("json"),
|
|
1595
|
+
" & j, ",
|
|
1596
|
+
this.withConst("char"),
|
|
1597
|
+
" * property)"
|
|
1598
|
+
], false, () => {
|
|
1599
|
+
this.emitLine(["auto it = j.find(property);"]);
|
|
1600
|
+
this.emitBlock(["if (it != j.end() && !it->is_null())"], false, () => {
|
|
1601
|
+
this.emitLine("return j.at(property).get<", optionalType, "<T>>();");
|
|
1602
|
+
});
|
|
1603
|
+
this.emitLine("return ", optionalType, "<T>();");
|
|
1496
1604
|
});
|
|
1497
|
-
this.
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1605
|
+
this.ensureBlankLine();
|
|
1606
|
+
this.emitLine("template <typename T>");
|
|
1607
|
+
this.emitBlock([
|
|
1608
|
+
"inline ",
|
|
1609
|
+
optionalType,
|
|
1610
|
+
`<T> get_${label}_optional(`,
|
|
1611
|
+
this.withConst("json"),
|
|
1612
|
+
" & j, std::string property)"
|
|
1613
|
+
], false, () => {
|
|
1614
|
+
this.emitLine(`return get_${label}_optional<T>(j, property.data());`);
|
|
1615
|
+
});
|
|
1616
|
+
};
|
|
1617
|
+
emitGetOptional(this.optionalTypeHeap(), "heap");
|
|
1618
|
+
emitGetOptional(this.optionalTypeStack(), "stack");
|
|
1504
1619
|
this.emitLine("#endif");
|
|
1505
1620
|
this.ensureBlankLine();
|
|
1506
1621
|
}
|