@@ -460,7 +460,7 @@ func (m *Model) Render(ctx context.Context, writer io.Writer) error {
460
460
// resolveAllOf resolves the list of `allOf` definitions in the schema to a complete type merging
461
461
// all the mentioned types.
462
462
// `passed` can be nil, it's used recursively in order to avoid infinite loops
463
- func resolveAllOf (ref * openapi3.SchemaRef , passed passedSchemas ) (out * openapi3.SchemaRef ) {
463
+ func resolveAllOf (ref * openapi3.SchemaRef , overrideRef bool , passed passedSchemas ) (out * openapi3.SchemaRef ) {
464
464
defer func () {
465
465
// clean up the allOf field after resolving it
466
466
ref .Value .AllOf = nil
@@ -482,17 +482,6 @@ func resolveAllOf(ref *openapi3.SchemaRef, passed passedSchemas) (out *openapi3.
482
482
passed = make (passedSchemas )
483
483
}
484
484
485
- // very special case where the allOf references
486
- // another named schema but is not actually merging
487
- // several schemas, this is usually just overriding
488
- // a value like nullable or the description
489
- if len (ref .Value .AllOf ) == 1 {
490
- pointer := ref .Value .AllOf [0 ]
491
- passed [pointer ] = true
492
- out = deepMerge (out , pointer , passed )
493
- return out
494
- }
495
-
496
485
// this is used for the special edge cases like this
497
486
// allOf:
498
487
// - description: "this will only set the description value"
@@ -503,27 +492,23 @@ func resolveAllOf(ref *openapi3.SchemaRef, passed passedSchemas) (out *openapi3.
503
492
// the special case of a single `ref`, which will used the named `ColumnTypeMetadata` type.
504
493
ref .Value .AllOf = removeSemanticallyEmptyRefs (ref .Value .AllOf )
505
494
506
- isSelfRef := false
495
+ // very special case where the allOf references
496
+ // another named schema but is not actually merging
497
+ // several schemas, this is usually just overriding
498
+ // a value like nullable or the description
499
+ if len (ref .Value .Properties ) == 0 && len (ref .Value .AllOf ) == 1 {
500
+ pointer := ref .Value .AllOf [0 ]
501
+ passed [pointer ] = true
502
+ out = deepMerge (out , pointer , overrideRef , passed )
503
+ return out
504
+ }
505
+
507
506
for _ , subSchema := range ref .Value .AllOf {
508
507
if passed [subSchema ] {
509
- isSelfRef = true
510
508
continue
511
509
}
512
510
passed [subSchema ] = true
513
- out = deepMerge (out , subSchema , passed )
514
- }
515
-
516
- // remove the reference field on AllOf values, these should be
517
- // flattened into a single (potentially inlined) struct.
518
- // We make exceptions for
519
- // * types are contain a self-reference, these can not be flattened
520
- // * types are a single allOf, these usually indicate merging in nullable properties, etc
521
- // it is not a _real_ allOf, rather we are just overriding fields on a single type.
522
- // this case should already be handled above, so this is really checking if AllOf > 0,
523
- // but checking >1 is more semantically correct
524
- //
525
- if ! isSelfRef && len (ref .Value .AllOf ) > 1 {
526
- out .Ref = ""
511
+ out = deepMerge (out , subSchema , false , passed )
527
512
}
528
513
529
514
return out
@@ -618,7 +603,7 @@ func isNonEmptySchemaRef(ref *openapi3.SchemaRef) bool {
618
603
// deepMerge merges `right` into `left` schema recursively resolving types (e.g. `allOf`).
619
604
// `passed` map will be populated with all the visited types during the resolution process, so we can
620
605
// avoid the infinite loop.
621
- func deepMerge (left * openapi3.SchemaRef , right * openapi3.SchemaRef , passed passedSchemas ) (out * openapi3.SchemaRef ) {
606
+ func deepMerge (left * openapi3.SchemaRef , right * openapi3.SchemaRef , overrideRef bool , passed passedSchemas ) (out * openapi3.SchemaRef ) {
622
607
out = left
623
608
if out == nil {
624
609
out = & openapi3.SchemaRef {}
@@ -634,11 +619,11 @@ func deepMerge(left *openapi3.SchemaRef, right *openapi3.SchemaRef, passed passe
634
619
right .Value = & openapi3.Schema {}
635
620
}
636
621
637
- right = resolveAllOf (right , passed )
638
- if right .Ref != "" {
622
+ right = resolveAllOf (right , false , passed )
623
+ if overrideRef && out . Ref == "" && right .Ref != "" {
639
624
out .Ref = right .Ref
640
625
}
641
- if right .Value .Type != "" {
626
+ if out . Value . Type == "" && right .Value .Type != "" {
642
627
out .Value .Type = right .Value .Type
643
628
}
644
629
@@ -679,6 +664,7 @@ func deepMerge(left *openapi3.SchemaRef, right *openapi3.SchemaRef, passed passe
679
664
out .Value .AdditionalProperties = deepMerge (
680
665
out .Value .AdditionalProperties ,
681
666
right .Value .AdditionalProperties ,
667
+ overrideRef ,
682
668
nil , // here we merge all over, without `passed`
683
669
)
684
670
}
@@ -688,12 +674,12 @@ func deepMerge(left *openapi3.SchemaRef, right *openapi3.SchemaRef, passed passe
688
674
out .Value .Properties = make (map [string ]* openapi3.SchemaRef )
689
675
}
690
676
for k , v := range right .Value .Properties {
691
- out .Value .Properties [k ] = resolveAllOf (v , passed )
677
+ out .Value .Properties [k ] = resolveAllOf (v , true , passed )
692
678
}
693
679
}
694
680
695
681
if right .Value .Type == "array" && right .Value .Items != nil {
696
- out .Value .Items = resolveAllOf (right .Value .Items , passed )
682
+ out .Value .Items = resolveAllOf (right .Value .Items , true , passed )
697
683
}
698
684
699
685
return out
@@ -718,29 +704,6 @@ func structPropsFromRef(ref *openapi3.SchemaRef) (specs []PropSpec, imports map[
718
704
imports = make (map [string ]string )
719
705
for _ , name := range sortedKeys (ref .Value .Properties ) {
720
706
prop := ref .Value .Properties [name ]
721
-
722
- // special case for singleton allOf
723
- // generally these are used to add
724
- // a new description or override the
725
- // nullable flag
726
- if len (prop .Value .AllOf ) == 1 {
727
- pointer := prop .Value .AllOf [0 ]
728
- prop .Ref = pointer .Ref
729
-
730
- // a sub-special case when the referenced type
731
- // is an array. Because we don't create top-level
732
- // models for arrays, we actually need to follow
733
- // this reference.
734
- resolved := resolveAllOf (prop , nil )
735
- if resolved .Value .Type == "array" {
736
- prop = resolved
737
- }
738
- }
739
-
740
- if prop .Ref == "" {
741
- prop = resolveAllOf (prop , nil )
742
- }
743
-
744
707
isRequired := checkIfRequired (name , ref .Value .Required )
745
708
var spec * PropSpec
746
709
spec , err = newPropertySpecFromRef (name , prop , isRequired , imports )
0 commit comments