Skip to content

Commit b3ecdc7

Browse files
authored
Merge pull request #38 from GerritPlehn/null-optional
Distinction between nullable and optional
2 parents 4ad1b6c + 980a120 commit b3ecdc7

File tree

8 files changed

+59
-6
lines changed

8 files changed

+59
-6
lines changed

json_typegen_shared/src/generation/json_schema.rs

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ fn type_from_shape(ctxt: &mut Ctxt, path: &str, shape: &Shape) -> Value {
5353
MapT { val_type: v } => generate_map_type(ctxt, path, v),
5454
Opaque(t) => Value::Object(string_hashmap! { "type" => Value::String(t.clone()) }),
5555
Optional(e) => type_from_shape(ctxt, path, e),
56+
Nullable(e) => type_from_shape(ctxt, path, e),
5657
}
5758
}
5859

json_typegen_shared/src/generation/kotlin.rs

+8
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ fn type_from_shape(ctxt: &mut Ctxt, path: &str, shape: &Shape) -> (Ident, Option
8080
} else {
8181
(format!("{}?", inner), defs)
8282
}
83+
},
84+
Nullable(e) => {
85+
let (inner, defs) = type_from_shape(ctxt, path, e);
86+
if ctxt.options.use_default_for_missing_fields {
87+
(inner, defs)
88+
} else {
89+
(format!("{}?", inner), defs)
90+
}
8391
}
8492
}
8593
}

json_typegen_shared/src/generation/python.rs

+9
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ fn type_from_shape(ctxt: &mut Ctxt, path: &str, shape: &Shape) -> (Ident, Option
126126
let optional = import(ctxt, Import::Optional);
127127
(format!("{}[{}]", optional, inner), defs)
128128
}
129+
},
130+
Nullable(e) => {
131+
let (inner, defs) = type_from_shape(ctxt, path, e);
132+
if ctxt.options.use_default_for_missing_fields {
133+
(inner, defs)
134+
} else {
135+
let optional = import(ctxt, Import::Optional);
136+
(format!("{}[{}]", optional, inner), defs)
137+
}
129138
}
130139
}
131140
}

json_typegen_shared/src/generation/rust.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,15 @@ fn type_from_shape(ctxt: &mut Ctxt, path: &str, shape: &Shape) -> (Ident, Option
9494
} else {
9595
(format!("Option<{}>", inner), defs)
9696
}
97-
}
97+
},
98+
Nullable(e) => {
99+
let (inner, defs) = type_from_shape(ctxt, path, e);
100+
if ctxt.options.use_default_for_missing_fields {
101+
(inner, defs)
102+
} else {
103+
(format!("Option<{}>", inner), defs)
104+
}
105+
},
98106
}
99107
}
100108

json_typegen_shared/src/generation/shape.rs

+4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ fn type_from_shape(ctxt: &mut Ctxt, shape: &Shape) -> Value {
4646
"__type__" => Value::Str("optional"),
4747
"item" => type_from_shape(ctxt, e),
4848
}),
49+
Nullable(e) => Value::Object(string_hashmap! {
50+
"__type__" => Value::Str("nullable"),
51+
"item" => type_from_shape(ctxt, e),
52+
}),
4953
}
5054
}
5155

json_typegen_shared/src/generation/typescript.rs

+4
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ fn type_from_shape(ctxt: &mut Ctxt, path: &str, shape: &Shape) -> (Ident, Option
6464
} else {
6565
(format!("{} | undefined", inner), defs)
6666
}
67+
},
68+
Nullable(e) => {
69+
let (inner, defs) = type_from_shape(ctxt, path, e);
70+
(format!("{} | null", inner), defs)
6771
}
6872
}
6973
}

json_typegen_shared/src/generation/typescript_type_alias.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,15 @@ fn type_from_shape(ctxt: &mut Ctxt, shape: &Shape) -> Code {
4949
} else {
5050
format!("{} | undefined", inner)
5151
}
52-
}
52+
},
53+
Nullable(e) => {
54+
let inner = type_from_shape(ctxt, e);
55+
if ctxt.options.use_default_for_missing_fields {
56+
inner
57+
} else {
58+
format!("{} | null", inner)
59+
}
60+
},
5361
}
5462
}
5563

json_typegen_shared/src/shape.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ pub enum Shape {
1515
/// represented by any single shape
1616
Any,
1717

18-
/// `Optional(T)` represents that a value is nullable, or not always present
18+
/// `Optional(T)` represents that a value is not always present
1919
Optional(Box<Shape>),
20-
20+
/// `Nullable(T)` represents that a value is nullable
21+
Nullable(Box<Shape>),
2122
/// Equivalent to `Optional(Bottom)`, `Null` represents optionality with no further information
2223
Null,
2324

@@ -50,7 +51,7 @@ pub fn common_shape(a: Shape, b: Shape) -> Shape {
5051
match (a, b) {
5152
(a, Bottom) | (Bottom, a) => a,
5253
(Integer, Floating) | (Floating, Integer) => Floating,
53-
(a, Null) | (Null, a) => a.into_optional(),
54+
(a, Null) | (Null, a) => a.into_nullable(),
5455
(a, Optional(b)) | (Optional(b), a) => common_shape(a, *b).into_optional(),
5556
(Tuple(shapes1, n1), Tuple(shapes2, n2)) => {
5657
if shapes1.len() == shapes2.len() {
@@ -81,6 +82,7 @@ pub fn common_shape(a: Shape, b: Shape) -> Shape {
8182
fields: common_field_shapes(f1, f2),
8283
},
8384
(Opaque(t), _) | (_, Opaque(t)) => Opaque(t),
85+
(a, Nullable(b)) | (Nullable(b), a) => common_shape(a, *b).into_nullable(),
8486
_ => Any,
8587
}
8688
}
@@ -113,10 +115,19 @@ impl Shape {
113115
fn into_optional(self) -> Self {
114116
use self::Shape::*;
115117
match self {
116-
Null | Any | Bottom | Optional(_) => self,
118+
Null => Nullable(Box::new(self)),
119+
Any | Bottom | Optional(_) => self,
117120
non_nullable => Optional(Box::new(non_nullable)),
118121
}
119122
}
123+
fn into_nullable(self) -> Self {
124+
use self::Shape::*;
125+
match self {
126+
Null => Nullable(Box::new(self)),
127+
Any | Bottom | Nullable(_) => self,
128+
non_nullable => Nullable(Box::new(non_nullable)),
129+
}
130+
}
120131

121132
/// Note: This is asymmetrical because we don't unify based on this,
122133
/// but check if `self` can be used *as is* as a replacement for `other`

0 commit comments

Comments
 (0)