From 50b9067dc06d4217bcd30ae9cf844139962affaf Mon Sep 17 00:00:00 2001 From: Marcel van Lohuizen Date: Mon, 15 Jun 2020 23:15:54 +0200 Subject: [PATCH] encoding/openapi: wrap $ref in allOf when needed. It is unclear to me what the JSON schema spec says (and it seems the current behavior is correct), but at least OpenAPI expects $ref to be by itself. Change-Id: Ic91f21eb16b1de342b99722ee45a91fb8844ed1a Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6344 Reviewed-by: Marcel van Lohuizen --- encoding/openapi/build.go | 19 +++++++++++++++++-- encoding/openapi/testdata/refs.cue | 8 ++++++++ encoding/openapi/testdata/refs.json | 26 ++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/encoding/openapi/build.go b/encoding/openapi/build.go index 05efb6296..e3f5d17d8 100644 --- a/encoding/openapi/build.go +++ b/encoding/openapi/build.go @@ -1155,10 +1155,24 @@ func (b *builder) finish() *ast.StructLit { t = &OrderedMap{} case 1: - t = (*OrderedMap)(b.allOf[0]) + hasRef := false + for _, e := range b.allOf[0].Elts { + if f, ok := e.(*ast.Field); ok { + name, _, _ := ast.LabelName(f.Label) + hasRef = hasRef || name == "$ref" + } + } + if !hasRef || b.singleFields == nil { + t = (*OrderedMap)(b.allOf[0]) + break + } + fallthrough default: exprs := []ast.Expr{} + if t != nil { + exprs = append(exprs, (*ast.StructLit)(t)) + } for _, s := range b.allOf { exprs = append(exprs, s) } @@ -1190,7 +1204,8 @@ func (b *builder) addConjunct(f func(*builder)) { func (b *builder) addRef(v cue.Value, inst *cue.Instance, ref []string) { name := b.ctx.makeRef(inst, ref) b.addConjunct(func(b *builder) { - b.set("$ref", ast.NewString(path.Join("#", b.ctx.refPrefix, name))) + b.allOf = append(b.allOf, ast.NewStruct( + "$ref", ast.NewString(path.Join("#", b.ctx.refPrefix, name)))) }) if b.ctx.inst != inst { diff --git a/encoding/openapi/testdata/refs.cue b/encoding/openapi/testdata/refs.cue index 970fd6d0b..76d54997a 100644 --- a/encoding/openapi/testdata/refs.cue +++ b/encoding/openapi/testdata/refs.cue @@ -11,3 +11,11 @@ // ExcludedInt is not included in the output. #ExcludedInt: int + +#Type: { + a?: string + #BaseType +} +#BaseType: { + b: string +} diff --git a/encoding/openapi/testdata/refs.json b/encoding/openapi/testdata/refs.json index e73e4ee60..8c507ed80 100644 --- a/encoding/openapi/testdata/refs.json +++ b/encoding/openapi/testdata/refs.json @@ -7,6 +7,18 @@ "paths": {}, "components": { "schemas": { + "BaseType": { + "type": "object", + "required": [ + "b" + ], + "properties": { + "b": { + "type": "string", + "format": "string" + } + } + }, "Keep": { "type": "object", "required": [ @@ -30,6 +42,20 @@ "type": "integer" } } + }, + "Type": { + "type": "object", + "properties": { + "a": { + "type": "string", + "format": "string" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/BaseType" + } + ] } } }