hcldec: New DefaultSpec specification
This is a wrapper that allows a default value to be applied if a primary spec results in a null value.
This commit is contained in:
parent
f44382c4fa
commit
a4ee7188ad
@ -5,8 +5,8 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/hcl2/hcl/hclsyntax"
|
||||
"github.com/hashicorp/hcl2/hcl"
|
||||
"github.com/hashicorp/hcl2/hcl/hclsyntax"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
@ -56,6 +56,36 @@ func TestDecode(t *testing.T) {
|
||||
cty.NumberIntVal(1),
|
||||
0,
|
||||
},
|
||||
{
|
||||
"a = 1\n",
|
||||
&DefaultSpec{
|
||||
Primary: &AttrSpec{
|
||||
Name: "a",
|
||||
Type: cty.Number,
|
||||
},
|
||||
Default: &LiteralSpec{
|
||||
Value: cty.NumberIntVal(10),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
cty.NumberIntVal(1),
|
||||
0,
|
||||
},
|
||||
{
|
||||
"",
|
||||
&DefaultSpec{
|
||||
Primary: &AttrSpec{
|
||||
Name: "a",
|
||||
Type: cty.Number,
|
||||
},
|
||||
Default: &LiteralSpec{
|
||||
Value: cty.NumberIntVal(10),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
cty.NumberIntVal(10),
|
||||
0,
|
||||
},
|
||||
{
|
||||
"a = \"1\"\n",
|
||||
&AttrSpec{
|
||||
|
@ -566,3 +566,33 @@ func (s *BlockLabelSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block)
|
||||
|
||||
return block.LabelRanges[s.Index]
|
||||
}
|
||||
|
||||
// DefaultSpec is a spec that wraps two specs, evaluating the primary first
|
||||
// and then evaluating the default if the primary returns a null value.
|
||||
type DefaultSpec struct {
|
||||
Primary Spec
|
||||
Default Spec
|
||||
}
|
||||
|
||||
func (s *DefaultSpec) visitSameBodyChildren(cb visitFunc) {
|
||||
cb(s.Primary)
|
||||
cb(s.Default)
|
||||
}
|
||||
|
||||
func (s *DefaultSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
|
||||
val, diags := s.Primary.decode(content, block, ctx)
|
||||
if val.IsNull() {
|
||||
var moreDiags hcl.Diagnostics
|
||||
val, moreDiags = s.Default.decode(content, block, ctx)
|
||||
diags = append(diags, moreDiags...)
|
||||
}
|
||||
return val, diags
|
||||
}
|
||||
|
||||
func (s *DefaultSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
|
||||
// We can't tell from here which of the two specs will ultimately be used
|
||||
// in our result, so we'll just assume the first. This is usually the right
|
||||
// choice because the default is often a literal spec that doesn't have a
|
||||
// reasonable source range to return anyway.
|
||||
return s.Primary.sourceRange(content, block)
|
||||
}
|
||||
|
@ -11,3 +11,4 @@ var blockListSpecAsSpec Spec = (*BlockListSpec)(nil)
|
||||
var blockSetSpecAsSpec Spec = (*BlockSetSpec)(nil)
|
||||
var blockMapSpecAsSpec Spec = (*BlockMapSpec)(nil)
|
||||
var blockLabelSpecAsSpec Spec = (*BlockLabelSpec)(nil)
|
||||
var defaultSepcAsSpec Spec = (*DefaultSpec)(nil)
|
||||
|
Loading…
Reference in New Issue
Block a user