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 i, part := range e.Parts {
20 e.Parts[i] = w(part).(Expression)
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(),
46 if !partVal.IsKnown() {
47 // If any part is unknown then the result as a whole must be
48 // unknown too. We'll keep on processing the rest of the parts
49 // anyway, because we want to still emit any diagnostics resulting
50 // from evaluating those.
55 strVal, err := convert.Convert(partVal, cty.String)
57 diags = append(diags, &hcl.Diagnostic{
58 Severity: hcl.DiagError,
59 Summary: "Invalid template interpolation value",
61 "Cannot include the given value in a string template: %s.",
64 Subject: part.Range().Ptr(),
70 buf.WriteString(strVal.AsString())
74 return cty.UnknownVal(cty.String), diags
77 return cty.StringVal(buf.String()), diags
80 func (e *TemplateExpr) Range() hcl.Range {
84 func (e *TemplateExpr) StartRange() hcl.Range {
85 return e.Parts[0].StartRange()
88 // TemplateJoinExpr is used to convert tuples of strings produced by template
89 // constructs (i.e. for loops) into flat strings, by converting the values
90 // tos strings and joining them. This AST node is not used directly; it's
91 // produced as part of the AST of a "for" loop in a template.
92 type TemplateJoinExpr struct {
96 func (e *TemplateJoinExpr) walkChildNodes(w internalWalkFunc) {
97 e.Tuple = w(e.Tuple).(Expression)
100 func (e *TemplateJoinExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
101 tuple, diags := e.Tuple.Value(ctx)
104 // This indicates a bug in the code that constructed the AST.
105 panic("TemplateJoinExpr got null tuple")
107 if tuple.Type() == cty.DynamicPseudoType {
108 return cty.UnknownVal(cty.String), diags
110 if !tuple.Type().IsTupleType() {
111 // This indicates a bug in the code that constructed the AST.
112 panic("TemplateJoinExpr got non-tuple tuple")
114 if !tuple.IsKnown() {
115 return cty.UnknownVal(cty.String), diags
118 buf := &bytes.Buffer{}
119 it := tuple.ElementIterator()
121 _, val := it.Element()
124 diags = append(diags, &hcl.Diagnostic{
125 Severity: hcl.DiagError,
126 Summary: "Invalid template interpolation value",
128 "An iteration result is null. Cannot include a null value in a string template.",
130 Subject: e.Range().Ptr(),
134 if val.Type() == cty.DynamicPseudoType {
135 return cty.UnknownVal(cty.String), diags
137 strVal, err := convert.Convert(val, cty.String)
139 diags = append(diags, &hcl.Diagnostic{
140 Severity: hcl.DiagError,
141 Summary: "Invalid template interpolation value",
143 "Cannot include one of the interpolation results into the string template: %s.",
146 Subject: e.Range().Ptr(),
151 return cty.UnknownVal(cty.String), diags
154 buf.WriteString(strVal.AsString())
157 return cty.StringVal(buf.String()), diags
160 func (e *TemplateJoinExpr) Range() hcl.Range {
161 return e.Tuple.Range()
164 func (e *TemplateJoinExpr) StartRange() hcl.Range {
165 return e.Tuple.StartRange()
168 // TemplateWrapExpr is used instead of a TemplateExpr when a template
169 // consists _only_ of a single interpolation sequence. In that case, the
170 // template's result is the single interpolation's result, verbatim with
171 // no type conversions.
172 type TemplateWrapExpr struct {
178 func (e *TemplateWrapExpr) walkChildNodes(w internalWalkFunc) {
179 e.Wrapped = w(e.Wrapped).(Expression)
182 func (e *TemplateWrapExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
183 return e.Wrapped.Value(ctx)
186 func (e *TemplateWrapExpr) Range() hcl.Range {
190 func (e *TemplateWrapExpr) StartRange() hcl.Range {