quicktype 15.0.258 → 15.0.261

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/README.md CHANGED
@@ -148,7 +148,7 @@ const {
148
148
  InputData,
149
149
  jsonInputForTargetLanguage,
150
150
  JSONSchemaInput,
151
- JSONSchemaStore,
151
+ FetchingJSONSchemaStore,
152
152
  } = require("quicktype-core");
153
153
 
154
154
  async function quicktypeJSON(targetLanguage, typeName, jsonString) {
@@ -172,7 +172,7 @@ async function quicktypeJSON(targetLanguage, typeName, jsonString) {
172
172
  }
173
173
 
174
174
  async function quicktypeJSONSchema(targetLanguage, typeName, jsonSchemaString) {
175
- const schemaInput = new JSONSchemaInput(new JSONSchemaStore());
175
+ const schemaInput = new JSONSchemaInput(new FetchingJSONSchemaStore());
176
176
 
177
177
  // We could add multiple schemas for multiple types,
178
178
  // but here we're just making one type from JSON schema.
@@ -1,5 +1,5 @@
1
1
  import { Readable } from "readable-stream";
2
- import { JSONSourceData, JSONSchemaSourceData } from "quicktype-core";
2
+ import { JSONSourceData, JSONSchemaSourceData } from "../quicktype-core";
3
3
  import { GraphQLSourceData } from "../quicktype-graphql-input";
4
4
  export interface JSONTypeSource extends JSONSourceData<Readable> {
5
5
  kind: "json";
@@ -26,9 +26,7 @@ const unionMemberNameOrder = 40;
26
26
  function splitDescription(descriptions) {
27
27
  if (descriptions === undefined)
28
28
  return undefined;
29
- const description = Array.from(descriptions)
30
- .join("\n\n")
31
- .trim();
29
+ const description = Array.from(descriptions).join("\n\n").trim();
32
30
  if (description === "")
33
31
  return undefined;
34
32
  return wordWrap(description)
@@ -475,9 +473,7 @@ class ConvenienceRenderer extends Renderer_1.Renderer {
475
473
  });
476
474
  }
477
475
  nameForUnionMember(u, t) {
478
- return Support_1.defined(Support_1.defined(this._memberNamesStoreView)
479
- .get(u)
480
- .get(t));
476
+ return Support_1.defined(Support_1.defined(this._memberNamesStoreView).get(u).get(t));
481
477
  }
482
478
  nameForEnumCase(e, caseName) {
483
479
  const caseNames = Support_1.defined(this._caseNamesStoreView).get(e);
@@ -5,7 +5,7 @@ export { JSONSchemaInput, JSONSchemaSourceData } from "./input/JSONSchemaInput";
5
5
  export { Ref, JSONSchemaType, JSONSchemaAttributes } from "./input/JSONSchemaInput";
6
6
  export { RenderContext } from "./Renderer";
7
7
  export { Option, OptionDefinition, getOptionValues } from "./RendererOptions";
8
- export { TargetLanguage } from "./TargetLanguage";
8
+ export { TargetLanguage, MultiFileRenderResult } from "./TargetLanguage";
9
9
  export { all as defaultTargetLanguages, languageNamed } from "./language/All";
10
10
  export { MultiWord, Sourcelike, SerializedRenderResult, Annotation, modifySource, singleWord, parenIfNeeded } from "./Source";
11
11
  export { Name, funPrefixNamer, Namer } from "./Naming";
@@ -28,7 +28,7 @@ export { StringTypes } from "./attributes/StringTypes";
28
28
  export { removeNullFromUnion, matchType, nullableFromUnion } from "./TypeUtils";
29
29
  export { ConvenienceRenderer } from "./ConvenienceRenderer";
30
30
  export { uriTypeAttributeKind } from "./attributes/URIAttributes";
31
- export { CPlusPlusTargetLanguage, CPlusPlusRenderer } from "./language/CPlusPlus";
31
+ export { CPlusPlusTargetLanguage, CPlusPlusRenderer, cPlusPlusOptions } from "./language/CPlusPlus";
32
32
  export { CSharpTargetLanguage, cSharpOptions, CSharpRenderer, NewtonsoftCSharpTargetLanguage, newtonsoftCSharpOptions, NewtonsoftCSharpRenderer } from "./language/CSharp";
33
33
  export { GoTargetLanguage, GoRenderer, goOptions } from "./language/Golang";
34
34
  export { ObjectiveCTargetLanguage, ObjectiveCRenderer, objcOptions } from "./language/Objective-C";
@@ -44,3 +44,4 @@ export { RustTargetLanguage, RustRenderer, rustOptions } from "./language/Rust";
44
44
  export { RubyTargetLanguage, RubyRenderer, rubyOptions } from "./language/ruby";
45
45
  export { CrystalTargetLanguage, CrystalRenderer } from "./language/Crystal";
46
46
  export { HaskellTargetLanguage, HaskellRenderer, haskellOptions } from "./language/Haskell";
47
+ export { DartTargetLanguage, DartRenderer, dartOptions } from "./language/Dart";
@@ -106,6 +106,7 @@ exports.uriTypeAttributeKind = URIAttributes_1.uriTypeAttributeKind;
106
106
  var CPlusPlus_1 = require("./language/CPlusPlus");
107
107
  exports.CPlusPlusTargetLanguage = CPlusPlus_1.CPlusPlusTargetLanguage;
108
108
  exports.CPlusPlusRenderer = CPlusPlus_1.CPlusPlusRenderer;
109
+ exports.cPlusPlusOptions = CPlusPlus_1.cPlusPlusOptions;
109
110
  var CSharp_1 = require("./language/CSharp");
110
111
  exports.CSharpTargetLanguage = CSharp_1.CSharpTargetLanguage;
111
112
  exports.cSharpOptions = CSharp_1.cSharpOptions;
@@ -169,3 +170,7 @@ var Haskell_1 = require("./language/Haskell");
169
170
  exports.HaskellTargetLanguage = Haskell_1.HaskellTargetLanguage;
170
171
  exports.HaskellRenderer = Haskell_1.HaskellRenderer;
171
172
  exports.haskellOptions = Haskell_1.haskellOptions;
173
+ var Dart_1 = require("./language/Dart");
174
+ exports.DartTargetLanguage = Dart_1.DartTargetLanguage;
175
+ exports.DartRenderer = Dart_1.DartRenderer;
176
+ exports.dartOptions = Dart_1.dartOptions;
@@ -21,11 +21,13 @@ export declare const cPlusPlusOptions: {
21
21
  memberNamingStyle: EnumOption<NamingStyle>;
22
22
  enumeratorNamingStyle: EnumOption<NamingStyle>;
23
23
  boost: BooleanOption;
24
+ hideNullOptional: BooleanOption;
24
25
  };
25
26
  export declare class CPlusPlusTargetLanguage extends TargetLanguage {
26
27
  constructor(displayName?: string, names?: string[], extension?: string);
27
28
  protected getOptions(): Option<any>[];
28
29
  readonly supportsUnionsWithBothNumberTypes: boolean;
30
+ readonly supportsOptionalClassProperties: boolean;
29
31
  protected makeRenderer(renderContext: RenderContext, untypedOptionValues: {
30
32
  [name: string]: any;
31
33
  }): CPlusPlusRenderer;
@@ -154,7 +156,7 @@ export declare class CPlusPlusRenderer extends ConvenienceRenderer {
154
156
  protected ourQualifier(inJsonNamespace: boolean): Sourcelike;
155
157
  protected jsonQualifier(inJsonNamespace: boolean): Sourcelike;
156
158
  protected variantIndirection(needIndirection: boolean, typeSrc: Sourcelike): Sourcelike;
157
- protected cppType(t: Type, ctx: TypeContext, withIssues: boolean, forceNarrowString: boolean): Sourcelike;
159
+ protected cppType(t: Type, ctx: TypeContext, withIssues: boolean, forceNarrowString: boolean, isOptional: boolean): Sourcelike;
158
160
  /**
159
161
  * similar to cppType, it practically gathers all the generated types within
160
162
  * 't'. It also records, whether a given sub-type is part of a variant or not.
@@ -55,7 +55,8 @@ exports.cPlusPlusOptions = {
55
55
  pascalUpperAcronymsValue,
56
56
  camelUpperAcronymsValue
57
57
  ]),
58
- boost: new RendererOptions_1.BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true)
58
+ boost: new RendererOptions_1.BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true),
59
+ hideNullOptional: new RendererOptions_1.BooleanOption("hide-null-optional", "Hide null value for optional field", false),
59
60
  };
60
61
  class CPlusPlusTargetLanguage extends TargetLanguage_1.TargetLanguage {
61
62
  constructor(displayName = "C++", names = ["c++", "cpp", "cplusplus"], extension = "cpp") {
@@ -75,12 +76,16 @@ class CPlusPlusTargetLanguage extends TargetLanguage_1.TargetLanguage {
75
76
  exports.cPlusPlusOptions.memberNamingStyle,
76
77
  exports.cPlusPlusOptions.enumeratorNamingStyle,
77
78
  exports.cPlusPlusOptions.enumType,
78
- exports.cPlusPlusOptions.boost
79
+ exports.cPlusPlusOptions.boost,
80
+ exports.cPlusPlusOptions.hideNullOptional,
79
81
  ];
80
82
  }
81
83
  get supportsUnionsWithBothNumberTypes() {
82
84
  return true;
83
85
  }
86
+ get supportsOptionalClassProperties() {
87
+ return true;
88
+ }
84
89
  makeRenderer(renderContext, untypedOptionValues) {
85
90
  return new CPlusPlusRenderer(this, renderContext, RendererOptions_1.getOptionValues(exports.cPlusPlusOptions, untypedOptionValues));
86
91
  }
@@ -633,7 +638,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
633
638
  }
634
639
  cppTypeInOptional(nonNulls, ctx, withIssues, forceNarrowString) {
635
640
  if (nonNulls.size === 1) {
636
- return this.cppType(Support_1.defined(collection_utils_1.iterableFirst(nonNulls)), ctx, withIssues, forceNarrowString);
641
+ return this.cppType(Support_1.defined(collection_utils_1.iterableFirst(nonNulls)), ctx, withIssues, forceNarrowString, false);
637
642
  }
638
643
  const typeList = [];
639
644
  for (const t of nonNulls) {
@@ -644,7 +649,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
644
649
  needsForwardIndirection: true,
645
650
  needsOptionalIndirection: false,
646
651
  inJsonNamespace: ctx.inJsonNamespace
647
- }, withIssues, false));
652
+ }, withIssues, false, false));
648
653
  }
649
654
  return [this._variantType, "<", typeList, ">"];
650
655
  }
@@ -669,9 +674,23 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
669
674
  return typeSrc;
670
675
  return [optionalType, "<", typeSrc, ">"];
671
676
  }
672
- cppType(t, ctx, withIssues, forceNarrowString) {
677
+ cppType(t, ctx, withIssues, forceNarrowString, isOptional) {
673
678
  const inJsonNamespace = ctx.inJsonNamespace;
674
- return TypeUtils_1.matchType(t, _anyType => Source_1.maybeAnnotated(withIssues, Annotation_1.anyTypeIssueAnnotation, [this.jsonQualifier(inJsonNamespace), "json"]), _nullType => Source_1.maybeAnnotated(withIssues, Annotation_1.nullTypeIssueAnnotation, [this.jsonQualifier(inJsonNamespace), "json"]), _boolType => "bool", _integerType => "int64_t", _doubleType => "double", _stringType => {
679
+ if (isOptional && t instanceof Type_1.UnionType) { // avoid have optionalType<optionalType<Type>>
680
+ for (const tChild of t.getChildren()) {
681
+ if (tChild.isNullable) {
682
+ isOptional = false;
683
+ break;
684
+ }
685
+ }
686
+ }
687
+ let typeSource = TypeUtils_1.matchType(t, _anyType => {
688
+ isOptional = false;
689
+ return Source_1.maybeAnnotated(withIssues, Annotation_1.anyTypeIssueAnnotation, [this.jsonQualifier(inJsonNamespace), "json"]);
690
+ }, _nullType => {
691
+ isOptional = false;
692
+ return Source_1.maybeAnnotated(withIssues, Annotation_1.nullTypeIssueAnnotation, [this.jsonQualifier(inJsonNamespace), "json"]);
693
+ }, _boolType => "bool", _integerType => "int64_t", _doubleType => "double", _stringType => {
675
694
  if (forceNarrowString) {
676
695
  return "std::string";
677
696
  }
@@ -680,9 +699,9 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
680
699
  }
681
700
  }, arrayType => [
682
701
  "std::vector<",
683
- this.cppType(arrayType.items, { needsForwardIndirection: false, needsOptionalIndirection: true, inJsonNamespace }, withIssues, forceNarrowString),
702
+ this.cppType(arrayType.items, { needsForwardIndirection: false, needsOptionalIndirection: true, inJsonNamespace }, withIssues, forceNarrowString, false),
684
703
  ">"
685
- ], classType => this.variantIndirection(ctx.needsForwardIndirection && this.isForwardDeclaredType(classType), [
704
+ ], classType => this.variantIndirection(ctx.needsForwardIndirection && this.isForwardDeclaredType(classType) && !isOptional, [
686
705
  this.ourQualifier(inJsonNamespace),
687
706
  this.nameForNamedType(classType)
688
707
  ]), mapType => {
@@ -694,20 +713,24 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
694
713
  "std::map<",
695
714
  keyType,
696
715
  ", ",
697
- this.cppType(mapType.values, { needsForwardIndirection: false, needsOptionalIndirection: true, inJsonNamespace }, withIssues, forceNarrowString),
716
+ this.cppType(mapType.values, { needsForwardIndirection: false, needsOptionalIndirection: true, inJsonNamespace }, withIssues, forceNarrowString, false),
698
717
  ">"
699
718
  ];
700
719
  }, enumType => [this.ourQualifier(inJsonNamespace), this.nameForNamedType(enumType)], unionType => {
701
720
  const nullable = TypeUtils_1.nullableFromUnion(unionType);
702
721
  if (nullable === null)
703
722
  return [this.ourQualifier(inJsonNamespace), this.nameForNamedType(unionType)];
704
- return [
705
- optionalType,
706
- "<",
707
- this.cppType(nullable, { needsForwardIndirection: false, needsOptionalIndirection: false, inJsonNamespace }, withIssues, forceNarrowString),
708
- ">"
709
- ];
723
+ isOptional = true;
724
+ return this.cppType(nullable, { needsForwardIndirection: false, needsOptionalIndirection: false, inJsonNamespace }, withIssues, forceNarrowString, false);
710
725
  });
726
+ if (!isOptional)
727
+ return typeSource;
728
+ return [
729
+ optionalType,
730
+ "<",
731
+ typeSource,
732
+ ">"
733
+ ];
711
734
  }
712
735
  /**
713
736
  * similar to cppType, it practically gathers all the generated types within
@@ -787,7 +810,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
787
810
  if (this._options.codeFormat) {
788
811
  this.emitLine("private:");
789
812
  this.forEachClassProperty(c, "none", (name, jsonName, property) => {
790
- this.emitMember(this.cppType(property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: false }, true, false), name);
813
+ this.emitMember(this.cppType(property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: false }, true, false, property.isOptional), name);
791
814
  if (constraints !== undefined && constraints.has(jsonName)) {
792
815
  /** FIXME!!! NameStyle will/can collide with other Names */
793
816
  const cnst = this.lookupGlobalName(GlobalNames.ClassMemberConstraints);
@@ -800,18 +823,18 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
800
823
  this.forEachClassProperty(c, "none", (name, jsonName, property) => {
801
824
  this.emitDescription(this.descriptionForClassProperty(c, jsonName));
802
825
  if (!this._options.codeFormat) {
803
- this.emitMember(this.cppType(property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: false }, true, false), name);
826
+ this.emitMember(this.cppType(property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: false }, true, false, property.isOptional), name);
804
827
  }
805
828
  else {
806
829
  const [getterName, mutableGetterName, setterName] = Support_1.defined(this._gettersAndSettersForPropertyName.get(name));
807
- const rendered = this.cppType(property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: false }, true, false);
830
+ const rendered = this.cppType(property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: false }, true, false, property.isOptional);
808
831
  /**
809
832
  * fix for optional type -> e.g. unique_ptrs can't be copied
810
833
  * One might as why the "this->xxx = value". Simple if we have
811
834
  * a member called 'value' value = value will screw up the compiler
812
835
  */
813
836
  const checkConst = this.lookupGlobalName(GlobalNames.CheckConstraint);
814
- if (property.type instanceof Type_1.UnionType && property.type.findMember("null") !== undefined) {
837
+ if ((property.type instanceof Type_1.UnionType && property.type.findMember("null") !== undefined) || (property.isOptional && property.type.kind !== "null" && property.type.kind !== "any")) {
815
838
  this.emitLine(rendered, " ", getterName, "() const { return ", name, "; }");
816
839
  if (constraints !== undefined && constraints.has(jsonName)) {
817
840
  this.emitLine("void ", setterName, "(", rendered, " value) { if (value) ", checkConst, "(", this._stringType.createStringLiteral([name]), ", ", this.constraintMember(jsonName), ", *value); this->", name, " = value; }");
@@ -909,8 +932,8 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
909
932
  let cppType;
910
933
  let toType;
911
934
  this.emitBlock(["inline void from_json(", this.withConst("json"), " & j, ", ourQualifier, className, "& x)"], false, () => {
912
- cppType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true);
913
- toType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false);
935
+ cppType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true, false);
936
+ toType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false, false);
914
937
  this.emitLine([
915
938
  "x = ",
916
939
  this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, ["j.get<", cppType, ">()"]),
@@ -918,8 +941,8 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
918
941
  ]);
919
942
  });
920
943
  this.emitBlock(["inline void to_json(json & j, ", this.withConst([ourQualifier, className]), " & x)"], false, () => {
921
- cppType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false);
922
- toType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true);
944
+ cppType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false, false);
945
+ toType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true, false);
923
946
  this.emitLine([
924
947
  "j = ",
925
948
  this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, "x"),
@@ -943,15 +966,34 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
943
966
  else {
944
967
  assignment = new WrappingCode(["x.", name, " = "], []);
945
968
  }
946
- if (t instanceof Type_1.UnionType) {
947
- const [maybeNull, nonNulls] = TypeUtils_1.removeNullFromUnion(t, true);
948
- if (maybeNull !== null) {
949
- cppType = this.cppTypeInOptional(nonNulls, {
969
+ if (t.kind === "null" || t.kind === "any") {
970
+ this.emitLine(assignment.wrap([], [
971
+ ourQualifier,
972
+ "get_untyped(j, ",
973
+ this._stringType.wrapEncodingChange([ourQualifier], this._stringType.getType(), this.NarrowString.getType(), [this._stringType.createStringLiteral([Strings_1.stringEscape(json)])]),
974
+ ")"
975
+ ]), ";");
976
+ return;
977
+ }
978
+ if (p.isOptional || t instanceof Type_1.UnionType) {
979
+ const [nullOrOptional, typeSet] = function () {
980
+ if (t instanceof Type_1.UnionType) {
981
+ const [maybeNull, nonNulls] = TypeUtils_1.removeNullFromUnion(t, true);
982
+ return [maybeNull !== null || p.isOptional, nonNulls];
983
+ }
984
+ else {
985
+ let set = new Set();
986
+ set.add(t);
987
+ return [true, set];
988
+ }
989
+ }();
990
+ if (nullOrOptional) {
991
+ cppType = this.cppTypeInOptional(typeSet, {
950
992
  needsForwardIndirection: false,
951
993
  needsOptionalIndirection: false,
952
994
  inJsonNamespace: true
953
995
  }, false, true);
954
- toType = this.cppTypeInOptional(nonNulls, {
996
+ toType = this.cppTypeInOptional(typeSet, {
955
997
  needsForwardIndirection: false,
956
998
  needsOptionalIndirection: false,
957
999
  inJsonNamespace: true
@@ -969,17 +1011,8 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
969
1011
  return;
970
1012
  }
971
1013
  }
972
- if (t.kind === "null" || t.kind === "any") {
973
- this.emitLine(assignment.wrap([], [
974
- ourQualifier,
975
- "get_untyped(j, ",
976
- this._stringType.wrapEncodingChange([ourQualifier], this._stringType.getType(), this.NarrowString.getType(), [this._stringType.createStringLiteral([Strings_1.stringEscape(json)])]),
977
- ")"
978
- ]), ";");
979
- return;
980
- }
981
- cppType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true);
982
- toType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false);
1014
+ cppType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true, p.isOptional);
1015
+ toType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false, p.isOptional);
983
1016
  this.emitLine(assignment.wrap([], this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [
984
1017
  "j.at(",
985
1018
  this._stringType.wrapEncodingChange([ourQualifier], this._stringType.getType(), this.NarrowString.getType(), this._stringType.createStringLiteral([Strings_1.stringEscape(json)])),
@@ -994,8 +1027,8 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
994
1027
  this.emitLine("j = json::object();");
995
1028
  this.forEachClassProperty(c, "none", (name, json, p) => {
996
1029
  const t = p.type;
997
- cppType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false);
998
- toType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true);
1030
+ cppType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false, p.isOptional);
1031
+ toType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true, p.isOptional);
999
1032
  const [getterName, ,] = Support_1.defined(this._gettersAndSettersForPropertyName.get(name));
1000
1033
  let getter;
1001
1034
  if (this._options.codeFormat) {
@@ -1004,7 +1037,21 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1004
1037
  else {
1005
1038
  getter = [name];
1006
1039
  }
1007
- this.emitLine("j[", this._stringType.wrapEncodingChange([ourQualifier], this._stringType.getType(), this.NarrowString.getType(), this._stringType.createStringLiteral([Strings_1.stringEscape(json)])), "] = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, ["x.", getter]), ";");
1040
+ let assignment = [
1041
+ "j[",
1042
+ this._stringType.wrapEncodingChange([ourQualifier], this._stringType.getType(), this.NarrowString.getType(), this._stringType.createStringLiteral([Strings_1.stringEscape(json)])),
1043
+ "] = ",
1044
+ this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, ["x.", getter]),
1045
+ ";"
1046
+ ];
1047
+ if (p.isOptional && this._options.hideNullOptional) {
1048
+ this.emitBlock(["if (", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, ["x.", getter]), ")"], false, () => {
1049
+ this.emitLine(assignment);
1050
+ });
1051
+ }
1052
+ else {
1053
+ this.emitLine(assignment);
1054
+ }
1008
1055
  });
1009
1056
  });
1010
1057
  }
@@ -1056,8 +1103,8 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1056
1103
  continue;
1057
1104
  this.emitLine(onFirst ? "if" : "else if", " (j.", func, "())");
1058
1105
  this.indent(() => {
1059
- const cppType = this.cppType(typeForKind, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true);
1060
- let toType = this.cppType(typeForKind, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false);
1106
+ const cppType = this.cppType(typeForKind, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true, false);
1107
+ let toType = this.cppType(typeForKind, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false, false);
1061
1108
  this.emitLine("x = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [
1062
1109
  "j.get<",
1063
1110
  cppType,
@@ -1079,12 +1126,12 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1079
1126
  needsForwardIndirection: true,
1080
1127
  needsOptionalIndirection: true,
1081
1128
  inJsonNamespace: true
1082
- }, false, false);
1129
+ }, false, false, false);
1083
1130
  const toType = this.cppType(t, {
1084
1131
  needsForwardIndirection: true,
1085
1132
  needsOptionalIndirection: true,
1086
1133
  inJsonNamespace: true
1087
- }, false, true);
1134
+ }, false, true, false);
1088
1135
  this.emitLine("j = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [
1089
1136
  this._options.boost ? "boost::get<" : "std::get<",
1090
1137
  cppType,
@@ -1143,7 +1190,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1143
1190
  });
1144
1191
  }
1145
1192
  emitTopLevelTypedef(t, name) {
1146
- this.emitLine("using ", name, " = ", this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: false }, true, false), ";");
1193
+ this.emitLine("using ", name, " = ", this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: false }, true, false, false), ";");
1147
1194
  }
1148
1195
  emitAllUnionFunctions() {
1149
1196
  this.forEachUniqueUnion("interposing", u => this.sourcelikeToString(this.cppTypeInOptional(TypeUtils_1.removeNullFromUnion(u, true)[1], { needsForwardIndirection: false, needsOptionalIndirection: false, inJsonNamespace: true }, false, false)), (u) => this.emitUnionFunctions(u));
@@ -1259,7 +1306,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1259
1306
  this.ensureBlankLine();
1260
1307
  }
1261
1308
  const checkConst = this.lookupGlobalName(GlobalNames.CheckConstraint);
1262
- this.emitBlock(["void ", checkConst, "(", this._stringType.getConstType(), " name, ", this.withConst(classConstraint), " & c, int64_t value)"], false, () => {
1309
+ this.emitBlock(["inline void ", checkConst, "(", this._stringType.getConstType(), " name, ", this.withConst(classConstraint), " & c, int64_t value)"], false, () => {
1263
1310
  this.emitBlock(["if (c.", getterMinValue, "() != ", this._nulloptType, " && value < *c.", getterMinValue, "())"], false, () => {
1264
1311
  this.emitLine("throw ", this.lookupGlobalName(GlobalNames.ValueTooLowException), " (", this._stringType.createStringLiteral(["Value too low for "]), " + name + ", this._stringType.createStringLiteral([" ("]), " + ", this._stringType.wrapToString(["value"]), " + ", this._stringType.createStringLiteral(["<"]), " + ", this._stringType.wrapToString(["*c.", getterMinValue, "()"]), " + ", this._stringType.createStringLiteral([")"]), ");");
1265
1312
  });
@@ -1270,7 +1317,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1270
1317
  this.ensureBlankLine();
1271
1318
  });
1272
1319
  this.ensureBlankLine();
1273
- this.emitBlock(["void ", checkConst, "(", this._stringType.getConstType(), " name, ", this.withConst(classConstraint), " & c, ", this._stringType.getConstType(), " value)"], false, () => {
1320
+ this.emitBlock(["inline void ", checkConst, "(", this._stringType.getConstType(), " name, ", this.withConst(classConstraint), " & c, ", this._stringType.getConstType(), " value)"], false, () => {
1274
1321
  this.emitBlock(["if (c.", getterMinLength, "() != ", this._nulloptType, " && value.length() < *c.", getterMinLength, "())"], false, () => {
1275
1322
  this.emitLine("throw ", this.lookupGlobalName(GlobalNames.ValueTooShortException), " (", this._stringType.createStringLiteral(["Value too short for "]), " + name + ", this._stringType.createStringLiteral([" ("]), " + ", this._stringType.wrapToString(["value.length()"]), " + ", this._stringType.createStringLiteral(["<"]), " + ", this._stringType.wrapToString(["*c.", getterMinLength, "()"]), " + ", this._stringType.createStringLiteral([")"]), ");");
1276
1323
  });
@@ -1311,7 +1358,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1311
1358
  this.emitLine("return get_untyped(j, property.data());");
1312
1359
  });
1313
1360
  this.ensureBlankLine();
1314
- if (this.haveUnions) {
1361
+ if (this.haveUnions || this.haveOptionalProperties) {
1315
1362
  this.emitLine("template <typename T>");
1316
1363
  this.emitBlock(["inline ", optionalType, "<T> get_optional(", this.withConst("json"), " & j, ", this.withConst("char"), " * property)"], false, () => {
1317
1364
  this.emitBlock(["if (j.find(property) != j.end())"], false, () => {
@@ -1359,7 +1406,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1359
1406
  this.ensureBlankLine();
1360
1407
  this.emitHelperFunctions();
1361
1408
  });
1362
- if (this.haveUnions) {
1409
+ if (this.haveUnions || this.haveOptionalProperties) {
1363
1410
  this.ensureBlankLine();
1364
1411
  this.emitOptionalHelpers();
1365
1412
  }
@@ -1415,7 +1462,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1415
1462
  this.emitTypes();
1416
1463
  }
1417
1464
  else {
1418
- if (!this._options.justTypes && this.haveNamedTypes && this.haveUnions) {
1465
+ if (!this._options.justTypes && this.haveNamedTypes && (this.haveUnions || this.haveOptionalProperties)) {
1419
1466
  this.emitOptionalHelpers();
1420
1467
  this.ensureBlankLine();
1421
1468
  }
@@ -1611,7 +1658,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1611
1658
  needsForwardIndirection: false,
1612
1659
  needsOptionalIndirection: false,
1613
1660
  inJsonNamespace: false
1614
- }, true, false))
1661
+ }, true, false, false))
1615
1662
  ]);
1616
1663
  }
1617
1664
  return null;
@@ -1626,8 +1673,8 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1626
1673
  }
1627
1674
  }
1628
1675
  isConversionRequired(t) {
1629
- let originalType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false);
1630
- let newType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true);
1676
+ let originalType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, false, false);
1677
+ let newType = this.cppType(t, { needsForwardIndirection: true, needsOptionalIndirection: true, inJsonNamespace: true }, false, true, false);
1631
1678
  return originalType !== newType;
1632
1679
  }
1633
1680
  }
@@ -23,6 +23,7 @@ export declare const cSharpOptions: {
23
23
  dense: EnumOption<boolean>;
24
24
  namespace: StringOption;
25
25
  version: EnumOption<Version>;
26
+ virtual: BooleanOption;
26
27
  typeForAny: EnumOption<CSharpTypeForAny>;
27
28
  useDecimal: EnumOption<boolean>;
28
29
  };
@@ -76,6 +77,7 @@ export declare const newtonsoftCSharpOptions: {
76
77
  dense: EnumOption<boolean>;
77
78
  namespace: StringOption;
78
79
  version: EnumOption<Version>;
80
+ virtual: BooleanOption;
79
81
  typeForAny: EnumOption<CSharpTypeForAny>;
80
82
  useDecimal: EnumOption<boolean>;
81
83
  } & {
@@ -87,6 +87,7 @@ exports.cSharpOptions = {
87
87
  ["5", 5],
88
88
  ["6", 6],
89
89
  ], "6", "secondary"),
90
+ virtual: new RendererOptions_1.BooleanOption("virtual", "Generate virtual properties", false),
90
91
  typeForAny: new RendererOptions_1.EnumOption("any-type", 'Type to use for "any"', [
91
92
  ["object", "object"],
92
93
  ["dynamic", "dynamic"],
@@ -105,6 +106,7 @@ class CSharpTargetLanguage extends TargetLanguage_1.TargetLanguage {
105
106
  exports.cSharpOptions.useList,
106
107
  exports.cSharpOptions.useDecimal,
107
108
  exports.cSharpOptions.typeForAny,
109
+ exports.cSharpOptions.virtual,
108
110
  ];
109
111
  }
110
112
  get stringTypeMapping() {
@@ -222,12 +224,12 @@ class CSharpRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
222
224
  return TypeUtils_1.matchType(actualType, (_anyType) => Source_1.maybeAnnotated(withIssues, Annotation_1.anyTypeIssueAnnotation, this._csOptions.typeForAny), (_nullType) => Source_1.maybeAnnotated(withIssues, Annotation_1.nullTypeIssueAnnotation, this._csOptions.typeForAny), (_boolType) => "bool", (_integerType) => "long", (_doubleType) => this.doubleType, (_stringType) => "string", (arrayType) => {
223
225
  const itemsType = this.csType(arrayType.items, follow, withIssues);
224
226
  if (this._csOptions.useList) {
225
- return ["List<", itemsType, ">"];
227
+ return ["System.Collections.Generic.List<", itemsType, ">"];
226
228
  }
227
229
  else {
228
230
  return [itemsType, "[]"];
229
231
  }
230
- }, (classType) => this.nameForNamedType(classType), (mapType) => ["Dictionary<string, ", this.csType(mapType.values, follow, withIssues), ">"], (enumType) => this.nameForNamedType(enumType), (unionType) => {
232
+ }, (classType) => this.nameForNamedType(classType), (mapType) => ["System.Collections.Generic.Dictionary<string, ", this.csType(mapType.values, follow, withIssues), ">"], (enumType) => this.nameForNamedType(enumType), (unionType) => {
231
233
  const nullable = TypeUtils_1.nullableFromUnion(unionType);
232
234
  if (nullable !== null)
233
235
  return this.nullableCSType(nullable, noFollow);
@@ -275,7 +277,10 @@ class CSharpRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
275
277
  const csType = property.isOptional
276
278
  ? this.nullableCSType(t, Transformers_1.followTargetType, true)
277
279
  : this.csType(t, Transformers_1.followTargetType, true);
278
- return ["public ", csType, " ", name, " { get; set; }"];
280
+ const propertyArray = ["public "];
281
+ if (this._csOptions.virtual)
282
+ propertyArray.push("virtual ");
283
+ return [...propertyArray, csType, " ", name, " { get; set; }"];
279
284
  }
280
285
  emitDescriptionBlock(lines) {
281
286
  const start = "/// <summary>";
@@ -471,6 +476,7 @@ class NewtonsoftCSharpTargetLanguage extends CSharpTargetLanguage {
471
476
  exports.newtonsoftCSharpOptions.checkRequired,
472
477
  exports.newtonsoftCSharpOptions.typeForAny,
473
478
  exports.newtonsoftCSharpOptions.baseclass,
479
+ exports.newtonsoftCSharpOptions.virtual,
474
480
  ];
475
481
  }
476
482
  makeRenderer(renderContext, untypedOptionValues) {
@@ -4,7 +4,7 @@ import { StringTypeMapping } from "../TypeBuilder";
4
4
  import { Name, Namer, DependencyName } from "../Naming";
5
5
  import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer";
6
6
  import { TargetLanguage } from "../TargetLanguage";
7
- import { Option, BooleanOption, OptionValues } from "../RendererOptions";
7
+ import { Option, BooleanOption, OptionValues, StringOption } from "../RendererOptions";
8
8
  import { RenderContext } from "../Renderer";
9
9
  export declare const dartOptions: {
10
10
  justTypes: BooleanOption;
@@ -13,6 +13,9 @@ export declare const dartOptions: {
13
13
  requiredProperties: BooleanOption;
14
14
  finalProperties: BooleanOption;
15
15
  generateCopyWith: BooleanOption;
16
+ useFreezed: BooleanOption;
17
+ useHive: BooleanOption;
18
+ partName: StringOption;
16
19
  };
17
20
  export declare class DartTargetLanguage extends TargetLanguage {
18
21
  constructor();
@@ -27,6 +30,8 @@ export declare class DartRenderer extends ConvenienceRenderer {
27
30
  private readonly _options;
28
31
  private readonly _gettersAndSettersForPropertyName;
29
32
  private _needEnumValues;
33
+ private classCounter;
34
+ private classPropertyCounter;
30
35
  private readonly _topLevelDependents;
31
36
  private readonly _enumValues;
32
37
  constructor(targetLanguage: TargetLanguage, renderContext: RenderContext, _options: OptionValues<typeof dartOptions>);
@@ -53,6 +58,7 @@ export declare class DartRenderer extends ConvenienceRenderer {
53
58
  protected fromDynamicExpression(t: Type, ...dynamic: Sourcelike[]): Sourcelike;
54
59
  protected toDynamicExpression(t: Type, ...dynamic: Sourcelike[]): Sourcelike;
55
60
  protected emitClassDefinition(c: ClassType, className: Name): void;
61
+ protected emitFreezedClassDefinition(c: ClassType, className: Name): void;
56
62
  protected emitEnumDefinition(e: EnumType, enumName: Name): void;
57
63
  protected emitEnumValues(): void;
58
64
  protected emitSourceStructure(): void;
@@ -17,7 +17,10 @@ exports.dartOptions = {
17
17
  methodNamesWithMap: new RendererOptions_1.BooleanOption("from-map", "Use method names fromMap() & toMap()", false),
18
18
  requiredProperties: new RendererOptions_1.BooleanOption("required-props", "Make all properties required", false),
19
19
  finalProperties: new RendererOptions_1.BooleanOption("final-props", "Make all properties final", false),
20
- generateCopyWith: new RendererOptions_1.BooleanOption("copy-with", "Generate CopyWith method", false)
20
+ generateCopyWith: new RendererOptions_1.BooleanOption("copy-with", "Generate CopyWith method", false),
21
+ useFreezed: new RendererOptions_1.BooleanOption("use-freezed", "Generate class definitions with @freezed compatibility", false),
22
+ useHive: new RendererOptions_1.BooleanOption("use-hive", "Generate annotations for Hive type adapters", false),
23
+ partName: new RendererOptions_1.StringOption("part-name", "Use this name in `part` directive", "NAME", "")
21
24
  };
22
25
  class DartTargetLanguage extends TargetLanguage_1.TargetLanguage {
23
26
  constructor() {
@@ -30,7 +33,10 @@ class DartTargetLanguage extends TargetLanguage_1.TargetLanguage {
30
33
  exports.dartOptions.methodNamesWithMap,
31
34
  exports.dartOptions.requiredProperties,
32
35
  exports.dartOptions.finalProperties,
33
- exports.dartOptions.generateCopyWith
36
+ exports.dartOptions.generateCopyWith,
37
+ exports.dartOptions.useFreezed,
38
+ exports.dartOptions.useHive,
39
+ exports.dartOptions.partName
34
40
  ];
35
41
  }
36
42
  get supportsUnionsWithBothNumberTypes() {
@@ -154,6 +160,8 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
154
160
  this._options = _options;
155
161
  this._gettersAndSettersForPropertyName = new Map();
156
162
  this._needEnumValues = false;
163
+ this.classCounter = 0;
164
+ this.classPropertyCounter = 0;
157
165
  this._topLevelDependents = new Map();
158
166
  this._enumValues = new Map();
159
167
  }
@@ -229,7 +237,25 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
229
237
  if (this._options.requiredProperties) {
230
238
  this.emitLine("import 'package:meta/meta.dart';");
231
239
  }
240
+ if (this._options.useFreezed) {
241
+ this.emitLine("import 'package:freezed_annotation/freezed_annotation.dart';");
242
+ }
243
+ if (this._options.useHive) {
244
+ this.emitLine("import 'package:hive/hive.dart';");
245
+ }
232
246
  this.emitLine("import 'dart:convert';");
247
+ if (this._options.useFreezed || this._options.useHive) {
248
+ this.ensureBlankLine();
249
+ const optionNameIsEmpty = this._options.partName.length === 0;
250
+ // FIXME: This should use a `Name`, not `modifySource`
251
+ const name = Source_1.modifySource(Strings_1.snakeCase, optionNameIsEmpty ? [...this.topLevels.keys()][0] : this._options.partName);
252
+ if (this._options.useFreezed) {
253
+ this.emitLine("part '", name, ".freezed.dart';");
254
+ }
255
+ if (!this._options.justTypes) {
256
+ this.emitLine("part '", name, ".g.dart';");
257
+ }
258
+ }
233
259
  }
234
260
  emitDescriptionBlock(lines) {
235
261
  this.emitCommentLines(lines, " * ", "/**", " */");
@@ -310,6 +336,11 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
310
336
  }
311
337
  emitClassDefinition(c, className) {
312
338
  this.emitDescription(this.descriptionForType(c));
339
+ if (this._options.useHive) {
340
+ this.classCounter++;
341
+ this.emitLine(`@HiveType(typeId: ${this.classCounter})`);
342
+ this.classPropertyCounter = 0;
343
+ }
313
344
  this.emitBlock(["class ", className], () => {
314
345
  if (c.getProperties().size === 0) {
315
346
  this.emitLine(className, "();");
@@ -323,7 +354,15 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
323
354
  });
324
355
  this.emitLine("});");
325
356
  this.ensureBlankLine();
326
- this.forEachClassProperty(c, "none", (name, _, p) => {
357
+ this.forEachClassProperty(c, "none", (name, jsonName, p) => {
358
+ const description = this.descriptionForClassProperty(c, jsonName);
359
+ if (description !== undefined) {
360
+ this.emitDescription(description);
361
+ }
362
+ if (this._options.useHive) {
363
+ this.classPropertyCounter++;
364
+ this.emitLine(`@HiveField(${this.classPropertyCounter})`);
365
+ }
327
366
  this.emitLine(this._options.finalProperties ? "final " : "", this.dartType(p.type, true), " ", name, ";");
328
367
  });
329
368
  }
@@ -372,6 +411,30 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
372
411
  this.emitLine("};");
373
412
  });
374
413
  }
414
+ emitFreezedClassDefinition(c, className) {
415
+ this.emitDescription(this.descriptionForType(c));
416
+ this.emitLine("@freezed");
417
+ this.emitBlock(["class ", className, " with _$", className], () => {
418
+ if (c.getProperties().size === 0) {
419
+ this.emitLine("const factory ", className, "() = _", className, ";");
420
+ }
421
+ else {
422
+ this.emitLine("const factory ", className, "({");
423
+ this.indent(() => {
424
+ this.forEachClassProperty(c, "none", (name, _, _p) => {
425
+ this.emitLine(this._options.requiredProperties ? "required " : "", this.dartType(_p.type, true), this._options.requiredProperties ? "" : "?", " ", name, ",");
426
+ });
427
+ });
428
+ this.emitLine("}) = _", className, ";");
429
+ }
430
+ if (this._options.justTypes)
431
+ return;
432
+ this.ensureBlankLine();
433
+ this.emitLine(
434
+ // factory PublicAnswer.fromJson(Map<String, dynamic> json) => _$PublicAnswerFromJson(json);
435
+ "factory ", className, ".fromJson(Map<String, dynamic> json) => ", "_$", className, "FromJson(json);");
436
+ });
437
+ }
375
438
  emitEnumDefinition(e, enumName) {
376
439
  const caseNames = Array.from(e.cases).map(c => this.nameForEnumCase(e, c));
377
440
  this.emitDescription(this.descriptionForType(e));
@@ -418,7 +481,7 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
418
481
  // });
419
482
  });
420
483
  }
421
- this.forEachNamedType("leading-and-interposing", (c, n) => this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), (_e, _n) => {
484
+ this.forEachNamedType("leading-and-interposing", (c, n) => this._options.useFreezed ? this.emitFreezedClassDefinition(c, n) : this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), (_e, _n) => {
422
485
  // We don't support this yet.
423
486
  });
424
487
  if (this._needEnumValues) {
@@ -515,7 +515,7 @@ class JavaRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
515
515
  javaTypeWithoutGenerics(reference, t) {
516
516
  if (t instanceof Type_1.ArrayType) {
517
517
  if (this._options.useList) {
518
- return ["List<", this.javaTypeWithoutGenerics(true, t.items), ">"];
518
+ return ["List"];
519
519
  }
520
520
  else {
521
521
  return [this.javaTypeWithoutGenerics(false, t.items), "[]"];
@@ -1055,6 +1055,7 @@ class JacksonRenderer extends JavaRenderer {
1055
1055
  const renderedForClass = this.javaTypeWithoutGenerics(false, topLevelType);
1056
1056
  this.emitLine("ObjectMapper mapper = new ObjectMapper();");
1057
1057
  this.emitLine("mapper.findAndRegisterModules();");
1058
+ this.emitLine("mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);");
1058
1059
  this.emitLine("mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);");
1059
1060
  this.emitOffsetDateTimeConverterModule();
1060
1061
  this.emitLine(readerName, " = mapper.readerFor(", renderedForClass, ".class);");
@@ -17,7 +17,7 @@ exports.javaScriptOptions = {
17
17
  runtimeTypecheck: new RendererOptions_1.BooleanOption("runtime-typecheck", "Verify JSON.parse results at runtime", true),
18
18
  runtimeTypecheckIgnoreUnknownProperties: new RendererOptions_1.BooleanOption("runtime-typecheck-ignore-unknown-properties", "Ignore unknown properties when verifying at runtime", false, "secondary"),
19
19
  converters: Converters_1.convertersOption(),
20
- rawType: new RendererOptions_1.EnumOption("raw-type", "Type to raw input (json by default)", [
20
+ rawType: new RendererOptions_1.EnumOption("raw-type", "Type of raw input (json by default)", [
21
21
  ["json", "json"],
22
22
  ["any", "any"]
23
23
  ], "json", "secondary")
@@ -38,7 +38,7 @@ export declare class KotlinRenderer extends ConvenienceRenderer {
38
38
  protected makeEnumCaseNamer(): Namer;
39
39
  protected emitDescriptionBlock(lines: Sourcelike[]): void;
40
40
  protected emitBlock(line: Sourcelike, f: () => void, delimiter?: "curly" | "paren" | "lambda"): void;
41
- protected anyType(withIssues?: boolean, noOptional?: boolean): Sourcelike;
41
+ protected anySourceType(optional: string): Sourcelike;
42
42
  protected arrayType(arrayType: ArrayType, withIssues?: boolean, _noOptional?: boolean): Sourcelike;
43
43
  protected mapType(mapType: MapType, withIssues?: boolean, _noOptional?: boolean): Sourcelike;
44
44
  protected kotlinType(t: Type, withIssues?: boolean, noOptional?: boolean): Sourcelike;
@@ -47,12 +47,12 @@ export declare class KotlinRenderer extends ConvenienceRenderer {
47
47
  protected emitTopLevelArray(t: ArrayType, name: Name): void;
48
48
  protected emitTopLevelMap(t: MapType, name: Name): void;
49
49
  protected emitEmptyClassDefinition(c: ClassType, className: Name): void;
50
- private emitClassDefinition;
50
+ protected emitClassDefinition(c: ClassType, className: Name): void;
51
51
  protected emitClassDefinitionMethods(_c: ClassType, _className: Name): void;
52
- protected emitClassAnnotations(_c: ClassType, _className: Name): void;
52
+ protected emitClassAnnotations(_c: Type, _className: Name): void;
53
53
  protected renameAttribute(_name: Name, _jsonName: string, _required: boolean, _meta: Array<() => void>): void;
54
54
  protected emitEnumDefinition(e: EnumType, enumName: Name): void;
55
- private emitUnionDefinition;
55
+ protected emitUnionDefinition(u: UnionType, unionName: Name): void;
56
56
  protected emitUnionDefinitionMethods(_u: UnionType, _nonNulls: ReadonlySet<Type>, _maybeNull: PrimitiveType | null, _unionName: Name): void;
57
57
  protected emitSourceStructure(): void;
58
58
  }
@@ -93,14 +93,14 @@ export declare class KotlinJacksonRenderer extends KotlinRenderer {
93
93
  */
94
94
  export declare class KotlinXRenderer extends KotlinRenderer {
95
95
  constructor(targetLanguage: TargetLanguage, renderContext: RenderContext, _kotlinOptions: OptionValues<typeof kotlinOptions>);
96
- protected anyType(_withIssues?: boolean, _noOptional?: boolean): Sourcelike;
96
+ protected anySourceType(optional: string): Sourcelike;
97
97
  protected arrayType(arrayType: ArrayType, withIssues?: boolean, noOptional?: boolean): Sourcelike;
98
98
  protected mapType(mapType: MapType, withIssues?: boolean, noOptional?: boolean): Sourcelike;
99
99
  protected emitTopLevelMap(t: MapType, name: Name): void;
100
100
  protected emitTopLevelArray(t: ArrayType, name: Name): void;
101
101
  protected emitUsageHeader(): void;
102
102
  protected emitHeader(): void;
103
- protected emitClassAnnotations(_c: ClassType, _className: Name): void;
103
+ protected emitClassAnnotations(_c: Type, _className: Name): void;
104
104
  protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>): void;
105
105
  private _rename;
106
106
  protected emitEnumDefinition(e: EnumType, enumName: Name): void;
@@ -165,12 +165,11 @@ class KotlinRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
165
165
  this.indent(f);
166
166
  this.emitLine(close);
167
167
  }
168
- // (asarazan): I've broken out the following three functions
169
- // because some renderers, such as kotlinx, can cope with `any`, while some get mad.
170
- anyType(withIssues = false, noOptional = false) {
171
- const optional = noOptional ? "" : "?";
172
- return Source_1.maybeAnnotated(withIssues, Annotation_1.anyTypeIssueAnnotation, ["Any", optional]);
168
+ anySourceType(optional) {
169
+ return ["Any", optional];
173
170
  }
171
+ // (asarazan): I've broken out the following two functions
172
+ // because some renderers, such as kotlinx, can cope with `any`, while some get mad.
174
173
  arrayType(arrayType, withIssues = false, _noOptional = false) {
175
174
  return ["List<", this.kotlinType(arrayType.items, withIssues), ">"];
176
175
  }
@@ -179,8 +178,10 @@ class KotlinRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
179
178
  }
180
179
  kotlinType(t, withIssues = false, noOptional = false) {
181
180
  const optional = noOptional ? "" : "?";
182
- return TypeUtils_1.matchType(t, _anyType => this.anyType(withIssues, noOptional), _nullType => {
183
- return Source_1.maybeAnnotated(withIssues, Annotation_1.nullTypeIssueAnnotation, ["Any", optional]);
181
+ return TypeUtils_1.matchType(t, _anyType => {
182
+ return Source_1.maybeAnnotated(withIssues, Annotation_1.anyTypeIssueAnnotation, this.anySourceType(optional));
183
+ }, _nullType => {
184
+ return Source_1.maybeAnnotated(withIssues, Annotation_1.nullTypeIssueAnnotation, this.anySourceType(optional));
184
185
  }, _boolType => "Boolean", _integerType => "Long", _doubleType => "Double", _stringType => "String", arrayType => this.arrayType(arrayType, withIssues), classType => this.nameForNamedType(classType), mapType => this.mapType(mapType, withIssues), enumType => this.nameForNamedType(enumType), unionType => {
185
186
  const nullable = TypeUtils_1.nullableFromUnion(unionType);
186
187
  if (nullable !== null)
@@ -212,6 +213,7 @@ class KotlinRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
212
213
  }
213
214
  emitEmptyClassDefinition(c, className) {
214
215
  this.emitDescription(this.descriptionForType(c));
216
+ this.emitClassAnnotations(c, className);
215
217
  this.emitLine("class ", className, "()");
216
218
  }
217
219
  emitClassDefinition(c, className) {
@@ -285,6 +287,7 @@ class KotlinRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
285
287
  }
286
288
  this.emitDescription(this.descriptionForType(u));
287
289
  const [maybeNull, nonNulls] = TypeUtils_1.removeNullFromUnion(u, sortBy);
290
+ this.emitClassAnnotations(u, unionName);
288
291
  this.emitBlock(["sealed class ", unionName], () => {
289
292
  {
290
293
  let table = [];
@@ -731,8 +734,8 @@ class KotlinXRenderer extends KotlinRenderer {
731
734
  constructor(targetLanguage, renderContext, _kotlinOptions) {
732
735
  super(targetLanguage, renderContext, _kotlinOptions);
733
736
  }
734
- anyType(_withIssues = false, _noOptional = false) {
735
- return "JsonObject";
737
+ anySourceType(optional) {
738
+ return ["JsonObject", optional];
736
739
  }
737
740
  arrayType(arrayType, withIssues = false, noOptional = false) {
738
741
  const valType = this.kotlinType(arrayType.items, withIssues, true);
@@ -767,7 +770,7 @@ class KotlinXRenderer extends KotlinRenderer {
767
770
  this.emitLine("// To parse the JSON, install kotlin's serialization plugin and do:");
768
771
  this.emitLine("//");
769
772
  const table = [];
770
- table.push(["// val ", "json", " = Json(JsonConfiguration.Stable)"]);
773
+ table.push(["// val ", "json", " = Json { allowStructuredMapKeys = true }"]);
771
774
  this.forEachTopLevel("none", (_, name) => {
772
775
  table.push(["// val ", Source_1.modifySource(Strings_1.camelCase, name), ` = json.parse(${this.sourcelikeToString(name)}.serializer(), jsonString)`]);
773
776
  });
@@ -777,7 +780,8 @@ class KotlinXRenderer extends KotlinRenderer {
777
780
  super.emitHeader();
778
781
  this.emitLine("import kotlinx.serialization.*");
779
782
  this.emitLine("import kotlinx.serialization.json.*");
780
- this.emitLine("import kotlinx.serialization.internal.*");
783
+ this.emitLine("import kotlinx.serialization.descriptors.*");
784
+ this.emitLine("import kotlinx.serialization.encoding.*");
781
785
  }
782
786
  emitClassAnnotations(_c, _className) {
783
787
  this.emitLine("@Serializable");
@@ -807,7 +811,7 @@ class KotlinXRenderer extends KotlinRenderer {
807
811
  this.ensureBlankLine();
808
812
  this.emitBlock(["companion object : KSerializer<", enumName, ">"], () => {
809
813
  this.emitBlock("override val descriptor: SerialDescriptor get()", () => {
810
- this.emitLine("return PrimitiveDescriptor(\"", this._kotlinOptions.packageName, ".", enumName, "\", PrimitiveKind.STRING)");
814
+ this.emitLine("return PrimitiveSerialDescriptor(\"", this._kotlinOptions.packageName, ".", enumName, "\", PrimitiveKind.STRING)");
811
815
  });
812
816
  this.emitBlock(["override fun deserialize(decoder: Decoder): ", enumName, " = when (val value = decoder.decodeString())"], () => {
813
817
  let table = [];
@@ -621,7 +621,7 @@ class SwiftRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
621
621
  this.emitLineOnce("// let ", Source_1.modifySource(Strings_1.camelCase, topLevelName), " = try ", topLevelName, "(json)");
622
622
  }
623
623
  else {
624
- this.emitLineOnce("// let ", Source_1.modifySource(Strings_1.camelCase, topLevelName), " = ", "try? newJSONDecoder().decode(", topLevelName, ".self, from: jsonData)");
624
+ this.emitLineOnce("// let ", Source_1.modifySource(Strings_1.camelCase, topLevelName), " = ", "try? JSONDecoder().decode(", topLevelName, ".self, from: jsonData)");
625
625
  }
626
626
  });
627
627
  }
@@ -15,6 +15,7 @@ export declare const tsFlowOptions: {
15
15
  justTypes: BooleanOption;
16
16
  nicePropertyNames: BooleanOption;
17
17
  declareUnions: BooleanOption;
18
+ preferUnions: BooleanOption;
18
19
  };
19
20
  export declare abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetLanguage {
20
21
  protected getOptions(): Option<any>[];
@@ -12,7 +12,8 @@ const JavaScriptUnicodeMaps_1 = require("./JavaScriptUnicodeMaps");
12
12
  exports.tsFlowOptions = Object.assign({}, JavaScript_1.javaScriptOptions, {
13
13
  justTypes: new RendererOptions_1.BooleanOption("just-types", "Interfaces only", false),
14
14
  nicePropertyNames: new RendererOptions_1.BooleanOption("nice-property-names", "Transform property names to be JavaScripty", false),
15
- declareUnions: new RendererOptions_1.BooleanOption("explicit-unions", "Explicitly name unions", false)
15
+ declareUnions: new RendererOptions_1.BooleanOption("explicit-unions", "Explicitly name unions", false),
16
+ preferUnions: new RendererOptions_1.BooleanOption("prefer-unions", "Use union type instead of enum", false)
16
17
  });
17
18
  const tsFlowTypeAnnotations = {
18
19
  any: ": any",
@@ -32,7 +33,8 @@ class TypeScriptFlowBaseTargetLanguage extends JavaScript_1.JavaScriptTargetLang
32
33
  exports.tsFlowOptions.runtimeTypecheckIgnoreUnknownProperties,
33
34
  exports.tsFlowOptions.acronymStyle,
34
35
  exports.tsFlowOptions.converters,
35
- exports.tsFlowOptions.rawType
36
+ exports.tsFlowOptions.rawType,
37
+ exports.tsFlowOptions.preferUnions
36
38
  ];
37
39
  }
38
40
  get supportsOptionalClassProperties() {
@@ -207,11 +209,24 @@ class TypeScriptRenderer extends TypeScriptFlowBaseRenderer {
207
209
  }
208
210
  emitEnum(e, enumName) {
209
211
  this.emitDescription(this.descriptionForType(e));
210
- this.emitBlock(["export enum ", enumName, " "], "", () => {
211
- this.forEachEnumCase(e, "none", (name, jsonName) => {
212
- this.emitLine(name, ` = "${Strings_1.utf16StringEscape(jsonName)}",`);
212
+ if (this._tsFlowOptions.preferUnions) {
213
+ let items = "";
214
+ e.cases.forEach((item) => {
215
+ if (items === "") {
216
+ items += `"${Strings_1.utf16StringEscape(item)}"`;
217
+ return;
218
+ }
219
+ items += ` | "${Strings_1.utf16StringEscape(item)}"`;
213
220
  });
214
- });
221
+ this.emitLine("export type ", enumName, " = ", items, ";");
222
+ }
223
+ else {
224
+ this.emitBlock(["export enum ", enumName, " "], "", () => {
225
+ this.forEachEnumCase(e, "none", (name, jsonName) => {
226
+ this.emitLine(name, ` = "${Strings_1.utf16StringEscape(jsonName)}",`);
227
+ });
228
+ });
229
+ }
215
230
  }
216
231
  emitClassBlock(c, className) {
217
232
  this.emitBlock(["export interface ", className, " "], "", () => {
@@ -13,10 +13,6 @@ const Strings_1 = require("../../support/Strings");
13
13
  function unicodeEscape(codePoint) {
14
14
  return "\\u{" + Strings_1.intToHex(codePoint, 0) + "}";
15
15
  }
16
- function snakeCase(str) {
17
- const words = Strings_1.splitIntoWords(str).map(({ word }) => word.toLowerCase());
18
- return words.join("_");
19
- }
20
16
  const stringEscape = Strings_1.utf32ConcatMap(Strings_1.escapeNonPrintableMapper(Strings_1.isPrintable, unicodeEscape));
21
17
  var Strictness;
22
18
  (function (Strictness) {
@@ -284,11 +280,17 @@ class RubyRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
284
280
  : // This will raise a runtime error if the key is not found in the hash
285
281
  `d.fetch("${stringEscape(jsonName)}")`;
286
282
  if (this.propertyTypeMarshalsImplicitlyFromDynamic(p.type)) {
287
- inits.push([[name, ": "], [dynamic, ","]]);
283
+ inits.push([
284
+ [name, ": "],
285
+ [dynamic, ","]
286
+ ]);
288
287
  }
289
288
  else {
290
289
  const expression = this.fromDynamic(p.type, dynamic, p.isOptional);
291
- inits.push([[name, ": "], [expression, ","]]);
290
+ inits.push([
291
+ [name, ": "],
292
+ [expression, ","]
293
+ ]);
292
294
  }
293
295
  });
294
296
  this.emitTable(inits);
@@ -452,7 +454,7 @@ class RubyRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
452
454
  this.emitLine("# To parse this JSON, add 'dry-struct' and 'dry-types' gems, then do:");
453
455
  this.emitLine("#");
454
456
  this.forEachTopLevel("none", (topLevel, name) => {
455
- const variable = Source_1.modifySource(snakeCase, name);
457
+ const variable = Source_1.modifySource(Strings_1.snakeCase, name);
456
458
  this.emitLine("# ", variable, " = ", name, ".from_json! ", this.jsonSample(topLevel));
457
459
  this.emitLine("# puts ", this.exampleUse(topLevel, variable));
458
460
  this.emitLine("#");
@@ -474,7 +476,7 @@ class RubyRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
474
476
  this.forEachNamedType("leading-and-interposing", (c, n) => this.emitClass(c, n), (e, n) => this.emitEnum(e, n), (u, n) => this.emitUnion(u, n));
475
477
  if (!this._options.justTypes) {
476
478
  this.forEachTopLevel("leading-and-interposing", (topLevel, name) => {
477
- const self = Source_1.modifySource(snakeCase, name);
479
+ const self = Source_1.modifySource(Strings_1.snakeCase, name);
478
480
  // The json gem defines to_json on maps and primitives, so we only need to supply
479
481
  // it for arrays.
480
482
  const needsToJsonDefined = "array" === topLevel.kind;
@@ -24,6 +24,7 @@ export declare function capitalize(str: string): string;
24
24
  export declare function decapitalize(str: string): string;
25
25
  export declare function pascalCase(str: string): string;
26
26
  export declare function camelCase(str: string): string;
27
+ export declare function snakeCase(str: string): string;
27
28
  export declare function startWithLetter(isAllowedStart: (codePoint: number) => boolean, // FIXME: technically, this operates on UTF16 units
28
29
  upper: boolean, str: string): string;
29
30
  export declare type WordInName = {
@@ -273,6 +273,11 @@ function camelCase(str) {
273
273
  return decapitalize(pascalCase(str));
274
274
  }
275
275
  exports.camelCase = camelCase;
276
+ function snakeCase(str) {
277
+ const words = splitIntoWords(str).map(({ word }) => word.toLowerCase());
278
+ return words.join("_");
279
+ }
280
+ exports.snakeCase = snakeCase;
276
281
  function startWithLetter(isAllowedStart, // FIXME: technically, this operates on UTF16 units
277
282
  upper, str) {
278
283
  const modify = upper ? capitalize : decapitalize;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quicktype",
3
- "version": "15.0.258",
3
+ "version": "15.0.261",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/cli/index.js",
6
6
  "types": "dist/cli/index.d.ts",
@@ -23,9 +23,9 @@
23
23
  "graphql": "^0.11.7",
24
24
  "is-url": "^1.2.4",
25
25
  "js-base64": "^2.4.3",
26
- "lodash": "^4.17.19",
26
+ "lodash": "^4.17.21",
27
27
  "moment": "^2.22.1",
28
- "node-fetch": "^1.7.1",
28
+ "node-fetch": "^2.6.1",
29
29
  "pako": "^1.0.6",
30
30
  "pluralize": "^7.0.0",
31
31
  "stream-json": "1.1.3",
@@ -33,7 +33,7 @@
33
33
  "typescript": "~3.2.1",
34
34
  "@mark.probst/typescript-json-schema": "~0.32.0",
35
35
  "@mark.probst/unicode-properties": "~1.1.0",
36
- "urijs": "^1.19.1",
36
+ "urijs": "^1.19.6",
37
37
  "uuid": "^3.2.1",
38
38
  "wordwrap": "^1.0.0",
39
39
  "yaml": "^1.5.0",