hcl: ExprMap function
This is similar to the ExprList function but for map-like constructs (object constructors in the native syntax). It allows a more-advanced calling application to analyze the physical structure of the configuration directly, rather than analyzing the dynamic results of its expressions. This is useful when creating what appear to be first-class language constructs out of the language's grammar elements. In the JSON syntax, a static map construct is expressed as a direct JSON object. As with ExprList, this bypasses any dynamic expression evaluation behavior and requires the user to provide a literal JSON object, though the calling application is then free to evaluate the key/value expressions inside in whatever way makes sense.
This commit is contained in:
parent
8c3aa9a6d4
commit
397fa07dea
44
hcl/expr_map.go
Normal file
44
hcl/expr_map.go
Normal file
@ -0,0 +1,44 @@
|
||||
package hcl
|
||||
|
||||
// ExprMap tests if the given expression is a static map construct and,
|
||||
// if so, extracts the expressions that represent the map elements.
|
||||
// If the given expression is not a static map, error diagnostics are
|
||||
// returned.
|
||||
//
|
||||
// A particular Expression implementation can support this function by
|
||||
// offering a method called ExprMap that takes no arguments and returns
|
||||
// []KeyValuePair. This method should return nil if a static map cannot
|
||||
// be extracted. Alternatively, an implementation can support
|
||||
// UnwrapExpression to delegate handling of this function to a wrapped
|
||||
// Expression object.
|
||||
func ExprMap(expr Expression) ([]KeyValuePair, Diagnostics) {
|
||||
type exprMap interface {
|
||||
ExprMap() []KeyValuePair
|
||||
}
|
||||
|
||||
physExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {
|
||||
_, supported := expr.(exprMap)
|
||||
return supported
|
||||
})
|
||||
|
||||
if exM, supported := physExpr.(exprMap); supported {
|
||||
if pairs := exM.ExprMap(); pairs != nil {
|
||||
return pairs, nil
|
||||
}
|
||||
}
|
||||
return nil, Diagnostics{
|
||||
&Diagnostic{
|
||||
Severity: DiagError,
|
||||
Summary: "Invalid expression",
|
||||
Detail: "A static map expression is required.",
|
||||
Subject: expr.StartRange().Ptr(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// KeyValuePair represents a pair of expressions that serve as a single item
|
||||
// within a map or object definition construct.
|
||||
type KeyValuePair struct {
|
||||
Key Expression
|
||||
Value Expression
|
||||
}
|
@ -648,6 +648,18 @@ func (e *ObjectConsExpr) StartRange() hcl.Range {
|
||||
return e.OpenRange
|
||||
}
|
||||
|
||||
// Implementation for hcl.ExprMap
|
||||
func (e *ObjectConsExpr) ExprMap() []hcl.KeyValuePair {
|
||||
ret := make([]hcl.KeyValuePair, len(e.Items))
|
||||
for i, item := range e.Items {
|
||||
ret[i] = hcl.KeyValuePair{
|
||||
Key: item.KeyExpr,
|
||||
Value: item.ValueExpr,
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ForExpr represents iteration constructs:
|
||||
//
|
||||
// tuple = [for i, v in list: upper(v) if i > 2]
|
||||
|
@ -571,3 +571,23 @@ func (e *expression) ExprList() []hcl.Expression {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation for hcl.ExprMap.
|
||||
func (e *expression) ExprMap() []hcl.KeyValuePair {
|
||||
switch v := e.src.(type) {
|
||||
case *objectVal:
|
||||
ret := make([]hcl.KeyValuePair, len(v.Attrs))
|
||||
for i, jsonAttr := range v.Attrs {
|
||||
ret[i] = hcl.KeyValuePair{
|
||||
Key: &expression{src: &stringVal{
|
||||
Value: jsonAttr.Name,
|
||||
SrcRange: jsonAttr.NameRange,
|
||||
}},
|
||||
Value: &expression{src: jsonAttr.Value},
|
||||
}
|
||||
}
|
||||
return ret
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user