1313//===----------------------------------------------------------------------===//
1414import OpenAPIKit30
1515
16+ /// A result of checking whether a schema is supported.
17+ enum IsSchemaSupportedResult : Equatable {
18+
19+ /// The schema is supported and can be generated.
20+ case supported
21+
22+ /// The reason a schema is unsupported.
23+ enum UnsupportedReason : Equatable , CustomStringConvertible {
24+
25+ /// Describes when no subschemas are found in an allOf, oneOf, or anyOf.
26+ case noSubschemas
27+
28+ /// Describes when the schema is not object-ish, in other words isn't
29+ /// an object, a ref, or an allOf.
30+ case notObjectish
31+
32+ /// Describes when the schema is not a reference.
33+ case notRef
34+
35+ /// Describes when the schema is of an unsupported schema type.
36+ case schemaType
37+
38+ var description : String {
39+ switch self {
40+ case . noSubschemas:
41+ return " no subschemas "
42+ case . notObjectish:
43+ return " not an object-ish schema (object, ref, allOf) "
44+ case . notRef:
45+ return " not a reference "
46+ case . schemaType:
47+ return " schema type "
48+ }
49+ }
50+ }
51+
52+ /// The schema is unsupported for the provided reason.
53+ case unsupported( reason: UnsupportedReason , schema: JSONSchema )
54+ }
55+
1656extension FileTranslator {
1757
1858 /// Validates that the schema is supported by the generator.
@@ -26,11 +66,17 @@ extension FileTranslator {
2666 _ schema: JSONSchema ,
2767 foundIn: String
2868 ) throws -> Bool {
29- guard try isSchemaSupported ( schema) else {
30- diagnostics. emitUnsupported ( " Schema " , foundIn: foundIn)
69+ switch try isSchemaSupported ( schema) {
70+ case . supported:
71+ return true
72+ case . unsupported( reason: let reason, schema: let schema) :
73+ diagnostics. emitUnsupportedSchema (
74+ reason: reason. description,
75+ schema: schema,
76+ foundIn: foundIn
77+ )
3178 return false
3279 }
33- return true
3480 }
3581
3682 /// Validates that the schema is supported by the generator.
@@ -44,22 +90,27 @@ extension FileTranslator {
4490 _ schema: UnresolvedSchema ? ,
4591 foundIn: String
4692 ) throws -> Bool {
47- guard try isSchemaSupported ( schema) else {
48- diagnostics. emitUnsupported ( " Schema " , foundIn: foundIn)
93+ switch try isSchemaSupported ( schema) {
94+ case . supported:
95+ return true
96+ case . unsupported( reason: let reason, schema: let schema) :
97+ diagnostics. emitUnsupportedSchema (
98+ reason: reason. description,
99+ schema: schema,
100+ foundIn: foundIn
101+ )
49102 return false
50103 }
51- return true
52104 }
53105
54- /// Returns a Boolean value that indicates whether the schema is supported.
106+ /// Returns whether the schema is supported.
55107 ///
56108 /// If a schema is not supported, no references to it should be emitted.
57109 /// - Parameters:
58110 /// - schema: The schema to validate.
59- /// - Returns: `true` if the schema is supported; `false` otherwise.
60111 func isSchemaSupported(
61112 _ schema: JSONSchema
62- ) throws -> Bool {
113+ ) throws -> IsSchemaSupportedResult {
63114 switch schema. value {
64115 case . string,
65116 . integer,
@@ -71,31 +122,40 @@ extension FileTranslator {
71122 // responsible for picking only supported properties.
72123 . object,
73124 . fragment:
74- return true
125+ return . supported
75126 case . reference( let ref, _) :
76127 // reference is supported iff the existing type is supported
77128 let existingSchema = try components. lookup ( ref)
78129 return try isSchemaSupported ( existingSchema)
79130 case . array( _, let array) :
80131 guard let items = array. items else {
81132 // an array of fragments is supported
82- return true
133+ return . supported
83134 }
84135 // an array is supported iff its element schema is supported
85136 return try isSchemaSupported ( items)
86137 case . all( of: let schemas, _) :
87138 guard !schemas. isEmpty else {
88- return false
139+ return . unsupported(
140+ reason: . noSubschemas,
141+ schema: schema
142+ )
89143 }
90144 return try areObjectishSchemasAndSupported ( schemas)
91145 case . any( of: let schemas, _) :
92146 guard !schemas. isEmpty else {
93- return false
147+ return . unsupported(
148+ reason: . noSubschemas,
149+ schema: schema
150+ )
94151 }
95152 return try areObjectishSchemasAndSupported ( schemas)
96153 case . one( of: let schemas, let context) :
97154 guard !schemas. isEmpty else {
98- return false
155+ return . unsupported(
156+ reason: . noSubschemas,
157+ schema: schema
158+ )
99159 }
100160 // If a discriminator is provided, only refs to object/allOf of
101161 // object schemas are allowed.
@@ -105,81 +165,104 @@ extension FileTranslator {
105165 }
106166 return try areRefsToObjectishSchemaAndSupported ( schemas)
107167 case . not:
108- return false
168+ return . unsupported(
169+ reason: . schemaType,
170+ schema: schema
171+ )
109172 }
110173 }
111174
112- /// Returns a Boolean value that indicates whether the schema is supported.
175+ /// Returns a result indicating whether the schema is supported.
113176 ///
114177 /// If a schema is not supported, no references to it should be emitted.
115178 /// - Parameters:
116179 /// - schema: The schema to validate.
117- /// - Returns: `true` if the schema is supported; `false` otherwise.
118180 func isSchemaSupported(
119181 _ schema: UnresolvedSchema ?
120- ) throws -> Bool {
182+ ) throws -> IsSchemaSupportedResult {
121183 guard let schema else {
122184 // fragment type is supported
123- return true
185+ return . supported
124186 }
125187 switch schema {
126188 case . a:
127189 // references are supported
128- return true
190+ return . supported
129191 case let . b( schema) :
130192 return try isSchemaSupported ( schema)
131193 }
132194 }
133195
134- /// Returns a Boolean value that indicates whether the provided schemas
196+ /// Returns a result indicating whether the provided schemas
135197 /// are supported.
136198 /// - Parameter schemas: Schemas to check.
137- /// - Returns: `true` if all schemas are supported; `false` otherwise.
138- func areSchemasSupported( _ schemas: [ JSONSchema ] ) throws -> Bool {
139- try schemas. allSatisfy ( isSchemaSupported)
199+ func areSchemasSupported( _ schemas: [ JSONSchema ] ) throws -> IsSchemaSupportedResult {
200+ for schema in schemas {
201+ let result = try isSchemaSupported ( schema)
202+ guard result == . supported else {
203+ return result
204+ }
205+ }
206+ return . supported
140207 }
141208
142- /// Returns a Boolean value that indicates whether the provided schemas
209+ /// Returns a result indicating whether the provided schemas
143210 /// are reference, object, or allOf schemas and supported.
144211 /// - Parameter schemas: Schemas to check.
145- /// - Returns: `true` if all schemas match; `false` otherwise.
146- func areObjectishSchemasAndSupported( _ schemas: [ JSONSchema ] ) throws -> Bool {
147- try schemas. allSatisfy ( isObjectishSchemaAndSupported)
212+ /// - Returns: `.supported` if all schemas match; `.unsupported` otherwise.
213+ func areObjectishSchemasAndSupported( _ schemas: [ JSONSchema ] ) throws -> IsSchemaSupportedResult {
214+ for schema in schemas {
215+ let result = try isObjectishSchemaAndSupported ( schema)
216+ guard result == . supported else {
217+ return result
218+ }
219+ }
220+ return . supported
148221 }
149222
150- /// Returns a Boolean value that indicates whether the provided schema
223+ /// Returns a result indicating whether the provided schema
151224 /// is an reference, object, or allOf (object-ish) schema and is supported.
152225 /// - Parameter schema: A schemas to check.
153- /// - Returns: `true` if the schema matches; `false` otherwise.
154- func isObjectishSchemaAndSupported( _ schema: JSONSchema ) throws -> Bool {
226+ func isObjectishSchemaAndSupported( _ schema: JSONSchema ) throws -> IsSchemaSupportedResult {
155227 switch schema. value {
156228 case . object, . reference:
157229 return try isSchemaSupported ( schema)
158230 case . all( of: let schemas, _) :
159231 return try areObjectishSchemasAndSupported ( schemas)
160232 default :
161- return false
233+ return . unsupported(
234+ reason: . notObjectish,
235+ schema: schema
236+ )
162237 }
163238 }
164239
165- /// Returns a Boolean value that indicates whether the provided schemas
240+ /// Returns a result indicating whether the provided schemas
166241 /// are reference schemas that point to object-ish schemas and supported.
167242 /// - Parameter schemas: Schemas to check.
168- /// - Returns: `true` if all schemas match; `false` otherwise.
169- func areRefsToObjectishSchemaAndSupported( _ schemas: [ JSONSchema ] ) throws -> Bool {
170- try schemas. allSatisfy ( isRefToObjectishSchemaAndSupported)
243+ /// - Returns: `.supported` if all schemas match; `.unsupported` otherwise.
244+ func areRefsToObjectishSchemaAndSupported( _ schemas: [ JSONSchema ] ) throws -> IsSchemaSupportedResult {
245+ for schema in schemas {
246+ let result = try isRefToObjectishSchemaAndSupported ( schema)
247+ guard result == . supported else {
248+ return result
249+ }
250+ }
251+ return . supported
171252 }
172253
173- /// Returns a Boolean value that indicates whether the provided schema
254+ /// Returns a result indicating whether the provided schema
174255 /// is a reference schema that points to an object-ish schema and is supported.
175256 /// - Parameter schema: A schema to check.
176- /// - Returns: `true` if the schema matches; `false` otherwise.
177- func isRefToObjectishSchemaAndSupported( _ schema: JSONSchema ) throws -> Bool {
257+ func isRefToObjectishSchemaAndSupported( _ schema: JSONSchema ) throws -> IsSchemaSupportedResult {
178258 switch schema. value {
179259 case . reference:
180260 return try isObjectishSchemaAndSupported ( schema)
181261 default :
182- return false
262+ return . unsupported(
263+ reason: . notRef,
264+ schema: schema
265+ )
183266 }
184267 }
185268}
0 commit comments