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 <mpvl@golang.org>
diff --git a/encoding/openapi/build.go b/encoding/openapi/build.go
index 05efb62..e3f5d17 100644
--- a/encoding/openapi/build.go
+++ b/encoding/openapi/build.go
@@ -1155,10 +1155,24 @@
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) 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 970fd6d..76d5499 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 e73e4ee..8c507ed 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"
+ }
+ ]
}
}
}