...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package validate
17
18 import (
19 "cuelang.org/go/internal/core/adt"
20 )
21
22 type Config struct {
23
24 Concrete bool
25
26
27 Final bool
28
29
30 DisallowCycles bool
31
32
33 AllErrors bool
34
35
36 }
37
38
39
40 func Validate(ctx *adt.OpContext, v *adt.Vertex, cfg *Config) *adt.Bottom {
41 if cfg == nil {
42 cfg = &Config{}
43 }
44 x := validator{Config: *cfg, ctx: ctx}
45 x.validate(v)
46 return x.err
47 }
48
49 type validator struct {
50 Config
51 ctx *adt.OpContext
52 err *adt.Bottom
53 inDefinition int
54 }
55
56 func (v *validator) checkConcrete() bool {
57 return v.Concrete && v.inDefinition == 0
58 }
59
60 func (v *validator) add(b *adt.Bottom) {
61 if !v.AllErrors {
62 v.err = adt.CombineErrors(nil, v.err, b)
63 return
64 }
65 if !b.ChildError {
66 v.err = adt.CombineErrors(nil, v.err, b)
67 }
68 }
69
70 func (v *validator) validate(x *adt.Vertex) {
71 defer v.ctx.PopArc(v.ctx.PushArc(x))
72
73 if b, _ := x.BaseValue.(*adt.Bottom); b != nil {
74 switch b.Code {
75 case adt.CycleError:
76 if v.checkConcrete() || v.DisallowCycles {
77 v.add(b)
78 }
79
80 case adt.IncompleteError:
81 if v.checkConcrete() {
82 v.add(b)
83 }
84
85 default:
86 v.add(b)
87 }
88 if !b.HasRecursive {
89 return
90 }
91
92 } else if v.checkConcrete() {
93 x = x.Default()
94 if !adt.IsConcrete(x) {
95 x := x.Value()
96 v.add(&adt.Bottom{
97 Code: adt.IncompleteError,
98 Err: v.ctx.Newf("incomplete value %v", x),
99 })
100 }
101 }
102
103 for _, a := range x.Arcs {
104 if a.ArcType == adt.ArcRequired && v.Final && v.inDefinition == 0 {
105 v.add(adt.NewRequiredNotPresentError(v.ctx, a))
106 continue
107 }
108
109 if a.Label.IsLet() || !a.IsDefined(v.ctx) {
110 continue
111 }
112 if !v.AllErrors && v.err != nil {
113 break
114 }
115 if a.Label.IsRegular() {
116 v.validate(a)
117 } else {
118 v.inDefinition++
119 v.validate(a)
120 v.inDefinition--
121 }
122 }
123 }
124
View as plain text