addrs: Don't return zero-length slice in Reference.Remaining.
Although this rarely matters, making it always be nil when empty makes deep assertions simpler in tests. This also includes a minor update to the test in the core package that first encountered this problem, to improve the quality of its output on failure.
This commit is contained in:
parent
e1bc27ef6c
commit
26e820d829
|
@ -28,6 +28,48 @@ type Reference struct {
|
||||||
// If error diagnostics are returned then the Reference value is invalid and
|
// If error diagnostics are returned then the Reference value is invalid and
|
||||||
// must not be used.
|
// must not be used.
|
||||||
func ParseRef(traversal hcl.Traversal) (*Reference, tfdiags.Diagnostics) {
|
func ParseRef(traversal hcl.Traversal) (*Reference, tfdiags.Diagnostics) {
|
||||||
|
ref, diags := parseRef(traversal)
|
||||||
|
|
||||||
|
// Normalize a little to make life easier for callers.
|
||||||
|
if ref != nil {
|
||||||
|
if len(ref.Remaining) == 0 {
|
||||||
|
ref.Remaining = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref, diags
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseRefStr is a helper wrapper around ParseRef that takes a string
|
||||||
|
// and parses it with the HCL native syntax traversal parser before
|
||||||
|
// interpreting it.
|
||||||
|
//
|
||||||
|
// This should be used only in specialized situations since it will cause the
|
||||||
|
// created references to not have any meaningful source location information.
|
||||||
|
// If a reference string is coming from a source that should be identified in
|
||||||
|
// error messages then the caller should instead parse it directly using a
|
||||||
|
// suitable function from the HCL API and pass the traversal itself to
|
||||||
|
// ParseRef.
|
||||||
|
//
|
||||||
|
// Error diagnostics are returned if either the parsing fails or the analysis
|
||||||
|
// of the traversal fails. There is no way for the caller to distinguish the
|
||||||
|
// two kinds of diagnostics programmatically. If error diagnostics are returned
|
||||||
|
// the returned reference may be nil or incomplete.
|
||||||
|
func ParseRefStr(str string) (*Reference, tfdiags.Diagnostics) {
|
||||||
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
|
traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
|
||||||
|
diags = diags.Append(parseDiags)
|
||||||
|
if parseDiags.HasErrors() {
|
||||||
|
return nil, diags
|
||||||
|
}
|
||||||
|
|
||||||
|
ref, targetDiags := ParseRef(traversal)
|
||||||
|
diags = diags.Append(targetDiags)
|
||||||
|
return ref, diags
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRef(traversal hcl.Traversal) (*Reference, tfdiags.Diagnostics) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
root := traversal.RootName()
|
root := traversal.RootName()
|
||||||
|
@ -174,35 +216,6 @@ func ParseRef(traversal hcl.Traversal) (*Reference, tfdiags.Diagnostics) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseRefStr is a helper wrapper around ParseRef that takes a string
|
|
||||||
// and parses it with the HCL native syntax traversal parser before
|
|
||||||
// interpreting it.
|
|
||||||
//
|
|
||||||
// This should be used only in specialized situations since it will cause the
|
|
||||||
// created references to not have any meaningful source location information.
|
|
||||||
// If a reference string is coming from a source that should be identified in
|
|
||||||
// error messages then the caller should instead parse it directly using a
|
|
||||||
// suitable function from the HCL API and pass the traversal itself to
|
|
||||||
// ParseRef.
|
|
||||||
//
|
|
||||||
// Error diagnostics are returned if either the parsing fails or the analysis
|
|
||||||
// of the traversal fails. There is no way for the caller to distinguish the
|
|
||||||
// two kinds of diagnostics programmatically. If error diagnostics are returned
|
|
||||||
// the returned reference may be nil or incomplete.
|
|
||||||
func ParseRefStr(str string) (*Reference, tfdiags.Diagnostics) {
|
|
||||||
var diags tfdiags.Diagnostics
|
|
||||||
|
|
||||||
traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
|
|
||||||
diags = diags.Append(parseDiags)
|
|
||||||
if parseDiags.HasErrors() {
|
|
||||||
return nil, diags
|
|
||||||
}
|
|
||||||
|
|
||||||
ref, targetDiags := ParseRef(traversal)
|
|
||||||
diags = diags.Append(targetDiags)
|
|
||||||
return ref, diags
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseResourceRef(mode ResourceMode, startRange hcl.Range, traversal hcl.Traversal) (*Reference, tfdiags.Diagnostics) {
|
func parseResourceRef(mode ResourceMode, startRange hcl.Range, traversal hcl.Traversal) (*Reference, tfdiags.Diagnostics) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
|
@ -271,7 +284,6 @@ func parseResourceRef(mode ResourceMode, startRange hcl.Range, traversal hcl.Tra
|
||||||
return &Reference{
|
return &Reference{
|
||||||
Subject: resourceInstAddr,
|
Subject: resourceInstAddr,
|
||||||
SourceRange: tfdiags.SourceRangeFromHCL(rng),
|
SourceRange: tfdiags.SourceRangeFromHCL(rng),
|
||||||
Remaining: remain,
|
|
||||||
}, diags
|
}, diags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-test/deep"
|
||||||
"github.com/hashicorp/hcl2/hcl"
|
"github.com/hashicorp/hcl2/hcl"
|
||||||
"github.com/hashicorp/hcl2/hcl/hclsyntax"
|
"github.com/hashicorp/hcl2/hcl/hclsyntax"
|
||||||
|
|
||||||
|
@ -72,14 +73,14 @@ func TestNodeApplyableModuleVariableReference(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := []*addrs.Reference{
|
want := []*addrs.Reference{
|
||||||
{
|
{
|
||||||
Subject: addrs.InputVariable{Name: "foo"},
|
Subject: addrs.InputVariable{Name: "foo"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
actual := n.References()
|
got := n.References()
|
||||||
if !reflect.DeepEqual(actual, expected) {
|
for _, problem := range deep.Equal(got, want) {
|
||||||
t.Fatalf("%#v != %#v", actual, expected)
|
t.Error(problem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,13 +101,13 @@ func TestNodeApplyableModuleVariableReference_grandchild(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := []*addrs.Reference{
|
want := []*addrs.Reference{
|
||||||
{
|
{
|
||||||
Subject: addrs.InputVariable{Name: "foo"},
|
Subject: addrs.InputVariable{Name: "foo"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
actual := n.References()
|
got := n.References()
|
||||||
if !reflect.DeepEqual(actual, expected) {
|
for _, problem := range deep.Equal(got, want) {
|
||||||
t.Fatalf("%#v != %#v", actual, expected)
|
t.Error(problem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue