...

Source file src/cuelang.org/go/internal/core/validate/validate.go

Documentation: cuelang.org/go/internal/core/validate

     1  // Copyright 2020 CUE Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package validate collects errors from an evaluated Vertex.
    16  package validate
    17  
    18  import (
    19  	"cuelang.org/go/internal/core/adt"
    20  )
    21  
    22  type Config struct {
    23  	// Concrete, if true, requires that all values be concrete.
    24  	Concrete bool
    25  
    26  	// Final, if true, checks that there are no required fields left.
    27  	Final bool
    28  
    29  	// DisallowCycles indicates that there may not be cycles.
    30  	DisallowCycles bool
    31  
    32  	// AllErrors continues descending into a Vertex, even if errors are found.
    33  	AllErrors bool
    34  
    35  	// TODO: omitOptional, if this is becomes relevant.
    36  }
    37  
    38  // Validate checks that a value has certain properties. The value must have
    39  // been evaluated.
    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