this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cue: keep sane references for embedded disjunctions in Expr

In Expr, simulate a struct with just the fields so that embedded
disjunctions with references to such fields will direct to the unmerged
values of these references.

This also addes OpenAPI tests, which relies on this functionality.

Change-Id: I5d127fee1389a88a45f3705ad1a0c929ee1c2bb0
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9881
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>

authored by

Marcel van Lohuizen and committed by
Paul Jolly
37bf801b b39a2d00

+268 -18
+40 -18
cue/types.go
··· 2383 2383 op = CallOp 2384 2384 2385 2385 case *adt.StructLit: 2386 - // Simulate old embeddings. 2387 - envEmbed := &adt.Environment{ 2388 - Up: env, 2389 - Vertex: v.v, 2390 - } 2386 + hasEmbed := false 2391 2387 fields := []adt.Decl{} 2392 - ctx := v.ctx() 2393 2388 for _, d := range x.Decls { 2394 - switch x := d.(type) { 2389 + switch d.(type) { 2395 2390 default: 2396 2391 fields = append(fields, d) 2397 2392 case adt.Value: 2398 2393 fields = append(fields, d) 2399 2394 case adt.Expr: 2400 - // embedding 2401 - n := &adt.Vertex{Label: v.v.Label} 2402 - c := adt.MakeRootConjunct(envEmbed, x) 2403 - n.AddConjunct(c) 2404 - n.Finalize(ctx) 2405 - n.Parent = v.v.Parent 2406 - a = append(a, makeValue(v.idx, n, v.parent_)) 2395 + hasEmbed = true 2407 2396 } 2408 2397 } 2409 - if len(a) == 0 { 2398 + 2399 + if !hasEmbed { 2410 2400 a = append(a, v) 2411 2401 break 2412 2402 } 2413 2403 2404 + ctx := v.ctx() 2405 + 2406 + n := v.v 2407 + 2414 2408 if len(fields) > 0 { 2415 - n := &adt.Vertex{ 2416 - Label: v.v.Label, 2409 + n = &adt.Vertex{ 2410 + Parent: v.v.Parent, 2411 + Label: v.v.Label, 2417 2412 } 2413 + 2418 2414 s := &adt.StructLit{} 2419 2415 if k := v.v.Kind(); k != adt.StructKind && k != BottomKind { 2420 2416 // TODO: we should also add such a declaration for embeddings ··· 2428 2424 n.AddConjunct(c) 2429 2425 n.Finalize(ctx) 2430 2426 n.Parent = v.v.Parent 2427 + } 2428 + 2429 + // Simulate old embeddings. 2430 + envEmbed := &adt.Environment{ 2431 + Up: env, 2432 + Vertex: n, 2433 + } 2434 + 2435 + for _, d := range x.Decls { 2436 + switch x := d.(type) { 2437 + case adt.Value: 2438 + case adt.Expr: 2439 + // embedding 2440 + n := &adt.Vertex{Label: v.v.Label} 2441 + c := adt.MakeRootConjunct(envEmbed, x) 2442 + n.AddConjunct(c) 2443 + n.Finalize(ctx) 2444 + n.Parent = v.v.Parent 2445 + a = append(a, makeValue(v.idx, n, v.parent_)) 2446 + } 2447 + } 2448 + 2449 + // Could be done earlier, but keep struct with fields at end. 2450 + if len(fields) > 0 { 2431 2451 a = append(a, makeValue(v.idx, n, v.parent_)) 2432 2452 } 2433 2453 2434 - op = adt.AndOp 2454 + if len(a) > 1 { 2455 + op = adt.AndOp 2456 + } 2435 2457 2436 2458 default: 2437 2459 a = append(a, v)
+3
cue/types_test.go
··· 3344 3344 input: `v: { "foo", #def: 1 }`, 3345 3345 want: `{"foo",#def:1}`, 3346 3346 }, { 3347 + input: `v: { {} | { a: #A, b: #B}, #A: {} | { c: int} }, #B: int | bool`, 3348 + want: `&(|({} {a:#A,b:#B}) {#A:({}|{c:int})})`, 3349 + }, { 3347 3350 input: `v: { {c: a}, b: a }, a: int`, 3348 3351 want: `&({c:a} {b:a})`, 3349 3352 }, {
+8
encoding/openapi/openapi_test.go
··· 105 105 out: "openapi-norefs.json", 106 106 config: resolveRefs, 107 107 }, { 108 + in: "embed.cue", 109 + out: "embed.json", 110 + config: defaultConfig, 111 + }, { 112 + in: "embed.cue", 113 + out: "embed-norefs.json", 114 + config: resolveRefs, 115 + }, { 108 116 in: "oneof.cue", 109 117 out: "oneof-funcs.json", 110 118 config: &openapi.Config{
+121
encoding/openapi/testdata/embed-norefs.json
··· 1 + { 2 + "openapi": "3.0.0", 3 + "info": { 4 + "title": "test", 5 + "version": "v1" 6 + }, 7 + "paths": {}, 8 + "components": { 9 + "schemas": { 10 + "Foo": { 11 + "type": "string" 12 + }, 13 + "LoadBalancerSettings": { 14 + "type": "object", 15 + "properties": { 16 + "consistentHash": { 17 + "type": "object", 18 + "properties": { 19 + "httpHeaderName": { 20 + "type": "string" 21 + } 22 + } 23 + }, 24 + "b": { 25 + "type": "string" 26 + } 27 + }, 28 + "oneOf": [ 29 + { 30 + "not": { 31 + "anyOf": [ 32 + { 33 + "required": [ 34 + "consistentHash", 35 + "b" 36 + ], 37 + "properties": { 38 + "consistentHash": { 39 + "oneOf": [ 40 + { 41 + "not": { 42 + "anyOf": [ 43 + { 44 + "required": [ 45 + "httpHeaderName" 46 + ] 47 + } 48 + ] 49 + } 50 + }, 51 + { 52 + "required": [ 53 + "httpHeaderName" 54 + ] 55 + } 56 + ] 57 + } 58 + } 59 + } 60 + ] 61 + } 62 + }, 63 + { 64 + "required": [ 65 + "consistentHash", 66 + "b" 67 + ], 68 + "properties": { 69 + "consistentHash": { 70 + "oneOf": [ 71 + { 72 + "not": { 73 + "anyOf": [ 74 + { 75 + "required": [ 76 + "httpHeaderName" 77 + ] 78 + } 79 + ] 80 + } 81 + }, 82 + { 83 + "required": [ 84 + "httpHeaderName" 85 + ] 86 + } 87 + ] 88 + } 89 + } 90 + } 91 + ] 92 + }, 93 + "LoadBalancerSettings.ConsistentHashLB": { 94 + "type": "object", 95 + "properties": { 96 + "httpHeaderName": { 97 + "type": "string" 98 + } 99 + }, 100 + "oneOf": [ 101 + { 102 + "not": { 103 + "anyOf": [ 104 + { 105 + "required": [ 106 + "httpHeaderName" 107 + ] 108 + } 109 + ] 110 + } 111 + }, 112 + { 113 + "required": [ 114 + "httpHeaderName" 115 + ] 116 + } 117 + ] 118 + } 119 + } 120 + } 121 + }
+11
encoding/openapi/testdata/embed.cue
··· 1 + #Foo: string 2 + 3 + #LoadBalancerSettings: { 4 + {} | { 5 + consistentHash: #ConsistentHashLB 6 + b: #Foo 7 + } 8 + #ConsistentHashLB: {} | { 9 + httpHeaderName: string 10 + } 11 + }
+85
encoding/openapi/testdata/embed.json
··· 1 + { 2 + "openapi": "3.0.0", 3 + "info": { 4 + "title": "Generated by cue.", 5 + "version": "no version" 6 + }, 7 + "paths": {}, 8 + "components": { 9 + "schemas": { 10 + "Foo": { 11 + "type": "string" 12 + }, 13 + "LoadBalancerSettings": { 14 + "type": "object", 15 + "oneOf": [ 16 + { 17 + "not": { 18 + "anyOf": [ 19 + { 20 + "required": [ 21 + "consistentHash", 22 + "b" 23 + ], 24 + "properties": { 25 + "consistentHash": { 26 + "$ref": "#/components/schemas/LoadBalancerSettings.ConsistentHashLB" 27 + }, 28 + "b": { 29 + "$ref": "#/components/schemas/Foo" 30 + } 31 + } 32 + } 33 + ] 34 + } 35 + }, 36 + { 37 + "required": [ 38 + "consistentHash", 39 + "b" 40 + ], 41 + "properties": { 42 + "consistentHash": { 43 + "$ref": "#/components/schemas/LoadBalancerSettings.ConsistentHashLB" 44 + }, 45 + "b": { 46 + "$ref": "#/components/schemas/Foo" 47 + } 48 + } 49 + } 50 + ] 51 + }, 52 + "LoadBalancerSettings.ConsistentHashLB": { 53 + "type": "object", 54 + "oneOf": [ 55 + { 56 + "not": { 57 + "anyOf": [ 58 + { 59 + "required": [ 60 + "httpHeaderName" 61 + ], 62 + "properties": { 63 + "httpHeaderName": { 64 + "type": "string" 65 + } 66 + } 67 + } 68 + ] 69 + } 70 + }, 71 + { 72 + "required": [ 73 + "httpHeaderName" 74 + ], 75 + "properties": { 76 + "httpHeaderName": { 77 + "type": "string" 78 + } 79 + } 80 + } 81 + ] 82 + } 83 + } 84 + } 85 + }