hcl: ExprCall function
This accompanies ExprList, ExprMap, and AbsTraversalForExpr to complete the set of static analysis interfaces for digging down into the expression syntax structures without evaluation. The intent of this function is to be a little like AbsTraversalForExpr but for function calls. However, it's also similar to ExprList in that it gives access to the raw expression objects for the arguments, allowing for recursive analysis.
This commit is contained in:
parent
92456935b8
commit
5956048526
46
hcl/expr_call.go
Normal file
46
hcl/expr_call.go
Normal file
@ -0,0 +1,46 @@
|
||||
package hcl
|
||||
|
||||
// ExprCall tests if the given expression is a function call and,
|
||||
// if so, extracts the function name and the expressions that represent
|
||||
// the arguments. If the given expression is not statically a function call,
|
||||
// error diagnostics are returned.
|
||||
//
|
||||
// A particular Expression implementation can support this function by
|
||||
// offering a method called ExprCall that takes no arguments and returns
|
||||
// *StaticCall. This method should return nil if a static call cannot
|
||||
// be extracted. Alternatively, an implementation can support
|
||||
// UnwrapExpression to delegate handling of this function to a wrapped
|
||||
// Expression object.
|
||||
func ExprCall(expr Expression) (*StaticCall, Diagnostics) {
|
||||
type exprCall interface {
|
||||
ExprCall() *StaticCall
|
||||
}
|
||||
|
||||
physExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {
|
||||
_, supported := expr.(exprCall)
|
||||
return supported
|
||||
})
|
||||
|
||||
if exC, supported := physExpr.(exprCall); supported {
|
||||
if call := exC.ExprCall(); call != nil {
|
||||
return call, nil
|
||||
}
|
||||
}
|
||||
return nil, Diagnostics{
|
||||
&Diagnostic{
|
||||
Severity: DiagError,
|
||||
Summary: "Invalid expression",
|
||||
Detail: "A static function call is required.",
|
||||
Subject: expr.StartRange().Ptr(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// StaticCall represents a function call that was extracted statically from
|
||||
// an expression using ExprCall.
|
||||
type StaticCall struct {
|
||||
Name string
|
||||
NameRange Range
|
||||
Arguments []Expression
|
||||
ArgsRange Range
|
||||
}
|
@ -417,6 +417,21 @@ func (e *FunctionCallExpr) StartRange() hcl.Range {
|
||||
return hcl.RangeBetween(e.NameRange, e.OpenParenRange)
|
||||
}
|
||||
|
||||
// Implementation for hcl.ExprCall.
|
||||
func (e *FunctionCallExpr) ExprCall() *hcl.StaticCall {
|
||||
ret := &hcl.StaticCall{
|
||||
Name: e.Name,
|
||||
NameRange: e.NameRange,
|
||||
Arguments: make([]hcl.Expression, len(e.Args)),
|
||||
ArgsRange: hcl.RangeBetween(e.OpenParenRange, e.CloseParenRange),
|
||||
}
|
||||
// Need to convert our own Expression objects into hcl.Expression.
|
||||
for i, arg := range e.Args {
|
||||
ret.Arguments[i] = arg
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type ConditionalExpr struct {
|
||||
Condition Expression
|
||||
TrueResult Expression
|
||||
|
@ -558,6 +558,29 @@ func (e *expression) AsTraversal() hcl.Traversal {
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation for hcl.ExprCall.
|
||||
func (e *expression) ExprCall() *hcl.StaticCall {
|
||||
// In JSON-based syntax a static call is given as a string containing
|
||||
// an expression in the native syntax that also supports ExprCall.
|
||||
|
||||
switch v := e.src.(type) {
|
||||
case *stringVal:
|
||||
expr, diags := hclsyntax.ParseExpression([]byte(v.Value), v.SrcRange.Filename, v.SrcRange.Start)
|
||||
if diags.HasErrors() {
|
||||
return nil
|
||||
}
|
||||
|
||||
call, diags := hcl.ExprCall(expr)
|
||||
if diags.HasErrors() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return call
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation for hcl.ExprList.
|
||||
func (e *expression) ExprList() []hcl.Expression {
|
||||
switch v := e.src.(type) {
|
||||
|
Loading…
Reference in New Issue
Block a user