hcl: Export the source range for a Traversal

This can be useful, for example, when using Expression.Variables to
pre-validate all of the referenced variables before evaluation, so that
the traversal source ranges can be included in any generated diagnostics.
This commit is contained in:
Martin Atkins 2018-01-13 23:01:11 -08:00
parent f3af67f344
commit 600e8726ec

View File

@ -156,6 +156,17 @@ func (t Traversal) RootName() string {
return t[0].(TraverseRoot).Name return t[0].(TraverseRoot).Name
} }
// SourceRange returns the source range for the traversal.
func (t Traversal) SourceRange() Range {
if len(t) == 0 {
// Nothing useful to return here, but we'll return something
// that's correctly-typed at least.
return Range{}
}
return RangeBetween(t[0].SourceRange(), t[len(t)-1].SourceRange())
}
// TraversalSplit represents a pair of traversals, the first of which is // TraversalSplit represents a pair of traversals, the first of which is
// an absolute traversal and the second of which is relative to the first. // an absolute traversal and the second of which is relative to the first.
// //
@ -206,6 +217,7 @@ func (t TraversalSplit) RootName() string {
// A Traverser is a step within a Traversal. // A Traverser is a step within a Traversal.
type Traverser interface { type Traverser interface {
TraversalStep(cty.Value) (cty.Value, Diagnostics) TraversalStep(cty.Value) (cty.Value, Diagnostics)
SourceRange() Range
isTraverserSigil() isTraverser isTraverserSigil() isTraverser
} }
@ -231,6 +243,10 @@ func (tn TraverseRoot) TraversalStep(cty.Value) (cty.Value, Diagnostics) {
panic("Cannot traverse an absolute traversal") panic("Cannot traverse an absolute traversal")
} }
func (tn TraverseRoot) SourceRange() Range {
return tn.SrcRange
}
// TraverseAttr looks up an attribute in its initial value. // TraverseAttr looks up an attribute in its initial value.
type TraverseAttr struct { type TraverseAttr struct {
isTraverser isTraverser
@ -301,6 +317,10 @@ func (tn TraverseAttr) TraversalStep(val cty.Value) (cty.Value, Diagnostics) {
} }
} }
func (tn TraverseAttr) SourceRange() Range {
return tn.SrcRange
}
// TraverseIndex applies the index operation to its initial value. // TraverseIndex applies the index operation to its initial value.
type TraverseIndex struct { type TraverseIndex struct {
isTraverser isTraverser
@ -312,6 +332,10 @@ func (tn TraverseIndex) TraversalStep(val cty.Value) (cty.Value, Diagnostics) {
return Index(val, tn.Key, &tn.SrcRange) return Index(val, tn.Key, &tn.SrcRange)
} }
func (tn TraverseIndex) SourceRange() Range {
return tn.SrcRange
}
// TraverseSplat applies the splat operation to its initial value. // TraverseSplat applies the splat operation to its initial value.
type TraverseSplat struct { type TraverseSplat struct {
isTraverser isTraverser
@ -322,3 +346,7 @@ type TraverseSplat struct {
func (tn TraverseSplat) TraversalStep(val cty.Value) (cty.Value, Diagnostics) { func (tn TraverseSplat) TraversalStep(val cty.Value) (cty.Value, Diagnostics) {
panic("TraverseSplat not yet implemented") panic("TraverseSplat not yet implemented")
} }
func (tn TraverseSplat) SourceRange() Range {
return tn.SrcRange
}