hcl: ExprList function
This helper allows a calling application to require a given expression be some sort of list constructor (tuple constructor in native syntax, or array in JSON) and peel off that outer level of list to obtain a slice of the Expression objects inside. This is useful in rare cases where the calling application needs to extract the expressions within the list without evaluating the entire list expression first. For example, the expressions that result from this function might be passed into AbsTraversalForExpr in situations where the caller requires a static list of static traversals that will never actually be evaluated.
This commit is contained in:
parent
0949d55133
commit
77c855c5ed
30
hcl/expr_list.go
Normal file
30
hcl/expr_list.go
Normal file
@ -0,0 +1,30 @@
|
||||
package hcl
|
||||
|
||||
// ExprList tests if the given expression is a static list construct and,
|
||||
// if so, extracts the expressions that represent the list elements.
|
||||
// If the given expression is not a static list, error diagnostics are
|
||||
// returned.
|
||||
//
|
||||
// A particular Expression implementation can support this function by
|
||||
// offering a method called ExprList that takes no arguments and returns
|
||||
// []Expression. This method should return nil if a static list cannot
|
||||
// be extracted.
|
||||
func ExprList(expr Expression) ([]Expression, Diagnostics) {
|
||||
type exprList interface {
|
||||
ExprList() []Expression
|
||||
}
|
||||
|
||||
if exL, supported := expr.(exprList); supported {
|
||||
if list := exL.ExprList(); list != nil {
|
||||
return list, nil
|
||||
}
|
||||
}
|
||||
return nil, Diagnostics{
|
||||
&Diagnostic{
|
||||
Severity: DiagError,
|
||||
Summary: "Invalid expression",
|
||||
Detail: "A static list expression is required.",
|
||||
Subject: expr.StartRange().Ptr(),
|
||||
},
|
||||
}
|
||||
}
|
@ -544,6 +544,15 @@ func (e *TupleConsExpr) StartRange() hcl.Range {
|
||||
return e.OpenRange
|
||||
}
|
||||
|
||||
// Implementation for hcl.ExprList
|
||||
func (e *TupleConsExpr) ExprList() []hcl.Expression {
|
||||
ret := make([]hcl.Expression, len(e.Exprs))
|
||||
for i, expr := range e.Exprs {
|
||||
ret[i] = expr
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type ObjectConsExpr struct {
|
||||
Items []ObjectConsItem
|
||||
|
||||
|
@ -1101,3 +1101,21 @@ func TestExpressionAsTraversal(t *testing.T) {
|
||||
t.Fatalf("wrong root name %q; want %q", traversal.RootName(), "a")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStaticExpressionList(t *testing.T) {
|
||||
expr, _ := ParseExpression([]byte("[0, a, true]"), "", hcl.Pos{})
|
||||
exprs, diags := hcl.ExprList(expr)
|
||||
if len(diags) != 0 {
|
||||
t.Fatalf("unexpected diagnostics")
|
||||
}
|
||||
if len(exprs) != 3 {
|
||||
t.Fatalf("wrong result %#v; want length 3", exprs)
|
||||
}
|
||||
first, ok := exprs[0].(*LiteralValueExpr)
|
||||
if !ok {
|
||||
t.Fatalf("first expr has wrong type %T; want *zclsyntax.LiteralValueExpr", exprs[0])
|
||||
}
|
||||
if !first.Val.RawEquals(cty.Zero) {
|
||||
t.Fatalf("wrong first value %#v; want cty.Zero", first.Val)
|
||||
}
|
||||
}
|
||||
|
@ -370,3 +370,17 @@ func (e *expression) AsTraversal() hcl.Traversal {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation for hcl.ExprList.
|
||||
func (e *expression) ExprList() []hcl.Expression {
|
||||
switch v := e.src.(type) {
|
||||
case *arrayVal:
|
||||
ret := make([]hcl.Expression, len(v.Values))
|
||||
for i, node := range v.Values {
|
||||
ret[i] = &expression{src: node}
|
||||
}
|
||||
return ret
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -753,3 +753,22 @@ func TestExpressionAsTraversal(t *testing.T) {
|
||||
t.Fatalf("incorrect traversal %#v; want length 3", traversal)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStaticExpressionList(t *testing.T) {
|
||||
e := &expression{
|
||||
src: &arrayVal{
|
||||
Values: []node{
|
||||
&stringVal{
|
||||
Value: "hello",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
exprs := e.ExprList()
|
||||
if len(exprs) != 1 {
|
||||
t.Fatalf("incorrect exprs %#v; want length 1", exprs)
|
||||
}
|
||||
if exprs[0].(*expression).src != e.src.(*arrayVal).Values[0] {
|
||||
t.Fatalf("wrong first expression node")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user