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"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/hcl2/hcl/hclsyntax"
|
|
||||||
"github.com/hashicorp/hcl2/hcl"
|
"github.com/hashicorp/hcl2/hcl"
|
||||||
|
"github.com/hashicorp/hcl2/hcl/hclsyntax"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -56,6 +56,36 @@ func TestDecode(t *testing.T) {
|
|||||||
cty.NumberIntVal(1),
|
cty.NumberIntVal(1),
|
||||||
0,
|
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",
|
"a = \"1\"\n",
|
||||||
&AttrSpec{
|
&AttrSpec{
|
||||||
|
@ -566,3 +566,33 @@ func (s *BlockLabelSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block)
|
|||||||
|
|
||||||
return block.LabelRanges[s.Index]
|
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 blockSetSpecAsSpec Spec = (*BlockSetSpec)(nil)
|
||||||
var blockMapSpecAsSpec Spec = (*BlockMapSpec)(nil)
|
var blockMapSpecAsSpec Spec = (*BlockMapSpec)(nil)
|
||||||
var blockLabelSpecAsSpec Spec = (*BlockLabelSpec)(nil)
|
var blockLabelSpecAsSpec Spec = (*BlockLabelSpec)(nil)
|
||||||
|
var defaultSepcAsSpec Spec = (*DefaultSpec)(nil)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user