1212//
1313//===----------------------------------------------------------------------===//
1414import OpenAPIKit
15+ import Foundation
1516
1617/// A set of functions that match Swift types onto OpenAPI types.
1718struct TypeMatcher {
@@ -46,7 +47,11 @@ struct TypeMatcher {
4647 matchedArrayHandler: { elementType, nullableItems in
4748 nullableItems ? elementType. asOptional. asArray : elementType. asArray
4849 } ,
49- genericArrayHandler: { TypeName . arrayContainer. asUsage }
50+ genericArrayHandler: { TypeName . arrayContainer. asUsage } ,
51+ substitutedTypeHandler: { substitute in
52+ // never built-in
53+ nil
54+ }
5055 )
5156 }
5257
@@ -75,7 +80,10 @@ struct TypeMatcher {
7580 matchedArrayHandler: { elementType, nullableItems in
7681 nullableItems ? elementType. asOptional. asArray : elementType. asArray
7782 } ,
78- genericArrayHandler: { TypeName . arrayContainer. asUsage }
83+ genericArrayHandler: { TypeName . arrayContainer. asUsage } ,
84+ substitutedTypeHandler: { substitute in
85+ substitute. asUsage
86+ }
7987 ) ?
8088 . withOptional ( isOptional ( schema, components: components) )
8189 }
@@ -98,7 +106,8 @@ struct TypeMatcher {
98106 return true
99107 } ,
100108 matchedArrayHandler: { elementIsReferenceable, _ in elementIsReferenceable } ,
101- genericArrayHandler: { true }
109+ genericArrayHandler: { true } ,
110+ substitutedTypeHandler: { _ in true }
102111 ) ?? false
103112 }
104113
@@ -353,8 +362,10 @@ struct TypeMatcher {
353362 for schema: JSONSchema . Schema ,
354363 test: ( JSONSchema . Schema ) throws -> R ? ,
355364 matchedArrayHandler: ( R , _ nullableItems: Bool ) -> R ,
356- genericArrayHandler: ( ) -> R
365+ genericArrayHandler: ( ) -> R ,
366+ substitutedTypeHandler: ( TypeName ) -> R ?
357367 ) rethrows -> R ? {
368+ if let substitute = schema. substituteType ( ) { return substitutedTypeHandler ( substitute) }
358369 switch schema {
359370 case let . array( _, arrayContext) :
360371 guard let items = arrayContext. items else { return genericArrayHandler ( ) }
@@ -363,11 +374,39 @@ struct TypeMatcher {
363374 for: items. value,
364375 test: test,
365376 matchedArrayHandler: matchedArrayHandler,
366- genericArrayHandler: genericArrayHandler
377+ genericArrayHandler: genericArrayHandler,
378+ substitutedTypeHandler: substitutedTypeHandler
367379 )
368380 else { return nil }
369381 return matchedArrayHandler ( itemsResult, items. nullable)
370382 default : return try test ( schema)
371383 }
372384 }
373385}
386+
387+ extension JSONSchema . Schema {
388+ func substituteType( ) -> TypeName ? {
389+ let extensions : [ String : AnyCodable ] =
390+ switch self {
391+ case . null( let context) : context. vendorExtensions
392+ case . boolean( let context) : context. vendorExtensions
393+ case . number( let context, _) : context. vendorExtensions
394+ case . integer( let context, _) : context. vendorExtensions
395+ case . string( let context, _) : context. vendorExtensions
396+ case . object( let context, _) : context. vendorExtensions
397+ case . array( let context, _) : context. vendorExtensions
398+ case . all( of: _, core: let context) : context. vendorExtensions
399+ case . one( of: _, core: let context) : context. vendorExtensions
400+ case . any( of: _, core: let context) : context. vendorExtensions
401+ case . not: [ : ]
402+ case . reference( _, let context) : context. vendorExtensions
403+ case . fragment( let context) : context. vendorExtensions
404+ }
405+ guard let substituteTypeName = extensions [ Constants . VendorExtension. replaceType] ? . value as? String else {
406+ return nil
407+ }
408+ assert ( !substituteTypeName. isEmpty)
409+
410+ return TypeName ( swiftKeyPath: substituteTypeName. components ( separatedBy: " . " ) )
411+ }
412+ }
0 commit comments