@@ -31,21 +31,37 @@ public struct StructureSwiftGen: JSONSchemaSwiftGenerator {
31
31
cascadingConformances: [ String ] = [ ] ,
32
32
rootConformances: [ String ] ? = nil
33
33
) throws {
34
- guard case . object( _, let context) = structure else {
35
- throw Error . rootNotJSONObject
34
+ let typeName : String
35
+ if reservedTypeNames. contains ( swiftTypeName) {
36
+ typeName = " Gen " + swiftTypeName
37
+ } else {
38
+ typeName = swiftTypeName
36
39
}
37
40
38
- self . swiftTypeName = swiftTypeName
41
+ self . swiftTypeName = typeName
39
42
self . structure = structure
40
43
41
- decls = [
42
- try StructureSwiftGen . structure (
43
- named: swiftTypeName,
44
- forObject: context,
44
+ switch structure {
45
+ case . object( _, let context) :
46
+ decls = [
47
+ try StructureSwiftGen . structure (
48
+ named: typeName,
49
+ forObject: context,
50
+ cascadingConformances: cascadingConformances,
51
+ rootConformances: rootConformances
52
+ )
53
+ ]
54
+ case . one( of: let schemas, core: _) :
55
+ let poly = try StructureSwiftGen . structure (
56
+ named: typeName,
57
+ forOneOf: schemas,
45
58
cascadingConformances: cascadingConformances,
46
59
rootConformances: rootConformances
47
60
)
48
- ]
61
+ decls = [ poly. polyDecl] + poly. dependencies
62
+ default :
63
+ throw Error . rootNotJSONObject
64
+ }
49
65
}
50
66
51
67
static func structure(
@@ -72,6 +88,40 @@ public struct StructureSwiftGen: JSONSchemaSwiftGenerator {
72
88
)
73
89
}
74
90
91
+ static func structure(
92
+ named name: String ,
93
+ forOneOf schemas: [ DereferencedJSONSchema ] ,
94
+ cascadingConformances: [ String ] ,
95
+ rootConformances: [ String ] ? = nil
96
+ ) throws -> ( polyDecl: Decl , dependencies: [ Decl ] ) {
97
+ let dependencies = try schemas
98
+ . enumerated ( )
99
+ . map { ( idx, schema) -> ( String , [ Decl ] ) in
100
+ let name = typeCased ( " Poly \( name) \( idx) " )
101
+ return (
102
+ name,
103
+ try declsForType (
104
+ named: name,
105
+ for: schema,
106
+ conformances: cascadingConformances
107
+ )
108
+ )
109
+ }
110
+
111
+ let poly = Typealias (
112
+ alias: . def( . init( name: name) ) ,
113
+ existingType: . def(
114
+ . init(
115
+ name: " Poly \( dependencies. count) " ,
116
+ specializationReps: dependencies. map { . def( . init( name: $0. 0 ) ) } ,
117
+ optional: false
118
+ )
119
+ )
120
+ )
121
+
122
+ return ( polyDecl: poly, dependencies: dependencies. flatMap ( \. 1 ) )
123
+ }
124
+
75
125
static func structure(
76
126
named name: String ,
77
127
forArray context: DereferencedJSONSchema . ArrayContext ,
@@ -91,6 +141,70 @@ public struct StructureSwiftGen: JSONSchemaSwiftGenerator {
91
141
)
92
142
}
93
143
144
+ /// Create the decls needed to represent the structures in use
145
+ /// by a PolyX.
146
+ static func declsForType(
147
+ named name: String ,
148
+ for schema: DereferencedJSONSchema ,
149
+ conformances: [ String ]
150
+ ) throws -> [ Decl ] {
151
+ let type : SwiftTypeRep
152
+ let structureDecl : Decl ?
153
+
154
+ do {
155
+ type = try swiftType ( from: schema, allowPlaceholders: false )
156
+ structureDecl = nil
157
+ } catch {
158
+ switch schema {
159
+ case . object( let context, let objContext) :
160
+ let newTypeName = typeCased ( name)
161
+
162
+ // TODO: ideally distinguish between these
163
+ // but that requires generating Swift code
164
+ // for custom encoding/decoding
165
+ let optional = !context. required || context. nullable
166
+
167
+ let typeIntermediate = SwiftTypeRep . def ( . init( name: newTypeName) )
168
+
169
+ type = optional ? typeIntermediate. optional : typeIntermediate
170
+
171
+ structureDecl = try structure (
172
+ named: newTypeName,
173
+ forObject: objContext,
174
+ cascadingConformances: conformances
175
+ )
176
+
177
+ case . array( let context, let arrayContext) :
178
+ let newTypeName = typeCased ( name)
179
+
180
+ // TODO: ideally distinguish between these
181
+ // but that requires generating Swift code
182
+ // for custom encoding/decoding
183
+ let optional = !context. required || context. nullable
184
+
185
+ let typeIntermediate = SwiftTypeRep . def ( SwiftTypeDef ( name: newTypeName) . array)
186
+
187
+ type = optional ? typeIntermediate. optional : typeIntermediate
188
+
189
+ structureDecl = try structure (
190
+ named: newTypeName,
191
+ forArray: arrayContext,
192
+ conformances: conformances
193
+ )
194
+ default :
195
+ throw SwiftTypeError . typeNotFound
196
+ }
197
+ }
198
+ return [
199
+ structureDecl ?? Typealias (
200
+ alias: . def( . init( name: name) ) ,
201
+ existingType: type
202
+ )
203
+ ] . compactMap { $0 }
204
+ }
205
+
206
+ /// Create the decls needed to represent the substructure of
207
+ /// a property with the given name.
94
208
static func declsForProp(
95
209
named name: String ,
96
210
for schema: DereferencedJSONSchema ,
0 commit comments