Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2144,8 +2144,14 @@ export class CPlusPlusRenderer extends ConvenienceRenderer {
],
false,
() => {
// A JSON null must become an *empty*
// optional. Only `optType<T>()` guarantees
// that: the factory would wrap a
// default-constructed T (std::make_optional
// and std::make_shared both do), turning
// null into 0/""/{} on round-trip.
this.emitLine(
`if (j.is_null()) return ${factory}<T>(); else return ${factory}<T>(j.get<T>());`,
`if (j.is_null()) return ${optType}<T>(); else return ${factory}<T>(j.get<T>());`,
);
},
);
Expand Down
2 changes: 1 addition & 1 deletion packages/quicktype-core/src/language/CPlusPlus/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export const cPlusPlusOptions = {
boost: new BooleanOption(
"boost",
"Require a dependency on boost. Without boost, C++17 is required",
true,
false,
),
hideNullOptional: new BooleanOption(
"hide-null-optional",
Expand Down
22 changes: 17 additions & 5 deletions packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import { type Sourcelike, maybeAnnotated } from "../../Source.js";
import { assert } from "../../support/Support.js";
import type { TargetLanguage } from "../../TargetLanguage.js";
import { followTargetType } from "../../Transformers.js";
import type {
ClassProperty,
ClassType,
EnumType,
Type,
import {
type ClassProperty,
type ClassType,
type EnumType,
type Type,
UnionType,
} from "../../Type/index.js";
import {
Expand Down Expand Up @@ -187,6 +187,18 @@ export class CSharpRenderer extends ConvenienceRenderer {
withIssues = false,
): Sourcelike {
t = followTargetType(t);
// A nullable union already renders with its own "?" through
// csType's union case; unwrap it so the annotation is applied
// exactly once. Without this, an optional property whose type
// is e.g. `string | null` would render as `string??` at C# 8
// (and a nullable value-type union as `long??` at any version).
if (t instanceof UnionType) {
const nullable = nullableFromUnion(t);
if (nullable !== null) {
t = followTargetType(nullable);
}
}

const csType = this.csType(t, follow, withIssues);
if (isValueType(t) || this._csOptions.version >= 8) {
return [csType, "?"];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,10 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer {

this.emitLine("#pragma warning restore CS8618");
this.emitLine("#pragma warning restore CS8601");
this.emitLine("#pragma warning restore CS8602");
this.emitLine("#pragma warning restore CS8603");
this.emitLine("#pragma warning restore CS8604");
this.emitLine("#pragma warning restore CS8625");
this.emitLine("#pragma warning restore CS8765");
}

Expand Down Expand Up @@ -239,7 +242,13 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer {
this.emitLine("#nullable enable");
this.emitLine("#pragma warning disable CS8618");
this.emitLine("#pragma warning disable CS8601");
// CS8602/CS8604/CS8625: the emitted constraint-check and
// string-transformer helpers dereference and pass around
// Deserialize<T>() results, which are nullable under NRT.
this.emitLine("#pragma warning disable CS8602");
this.emitLine("#pragma warning disable CS8603");
this.emitLine("#pragma warning disable CS8604");
this.emitLine("#pragma warning disable CS8625");
this.emitLine("#pragma warning disable CS8765");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer {

this.emitLine("#pragma warning restore CS8618");
this.emitLine("#pragma warning restore CS8601");
this.emitLine("#pragma warning restore CS8602");
this.emitLine("#pragma warning restore CS8603");
}

Expand Down Expand Up @@ -237,6 +238,9 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer {
this.emitLine("#nullable enable");
this.emitLine("#pragma warning disable CS8618");
this.emitLine("#pragma warning disable CS8601");
// CS8602: the emitted constraint-check converters dereference
// Deserialize<T>() results, which are nullable under NRT.
this.emitLine("#pragma warning disable CS8602");
this.emitLine("#pragma warning disable CS8603");
}

Expand Down
4 changes: 2 additions & 2 deletions packages/quicktype-core/src/language/CSharp/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const cSharpOptions = {
NewtonSoft: "NewtonSoft",
SystemTextJson: "SystemTextJson",
} as const,
"NewtonSoft",
"SystemTextJson",
),
useList: new EnumOption(
"array-type",
Expand Down Expand Up @@ -71,7 +71,7 @@ export const cSharpOptions = {
"6": 6,
"8": 8,
} as const,
"6",
"8",
"secondary",
),
virtual: new BooleanOption("virtual", "Generate virtual properties", false),
Expand Down
45 changes: 11 additions & 34 deletions packages/quicktype-core/src/language/Dart/DartRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,7 @@ export class DartRenderer extends ConvenienceRenderer {
): Sourcelike {
const nullable =
forceNullable ||
(this._options.nullSafety &&
t.isNullable &&
!this._options.requiredProperties);
(t.isNullable && !this._options.requiredProperties);
const withNullable = (s: Sourcelike): Sourcelike =>
nullable ? [s, "?"] : s;
return matchType<Sourcelike>(
Expand Down Expand Up @@ -321,11 +319,7 @@ export class DartRenderer extends ConvenienceRenderer {
list: Sourcelike,
mapper: Sourcelike,
): Sourcelike {
if (
this._options.nullSafety &&
isNullable &&
!this._options.requiredProperties
) {
if (isNullable && !this._options.requiredProperties) {
return [
list,
" == null ? [] : ",
Expand Down Expand Up @@ -356,11 +350,7 @@ export class DartRenderer extends ConvenienceRenderer {
map: Sourcelike,
valueMapper: Sourcelike,
): Sourcelike {
if (
this._options.nullSafety &&
isNullable &&
!this._options.requiredProperties
) {
if (isNullable && !this._options.requiredProperties) {
return [
"Map.from(",
map,
Expand Down Expand Up @@ -388,11 +378,7 @@ export class DartRenderer extends ConvenienceRenderer {
classType: ClassType,
dynamic: Sourcelike,
): Sourcelike {
if (
this._options.nullSafety &&
isNullable &&
!this._options.requiredProperties
) {
if (isNullable && !this._options.requiredProperties) {
return [
dynamic,
" == null ? null : ",
Expand Down Expand Up @@ -431,10 +417,7 @@ export class DartRenderer extends ConvenienceRenderer {
(_nullType) => dynamic, // FIXME: check null
(_boolType) => dynamic,
(_integerType) => dynamic,
(_doubleType) => [
dynamic,
this._options.nullSafety ? "?.toDouble()" : ".toDouble()",
],
(_doubleType) => [dynamic, "?.toDouble()"],
(_stringType) => dynamic,
(arrayType) =>
this.mapList(
Expand Down Expand Up @@ -469,8 +452,7 @@ export class DartRenderer extends ConvenienceRenderer {
defined(this._enumValues.get(enumType)),
".map[",
dynamic,
this._options.nullSafety &&
(!isNullable || this._options.requiredProperties)
!isNullable || this._options.requiredProperties
? "]!"
: "]",
];
Expand All @@ -493,8 +475,7 @@ export class DartRenderer extends ConvenienceRenderer {
case "date":
if (
(transformedStringType.isNullable || isNullable) &&
!this._options.requiredProperties &&
this._options.nullSafety
!this._options.requiredProperties
) {
return [
dynamic,
Expand Down Expand Up @@ -544,7 +525,6 @@ export class DartRenderer extends ConvenienceRenderer {
),
(_classType) => {
if (
this._options.nullSafety &&
(_classType.isNullable || isNullable) &&
!this._options.requiredProperties
) {
Expand Down Expand Up @@ -588,7 +568,6 @@ export class DartRenderer extends ConvenienceRenderer {
switch (transformedStringType.kind) {
case "date-time":
if (
this._options.nullSafety &&
!this._options.requiredProperties &&
(transformedStringType.isNullable || isNullable)
) {
Expand All @@ -598,7 +577,6 @@ export class DartRenderer extends ConvenienceRenderer {
return [dynamic, ".toIso8601String()"];
case "date":
if (
this._options.nullSafety &&
!this._options.requiredProperties &&
(transformedStringType.isNullable || isNullable)
) {
Expand Down Expand Up @@ -642,8 +620,8 @@ export class DartRenderer extends ConvenienceRenderer {
this.forEachClassProperty(c, "none", (name, _, prop) => {
const required =
this._options.requiredProperties ||
(this._options.nullSafety &&
(!prop.type.isNullable || !prop.isOptional));
!prop.type.isNullable ||
!prop.isOptional;
this.emitLine(required ? "required " : "", "this.", name, ",");
});
});
Expand Down Expand Up @@ -869,9 +847,8 @@ export class DartRenderer extends ConvenienceRenderer {

const required =
this._options.requiredProperties ||
(this._options.nullSafety &&
(!prop.type.isNullable ||
!prop.isOptional));
!prop.type.isNullable ||
!prop.isOptional;
if (this._options.useJsonAnnotation) {
this.classPropertyCounter++;
this.emitLine(
Expand Down
3 changes: 1 addition & 2 deletions packages/quicktype-core/src/language/Dart/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import type { LanguageName, RendererOptions } from "../../types.js";
import { DartRenderer } from "./DartRenderer.js";

export const dartOptions = {
nullSafety: new BooleanOption("null-safety", "Null Safety", true),
justTypes: new BooleanOption("just-types", "Types only", false),
codersInClass: new BooleanOption(
"coders-in-class",
Expand All @@ -36,7 +35,7 @@ export const dartOptions = {
finalProperties: new BooleanOption(
"final-props",
"Make all properties final",
false,
true,
),
generateCopyWith: new BooleanOption(
"copy-with",
Expand Down
2 changes: 1 addition & 1 deletion packages/quicktype-core/src/language/Haskell/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const haskellOptions = {
array: false,
list: true,
} as const,
"array",
"list",
),
moduleName: new StringOption(
"module",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,16 @@ export class JacksonRenderer extends JavaRenderer {
const { fieldName } = this.unionField(u, t);
const rendered = this.javaTypeWithoutGenerics(true, t);
if (this._options.useList && t instanceof ArrayType) {
// The TypeReference must carry the full generic type:
// a raw `TypeReference<List>` would make Jackson accept
// any element type, so schema-invalid inputs (which the
// expected-failure fixtures rely on rejecting) would
// deserialize successfully.
this.emitLine(
"value.",
fieldName,
" = jsonParser.readValueAs(new TypeReference<",
rendered,
this.javaType(true, t),
">() {});",
);
} else if (
Expand Down
2 changes: 1 addition & 1 deletion packages/quicktype-core/src/language/Java/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const javaOptions = {
"array-type",
"Use T[] or List<T>",
{ array: false, list: true } as const,
"array",
"list",
),
justTypes: new BooleanOption("just-types", "Plain types only", false),
dateTimeProvider: new EnumOption(
Expand Down
2 changes: 1 addition & 1 deletion packages/quicktype-core/src/language/Kotlin/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const kotlinOptions = {
klaxon: "Klaxon",
kotlinx: "KotlinX",
} as const,
"klaxon",
"jackson",
),
acronymStyle: acronymOption(AcronymStyleOptions.Pascal),
packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"),
Expand Down
6 changes: 1 addition & 5 deletions packages/quicktype-core/src/language/Rust/RustRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,11 +376,7 @@ export class RustRenderer extends ConvenienceRenderer {
}

this.ensureBlankLine();
if (this._options.edition2018) {
this.emitLine("use serde::{Serialize, Deserialize};");
} else {
this.emitLine("extern crate serde_derive;");
}
this.emitLine("use serde::{Serialize, Deserialize};");

if (this.haveMaps) {
this.emitLine("use std::collections::HashMap;");
Expand Down
7 changes: 3 additions & 4 deletions packages/quicktype-core/src/language/Rust/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ export const rustOptions = {
crate: Visibility.Crate,
public: Visibility.Public,
} as const,
"private",
"public",
),
deriveDebug: new BooleanOption("derive-debug", "Derive Debug impl", false),
deriveClone: new BooleanOption("derive-clone", "Derive Clone impl", false),
deriveDebug: new BooleanOption("derive-debug", "Derive Debug impl", true),
deriveClone: new BooleanOption("derive-clone", "Derive Clone impl", true),
derivePartialEq: new BooleanOption(
"derive-partial-eq",
"Derive PartialEq impl",
Expand All @@ -42,7 +42,6 @@ export const rustOptions = {
"Skip serializing empty Option fields",
false,
),
edition2018: new BooleanOption("edition-2018", "Edition 2018", true),
leadingComments: new BooleanOption(
"leading-comments",
"Leading Comments",
Expand Down
7 changes: 1 addition & 6 deletions packages/quicktype-core/src/language/Swift/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const swiftOptions = {
dense: true,
normal: false,
} as const,
"dense",
"normal",
"secondary",
),
linux: new BooleanOption(
Expand All @@ -91,11 +91,6 @@ export const swiftOptions = {
"If no matching case is found enum value is set to null",
false,
),
swift5Support: new BooleanOption(
"swift-5-support",
"Renders output in a Swift 5 compatible mode",
false,
),
sendable: new BooleanOption(
"sendable",
"Mark generated models as Sendable",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const tsFlowOptions = {
preferUnions: new BooleanOption(
"prefer-unions",
"Use union type instead of enum",
false,
true,
),
preferTypes: new BooleanOption(
"prefer-types",
Expand Down
Loading
Loading