@@ -30,10 +30,9 @@ object ASTTranslationFunctions {
30
30
private def extractRefOfMediaTypeObject (schemaObject : MediaTypeObject ): Option [Ref ] =
31
31
schemaObject.schema
32
32
.flatMap {
33
- case _ : SchemaObject => None
34
- case ReferenceObject (ref) => Some (ref)
33
+ case _ : SchemaObject => None
34
+ case ReferenceObject (ref, _ ) => Some (Ref ( ref, ref.split( " / " ).last, None ) )
35
35
}
36
- .map(x => Ref (x, x.split(" /" ).last))
37
36
38
37
private def getBodyEncodings (media : RequestBodyObject )(implicit packageName : PackageName ): List [TypeRepr ] =
39
38
media.content.values.toList.map { extractMediaTypeObject }.sequence.toList.flatten
@@ -80,15 +79,15 @@ object ASTTranslationFunctions {
80
79
buildPrimitiveFromSchemaObjectType(NonEmptyList .fromList(refinements), a.items)(packageName)(
81
80
a.`type`.get
82
81
).get
83
- if (! isRequired) {
84
- PrimitiveOption (dataType = value, defaultValue = a.default )
82
+ if (! isRequired && a.default.isEmpty ) {
83
+ PrimitiveOption (dataType = value)
85
84
} else {
86
85
value
87
86
}
88
87
case referenceObject : ReferenceObject =>
89
88
val value = loadSingleProperty(referenceObject).get
90
- if (! isRequired) {
91
- PrimitiveOption (dataType = value, defaultValue = None )
89
+ if (! isRequired && referenceObject.default.isEmpty ) {
90
+ PrimitiveOption (dataType = value)
92
91
} else {
93
92
value
94
93
}
@@ -216,10 +215,10 @@ object ASTTranslationFunctions {
216
215
refinements : Option [NonEmptyList [TypeRepr .RefinedTags ]],
217
216
items : Option [SchemaOrReferenceObject ] = None
218
217
)(implicit packageName : PackageName ): SchemaObjectType => Option [Primitive ] = {
219
- case SchemaObjectType .string => Some (PrimitiveString (refinements))
220
- case SchemaObjectType .boolean => Some (PrimitiveBoolean (refinements))
221
- case SchemaObjectType .number => Some (PrimitiveNumber (refinements))
222
- case SchemaObjectType .`integer` => Some (PrimitiveInt (refinements))
218
+ case SchemaObjectType .string => Some (PrimitiveString (refinements, None ))
219
+ case SchemaObjectType .boolean => Some (PrimitiveBoolean (refinements, None ))
220
+ case SchemaObjectType .number => Some (PrimitiveNumber (refinements, None ))
221
+ case SchemaObjectType .`integer` => Some (PrimitiveInt (refinements, None ))
223
222
case SchemaObjectType .`array` =>
224
223
val loadedType = items.flatMap {
225
224
case so : SchemaObject =>
@@ -248,10 +247,10 @@ object ASTTranslationFunctions {
248
247
so.`type`
249
248
.flatMap(buildPrimitiveFromSchemaObjectTypeForComponents(so.items, refinements))
250
249
}(loadSingleProperty(_).map(PrimitiveDict (_, None )))
251
- case ReferenceObject (ref) =>
250
+ case ReferenceObject (ref, _ ) =>
252
251
val name : String = ref.split(" /" ).last
253
252
val path : String = ref.split(" /" ).dropRight(1 ).mkString(" ." )
254
- (Ref (path.replace(" #.components.schemas" , packageName.name), name): TypeRepr ).some
253
+ (Ref (path.replace(" #.components.schemas" , packageName.name), name, None ): TypeRepr ).some
255
254
}
256
255
257
256
private def makeSymbolFromTypeRepr (name : String , repr : TypeRepr ): Symbol = repr match {
@@ -265,61 +264,67 @@ object ASTTranslationFunctions {
265
264
properties : Map [String , SchemaOrReferenceObject ],
266
265
required : List [String ],
267
266
summary : Option [String ],
268
- description : Option [String ]
267
+ description : Option [String ],
268
+ allSchemas : Map [String , SchemaObject ]
269
269
)(
270
270
implicit packageName : PackageName
271
271
): Option [NewType ] = {
272
272
val mapped : immutable.Iterable [Option [Symbol ]] = properties map {
273
273
case (name : String , repr : SchemaOrReferenceObject ) =>
274
- val loaded = getTypeRepr(required, name, repr)
274
+ val loaded : Option [ TypeRepr ] = getTypeRepr(required, name, repr, allSchemas )
275
275
assert(loaded.isDefined, s " $name in $typeName could not be parsed. " )
276
276
loaded map (makeSymbolFromTypeRepr(name, _))
277
277
}
278
278
mapped.toList.sequence.map(PrimitiveProduct (packageName.name, typeName, _, summary, description))
279
279
}
280
280
281
- private def typedDefaultMapping (value : TypeRepr , default : Option [PrimitiveValue ]): PrimitiveOption = {
282
- val mismatchErr = s " ${value.typeName} has wrong default value type "
283
- val mappedDefault = default map {
284
- case PrimitiveNumberValue (n) =>
285
- value match {
286
- case _ : PrimitiveNumber => PrimitiveNumberValue (n)
287
- case _ : PrimitiveInt =>
288
- assert(n.isValidInt, " Implicit double to integer type coercion" )
289
- PrimitiveIntValue (n.toInt)
290
- case _ => throw new AssertionError (mismatchErr)
291
- }
292
- case i : PrimitiveIntValue =>
293
- assert(value.isInstanceOf [PrimitiveInt ], mismatchErr)
294
- i
295
- case s : PrimitiveStringValue =>
296
- assert(value.isInstanceOf [PrimitiveString ], mismatchErr)
297
- s
298
- case self => self
299
- }
300
- PrimitiveOption (value, mappedDefault)
301
- }
302
-
303
- private def getTypeRepr (required : List [String ], name : String , repr : SchemaOrReferenceObject )(
281
+ private def getTypeRepr (
282
+ required : List [String ],
283
+ name : String ,
284
+ repr : SchemaOrReferenceObject ,
285
+ allProps : Map [String , SchemaObject ]
286
+ )(
304
287
implicit packageName : PackageName
305
288
): Option [TypeRepr ] =
306
289
repr match {
290
+ case o : SchemaObject if o.oneOf.nonEmpty =>
291
+ throw new AssertionError (" Discriminated Unions (OpenAPI: oneOf) are only supported as top-level types for now." )
307
292
case r : ReferenceObject =>
308
- val loadedTypeRepr = loadSingleProperty(r)
309
- if (required.contains(name)) loadedTypeRepr else loadedTypeRepr.map(PrimitiveOption (_, None ))
310
- case o : SchemaObject if o.oneOf.isEmpty =>
311
- val loadedTypeRepr : Option [TypeRepr ] = loadSingleProperty(o)
312
- if (required.contains(name)) loadedTypeRepr else loadedTypeRepr.map(typedDefaultMapping(_, o.default))
293
+ val typeRepr = loadSingleProperty(repr)
294
+ val referenceTo = r.$ref.split(" /" ).last.stripSuffix(" Request" )
295
+ allProps
296
+ .getOrElse(
297
+ referenceTo,
298
+ throw new Exception (
299
+ s " You're referencing ${r.$ref} which does not exist. Available components are ${allProps.keys.mkString(" , " )}"
300
+ )
301
+ )
302
+ .default
303
+ .fold(if (required contains name) typeRepr else typeRepr.map(PrimitiveOption ))(
304
+ dv => typeRepr.map(_.packDefault(dv))
305
+ )
313
306
case _ =>
314
- throw new AssertionError (" Discriminated Unions (OpenAPI: oneOf) are only supported as top-level types for now." )
307
+ val typeRepr : Option [TypeRepr ] = loadSingleProperty(repr)
308
+ repr.default.fold(if (required contains name) typeRepr else typeRepr.map(PrimitiveOption ))(
309
+ dv => typeRepr.map(_.packDefault(dv))
310
+ )
315
311
}
316
312
317
- private def loadEnum (typeName : String , values : List [String ], summary : Option [String ], description : Option [String ])(
313
+ private def loadEnum (
314
+ typeName : String ,
315
+ values : List [String ],
316
+ summary : Option [String ],
317
+ description : Option [String ]
318
+ )(
318
319
implicit packageName : PackageName
319
320
): NewType =
320
321
PrimitiveEnum (packageName.name, typeName, values.toSet, summary, description)
321
322
322
- private def handleSchemaObjectProductType (name : String , schemaObject : SchemaObject )(
323
+ private def handleSchemaObjectProductType (
324
+ name : String ,
325
+ schemaObject : SchemaObject ,
326
+ allSchemas : Map [String , SchemaObject ]
327
+ )(
323
328
implicit packageName : PackageName
324
329
): Option [Symbol ] = {
325
330
val required = schemaObject.required.getOrElse(List .empty[String ])
@@ -330,7 +335,8 @@ object ASTTranslationFunctions {
330
335
schemaObject.properties.getOrElse(Map .empty),
331
336
required,
332
337
schemaObject.summary,
333
- schemaObject.description
338
+ schemaObject.description,
339
+ allSchemas
334
340
)
335
341
case SchemaObjectType .`string` =>
336
342
schemaObject.enum .map(loadEnum(name, _, schemaObject.summary, schemaObject.description))
@@ -362,10 +368,10 @@ object ASTTranslationFunctions {
362
368
implicit packageName : PackageName
363
369
): Option [Symbol ] = {
364
370
val references : Set [Ref ] = unionMembers.map {
365
- case ReferenceObject (ref) =>
371
+ case ReferenceObject (ref, _ ) =>
366
372
val name : String = ref.split(" /" ).last
367
373
val path : String = ref.split(" /" ).dropRight(1 ).mkString(" ." )
368
- Ref (path, name)
374
+ Ref (path, name, None )
369
375
}.toSet
370
376
val newType : NewType =
371
377
PrimitiveUnion (
@@ -385,10 +391,10 @@ object ASTTranslationFunctions {
385
391
NewTypeSymbol (name, newType).some
386
392
}
387
393
388
- private def evalSchema (name : String , schemaObject : SchemaObject )(
394
+ private def evalSchema (name : String , schemaObject : SchemaObject , allSchemas : Map [ String , SchemaObject ] )(
389
395
implicit packageName : PackageName
390
396
): Option [Symbol ] =
391
- schemaObject.oneOf.fold(handleSchemaObjectProductType(name, schemaObject))(
397
+ schemaObject.oneOf.fold(handleSchemaObjectProductType(name, schemaObject, allSchemas ))(
392
398
handleSchemaObjectUnionType(name, schemaObject.discriminator, _, schemaObject.summary, schemaObject.description)
393
399
)
394
400
@@ -399,13 +405,13 @@ object ASTTranslationFunctions {
399
405
so.readOnly.getOrElse(
400
406
so.properties.exists { _.values.exists { schemaObjectHasReadOnlyComponent(components) } }
401
407
) || so.oneOf.fold(false )(_.map(schemaObjectHasReadOnlyComponent(components)(_)).reduce(_ || _))
402
- case ReferenceObject (ref) =>
408
+ case ReferenceObject (ref, _ ) =>
403
409
schemaObjectHasReadOnlyComponent(components)(findRefInComponents(components, ref.split(" /" ).last))
404
410
}
405
411
406
412
private def hasReadOnlyBase : SchemaOrReferenceObject => Boolean = {
407
- case so : SchemaObject => so.readOnly.getOrElse(false )
408
- case ReferenceObject (_) => false
413
+ case so : SchemaObject => so.readOnly.getOrElse(false )
414
+ case ReferenceObject (_, _ ) => false
409
415
}
410
416
411
417
private def enrichSublevelPropsWithRequest (
@@ -415,7 +421,7 @@ object ASTTranslationFunctions {
415
421
.map {
416
422
case (k, v : ReferenceObject ) =>
417
423
if (schemaObjectHasReadOnlyComponent(components)(v)) {
418
- (k, ReferenceObject (v.$ref + " Request" ))
424
+ (k, ReferenceObject (v.$ref + " Request" , v.default ))
419
425
} else {
420
426
(k, v)
421
427
}
@@ -451,7 +457,7 @@ object ASTTranslationFunctions {
451
457
splitReadOnlyComponents(ast.components.schemas)
452
458
.flatMap {
453
459
case (name : String , schemaObject : SchemaObject ) =>
454
- evalSchema(name, schemaObject)
460
+ evalSchema(name, schemaObject, ast.components.schemas )
455
461
.map { cleanFilename(name) -> _ }
456
462
}
457
463
.toList
0 commit comments