hcldec: Variables must visit deeply-nested specifications

Previously this implementation was doing only one level of recursion in
its walk, which gave the appearance of working until the
transform/container-type specs (DefaultSpec, TransformSpec, ...) were
introduced, creating the possibility of "same body children" being more
than one level away from the initial spec.

It's still correct to only process the schema and content once, because
ImpliedSchema is already collecting all of the requirements from the
"same body children", and so our content object will include everything
that the nested specs should need to analyze needed variables.
This commit is contained in:
Martin Atkins 2018-05-24 12:11:53 -07:00
parent 81d2277300
commit 36446359d2
2 changed files with 40 additions and 7 deletions

View File

@ -15,20 +15,22 @@ import (
// be incomplete, but that's assumed to be okay because the eventual call
// to Decode will produce error diagnostics anyway.
func Variables(body hcl.Body, spec Spec) []hcl.Traversal {
schema := ImpliedSchema(spec)
content, _, _ := body.PartialContent(schema)
var vars []hcl.Traversal
schema := ImpliedSchema(spec)
content, _, _ := body.PartialContent(schema)
if vs, ok := spec.(specNeedingVariables); ok {
vars = append(vars, vs.variablesNeeded(content)...)
}
spec.visitSameBodyChildren(func(s Spec) {
var visitFn visitFunc
visitFn = func(s Spec) {
if vs, ok := s.(specNeedingVariables); ok {
vars = append(vars, vs.variablesNeeded(content)...)
}
})
s.visitSameBodyChildren(visitFn)
}
spec.visitSameBodyChildren(visitFn)
return vars
}

View File

@ -5,8 +5,8 @@ import (
"reflect"
"testing"
"github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/hcl"
"github.com/hashicorp/hcl2/hcl/hclsyntax"
)
func TestVariables(t *testing.T) {
@ -42,6 +42,37 @@ func TestVariables(t *testing.T) {
},
},
},
{
"a = foo\nb = bar\n",
&DefaultSpec{
Primary: &AttrSpec{
Name: "a",
},
Default: &AttrSpec{
Name: "b",
},
},
[]hcl.Traversal{
{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: hcl.Pos{Line: 1, Column: 8, Byte: 7},
},
},
},
{
hcl.TraverseRoot{
Name: "bar",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 5, Byte: 12},
End: hcl.Pos{Line: 2, Column: 8, Byte: 15},
},
},
},
},
},
{
"a = foo\n",
&ObjectSpec{