(allOf []*openapi3.SchemaRef, path []string)
| 22 | } |
| 23 | |
| 24 | func mergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { |
| 25 | n := len(allOf) |
| 26 | |
| 27 | if n == 1 { |
| 28 | return GenerateGoSchema(allOf[0], path) |
| 29 | } |
| 30 | |
| 31 | // Distinguish two uses of allOf: |
| 32 | // |
| 33 | // 1. Decorator idiom — at least one INLINE member (Ref == "") is |
| 34 | // "extension-only" (carries no structural content). This is a |
| 35 | // workaround for OpenAPI 3.0's $ref-sibling restriction: users |
| 36 | // wrap a $ref in allOf to attach extensions like |
| 37 | // x-go-type-skip-optional-pointer (see issue #1957). Here |
| 38 | // extensions are meant to flow through to the result. |
| 39 | // |
| 40 | // 2. Real composition — every member either contributes structural |
| 41 | // content or is a $ref contributing the referenced schema. The |
| 42 | // result is a NEW distinct type, and extensions like x-go-type on |
| 43 | // a source schema do NOT transfer (see issue #2335: Client has |
| 44 | // x-go-type=OverlayClient, but allOf[Client, {properties:{id}}] |
| 45 | // is ClientWithId — a different shape, not OverlayClient). |
| 46 | // |
| 47 | // A $ref member is excluded from the decorator check because it is by |
| 48 | // construction delivering the referenced schema, not "decorating" |
| 49 | // siblings — even if the referenced schema happens to carry only |
| 50 | // extensions, that's a property of the target, not an intent on this |
| 51 | // composition. |
| 52 | decoratorIdiom := false |
| 53 | for _, m := range allOf { |
| 54 | if m.Ref == "" && isExtensionOnlySchema(m.Value) { |
| 55 | decoratorIdiom = true |
| 56 | break |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | schema, err := valueWithPropagatedRef(allOf[0]) |
| 61 | if err != nil { |
| 62 | return Schema{}, err |
| 63 | } |
| 64 | |
| 65 | // Seed allOf[0]'s ref so that if s1's own AllOf contains a back-reference |
| 66 | // to itself, the cycle is detected during recursive merging. |
| 67 | seenTopLevel := make(map[string]bool) |
| 68 | if allOf[0].Ref != "" { |
| 69 | seenTopLevel[allOf[0].Ref] = true |
| 70 | } |
| 71 | |
| 72 | for i := 1; i < n; i++ { |
| 73 | var err error |
| 74 | oneOfSchema, err := valueWithPropagatedRef(allOf[i]) |
| 75 | if err != nil { |
| 76 | return Schema{}, err |
| 77 | } |
| 78 | |
| 79 | seenSchemaRef := make(map[string]bool) |
| 80 | for k := range seenTopLevel { |
| 81 | seenSchemaRef[k] = true |
no test coverage detected
searching dependent graphs…