7 "github.com/hashicorp/hcl2/hcl"
8 "github.com/zclconf/go-cty/cty"
9 "github.com/zclconf/go-cty/cty/convert"
12 type TemplateExpr struct {
18 func (e *TemplateExpr) walkChildNodes(w internalWalkFunc) {
19 for _, part := range e.Parts {
24 func (e *TemplateExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
25 buf := &bytes.Buffer{}
26 var diags hcl.Diagnostics
29 for _, part := range e.Parts {
30 partVal, partDiags := part.Value(ctx)
31 diags = append(diags, partDiags...)
34 diags = append(diags, &hcl.Diagnostic{
35 Severity: hcl.DiagError,
36 Summary: "Invalid template interpolation value",
38 "The expression result is null. Cannot include a null value in a string template.",
40 Subject: part.Range().Ptr(),
48 if !partVal.IsKnown() {
49 // If any part is unknown then the result as a whole must be
50 // unknown too. We'll keep on processing the rest of the parts
51 // anyway, because we want to still emit any diagnostics resulting
52 // from evaluating those.
57 strVal, err := convert.Convert(partVal, cty.String)
59 diags = append(diags, &hcl.Diagnostic{
60 Severity: hcl.DiagError,
61 Summary: "Invalid template interpolation value",
63 "Cannot include the given value in a string template: %s.",
66 Subject: part.Range().Ptr(),
74 buf.WriteString(strVal.AsString())
78 return cty.UnknownVal(cty.String), diags
81 return cty.StringVal(buf.String()), diags
84 func (e *TemplateExpr) Range() hcl.Range {
88 func (e *TemplateExpr) StartRange() hcl.Range {
89 return e.Parts[0].StartRange()
92 // TemplateJoinExpr is used to convert tuples of strings produced by template
93 // constructs (i.e. for loops) into flat strings, by converting the values
94 // tos strings and joining them. This AST node is not used directly; it's
95 // produced as part of the AST of a "for" loop in a template.
96 type TemplateJoinExpr struct {
100 func (e *TemplateJoinExpr) walkChildNodes(w internalWalkFunc) {
104 func (e *TemplateJoinExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
105 tuple, diags := e.Tuple.Value(ctx)
108 // This indicates a bug in the code that constructed the AST.
109 panic("TemplateJoinExpr got null tuple")
111 if tuple.Type() == cty.DynamicPseudoType {
112 return cty.UnknownVal(cty.String), diags
114 if !tuple.Type().IsTupleType() {
115 // This indicates a bug in the code that constructed the AST.
116 panic("TemplateJoinExpr got non-tuple tuple")
118 if !tuple.IsKnown() {
119 return cty.UnknownVal(cty.String), diags
122 buf := &bytes.Buffer{}
123 it := tuple.ElementIterator()
125 _, val := it.Element()
128 diags = append(diags, &hcl.Diagnostic{
129 Severity: hcl.DiagError,
130 Summary: "Invalid template interpolation value",
132 "An iteration result is null. Cannot include a null value in a string template.",
134 Subject: e.Range().Ptr(),
140 if val.Type() == cty.DynamicPseudoType {
141 return cty.UnknownVal(cty.String), diags
143 strVal, err := convert.Convert(val, cty.String)
145 diags = append(diags, &hcl.Diagnostic{
146 Severity: hcl.DiagError,
147 Summary: "Invalid template interpolation value",
149 "Cannot include one of the interpolation results into the string template: %s.",
152 Subject: e.Range().Ptr(),
159 return cty.UnknownVal(cty.String), diags
162 buf.WriteString(strVal.AsString())
165 return cty.StringVal(buf.String()), diags
168 func (e *TemplateJoinExpr) Range() hcl.Range {
169 return e.Tuple.Range()
172 func (e *TemplateJoinExpr) StartRange() hcl.Range {
173 return e.Tuple.StartRange()
176 // TemplateWrapExpr is used instead of a TemplateExpr when a template
177 // consists _only_ of a single interpolation sequence. In that case, the
178 // template's result is the single interpolation's result, verbatim with
179 // no type conversions.
180 type TemplateWrapExpr struct {
186 func (e *TemplateWrapExpr) walkChildNodes(w internalWalkFunc) {
190 func (e *TemplateWrapExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
191 return e.Wrapped.Value(ctx)
194 func (e *TemplateWrapExpr) Range() hcl.Range {
198 func (e *TemplateWrapExpr) StartRange() hcl.Range {