Ability to look up the variables in an expression
This commit is contained in:
parent
73b5ba8089
commit
1535d4b708
@ -571,3 +571,7 @@ func (e *fixedExpression) Range() (r zcl.Range) {
|
|||||||
func (e *fixedExpression) StartRange() (r zcl.Range) {
|
func (e *fixedExpression) StartRange() (r zcl.Range) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *fixedExpression) Variables() []zcl.Traversal {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -310,6 +310,34 @@ func (e *expression) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
|
|||||||
return ctyValueFromHCLNode(e.src, ctx)
|
return ctyValueFromHCLNode(e.src, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *expression) Variables() []zcl.Traversal {
|
||||||
|
node := e.src
|
||||||
|
var vars []zcl.Traversal
|
||||||
|
|
||||||
|
switch tn := node.(type) {
|
||||||
|
case *hclast.LiteralType:
|
||||||
|
tok := tn.Token
|
||||||
|
switch tok.Type {
|
||||||
|
case hcltoken.STRING, hcltoken.HEREDOC:
|
||||||
|
// TODO: HIL parsing and evaluation, if ctx is non-nil.
|
||||||
|
}
|
||||||
|
case *hclast.ObjectType:
|
||||||
|
list := tn.List
|
||||||
|
attrs, _ := (&body{oli: list}).JustAttributes()
|
||||||
|
if attrs != nil {
|
||||||
|
for _, attr := range attrs {
|
||||||
|
vars = append(vars, attr.Expr.Variables()...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *hclast.ListType:
|
||||||
|
nodes := tn.List
|
||||||
|
for _, node := range nodes {
|
||||||
|
vars = append(vars, (&expression{src: node}).Variables()...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vars
|
||||||
|
}
|
||||||
|
|
||||||
func (e *expression) Range() zcl.Range {
|
func (e *expression) Range() zcl.Range {
|
||||||
return rangeFromHCLPos(e.src.Pos())
|
return rangeFromHCLPos(e.src.Pos())
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package hclhil
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/apparentlymart/go-cty/cty"
|
"github.com/apparentlymart/go-cty/cty"
|
||||||
"github.com/apparentlymart/go-cty/cty/function"
|
"github.com/apparentlymart/go-cty/cty/function"
|
||||||
@ -45,6 +46,58 @@ func (e *templateExpression) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnos
|
|||||||
return ctyValueFromHILNode(e.node, cfg)
|
return ctyValueFromHILNode(e.node, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *templateExpression) Variables() []zcl.Traversal {
|
||||||
|
var vars []zcl.Traversal
|
||||||
|
e.node.Accept(func(n hilast.Node) hilast.Node {
|
||||||
|
vn, ok := n.(*hilast.VariableAccess)
|
||||||
|
if !ok {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
rawName := vn.Name
|
||||||
|
parts := strings.Split(rawName, ".")
|
||||||
|
if len(parts) == 0 {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
tr := make(zcl.Traversal, 0, len(parts))
|
||||||
|
tr = append(tr, zcl.TraverseRoot{
|
||||||
|
Name: parts[0],
|
||||||
|
SrcRange: rangeFromHILPos(n.Pos()),
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, name := range parts {
|
||||||
|
if nv, err := strconv.Atoi(name); err == nil {
|
||||||
|
// Turn this into a sequence index in zcl land, to save
|
||||||
|
// callers from having to understand both HIL-style numeric
|
||||||
|
// attributes and zcl-style indices.
|
||||||
|
tr = append(tr, zcl.TraverseIndex{
|
||||||
|
Key: cty.NumberIntVal(int64(nv)),
|
||||||
|
SrcRange: rangeFromHILPos(n.Pos()),
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "*" {
|
||||||
|
// TODO: support splat traversals, but that requires some
|
||||||
|
// more work here because we need to then accumulate the
|
||||||
|
// rest of the parts into the splat's own "Each" traversal.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tr = append(tr, zcl.TraverseAttr{
|
||||||
|
Name: name,
|
||||||
|
SrcRange: rangeFromHILPos(n.Pos()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
vars = append(vars, tr)
|
||||||
|
|
||||||
|
return n
|
||||||
|
})
|
||||||
|
return vars
|
||||||
|
}
|
||||||
|
|
||||||
func (e *templateExpression) Range() zcl.Range {
|
func (e *templateExpression) Range() zcl.Range {
|
||||||
return rangeFromHILPos(e.node.Pos())
|
return rangeFromHILPos(e.node.Pos())
|
||||||
}
|
}
|
||||||
|
@ -307,6 +307,45 @@ func (e *expression) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *expression) Variables() []zcl.Traversal {
|
||||||
|
var vars []zcl.Traversal
|
||||||
|
|
||||||
|
switch v := e.src.(type) {
|
||||||
|
case *stringVal:
|
||||||
|
if e.useHIL {
|
||||||
|
// Legacy interface to parse HCL-style JSON with HIL expressions.
|
||||||
|
templateSrc := v.Value
|
||||||
|
hilExpr, _ := hclhil.ParseTemplateEmbedded(
|
||||||
|
[]byte(templateSrc),
|
||||||
|
v.SrcRange.Filename,
|
||||||
|
zcl.Pos{
|
||||||
|
// skip over the opening quote mark
|
||||||
|
Byte: v.SrcRange.Start.Byte + 1,
|
||||||
|
Line: v.SrcRange.Start.Line,
|
||||||
|
Column: v.SrcRange.Start.Column,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if hilExpr != nil {
|
||||||
|
vars = append(vars, hilExpr.Variables()...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Once the native zcl template language parser is implemented,
|
||||||
|
// parse with that and look for variables in there too,
|
||||||
|
|
||||||
|
case *arrayVal:
|
||||||
|
for _, jsonVal := range v.Values {
|
||||||
|
vars = append(vars, (&expression{src: jsonVal, useHIL: e.useHIL}).Variables()...)
|
||||||
|
}
|
||||||
|
case *objectVal:
|
||||||
|
for _, jsonAttr := range v.Attrs {
|
||||||
|
vars = append(vars, (&expression{src: jsonAttr.Value, useHIL: e.useHIL}).Variables()...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vars
|
||||||
|
}
|
||||||
|
|
||||||
func (e *expression) Range() zcl.Range {
|
func (e *expression) Range() zcl.Range {
|
||||||
return e.src.Range()
|
return e.src.Range()
|
||||||
}
|
}
|
||||||
|
@ -110,12 +110,15 @@ type Expression interface {
|
|||||||
// the specific symbol in question.
|
// the specific symbol in question.
|
||||||
Value(ctx *EvalContext) (cty.Value, Diagnostics)
|
Value(ctx *EvalContext) (cty.Value, Diagnostics)
|
||||||
|
|
||||||
|
// Variables returns a list of variables referenced in the receiving
|
||||||
|
// expression. These are expressed as absolute Traversals, so may include
|
||||||
|
// additional information about how the variable is used, such as
|
||||||
|
// attribute lookups, which the calling application can potentially use
|
||||||
|
// to only selectively populate the scope.
|
||||||
|
Variables() []Traversal
|
||||||
|
|
||||||
Range() Range
|
Range() Range
|
||||||
StartRange() Range
|
StartRange() Range
|
||||||
|
|
||||||
// TODO: A "Variables" method that returns a description of all of the
|
|
||||||
// variables used in the expression, so callers can populate the scope
|
|
||||||
// only with variables that are actually used.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OfType filters the receiving block sequence by block type name,
|
// OfType filters the receiving block sequence by block type name,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user