]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_template.go
update vendor and go.mod
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / hcl2 / hcl / hclsyntax / expression_template.go
1 package hclsyntax
2
3 import (
4 "bytes"
5 "fmt"
6
7 "github.com/hashicorp/hcl2/hcl"
8 "github.com/zclconf/go-cty/cty"
9 "github.com/zclconf/go-cty/cty/convert"
10 )
11
12 type TemplateExpr struct {
13 Parts []Expression
14
15 SrcRange hcl.Range
16 }
17
18 func (e *TemplateExpr) walkChildNodes(w internalWalkFunc) {
19 for _, part := range e.Parts {
20 w(part)
21 }
22 }
23
24 func (e *TemplateExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
25 buf := &bytes.Buffer{}
26 var diags hcl.Diagnostics
27 isKnown := true
28
29 for _, part := range e.Parts {
30 partVal, partDiags := part.Value(ctx)
31 diags = append(diags, partDiags...)
32
33 if partVal.IsNull() {
34 diags = append(diags, &hcl.Diagnostic{
35 Severity: hcl.DiagError,
36 Summary: "Invalid template interpolation value",
37 Detail: fmt.Sprintf(
38 "The expression result is null. Cannot include a null value in a string template.",
39 ),
40 Subject: part.Range().Ptr(),
41 Context: &e.SrcRange,
42 Expression: part,
43 EvalContext: ctx,
44 })
45 continue
46 }
47
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.
53 isKnown = false
54 continue
55 }
56
57 strVal, err := convert.Convert(partVal, cty.String)
58 if err != nil {
59 diags = append(diags, &hcl.Diagnostic{
60 Severity: hcl.DiagError,
61 Summary: "Invalid template interpolation value",
62 Detail: fmt.Sprintf(
63 "Cannot include the given value in a string template: %s.",
64 err.Error(),
65 ),
66 Subject: part.Range().Ptr(),
67 Context: &e.SrcRange,
68 Expression: part,
69 EvalContext: ctx,
70 })
71 continue
72 }
73
74 buf.WriteString(strVal.AsString())
75 }
76
77 if !isKnown {
78 return cty.UnknownVal(cty.String), diags
79 }
80
81 return cty.StringVal(buf.String()), diags
82 }
83
84 func (e *TemplateExpr) Range() hcl.Range {
85 return e.SrcRange
86 }
87
88 func (e *TemplateExpr) StartRange() hcl.Range {
89 return e.Parts[0].StartRange()
90 }
91
92 // IsStringLiteral returns true if and only if the template consists only of
93 // single string literal, as would be created for a simple quoted string like
94 // "foo".
95 //
96 // If this function returns true, then calling Value on the same expression
97 // with a nil EvalContext will return the literal value.
98 //
99 // Note that "${"foo"}", "${1}", etc aren't considered literal values for the
100 // purposes of this method, because the intent of this method is to identify
101 // situations where the user seems to be explicitly intending literal string
102 // interpretation, not situations that result in literals as a technicality
103 // of the template expression unwrapping behavior.
104 func (e *TemplateExpr) IsStringLiteral() bool {
105 if len(e.Parts) != 1 {
106 return false
107 }
108 _, ok := e.Parts[0].(*LiteralValueExpr)
109 return ok
110 }
111
112 // TemplateJoinExpr is used to convert tuples of strings produced by template
113 // constructs (i.e. for loops) into flat strings, by converting the values
114 // tos strings and joining them. This AST node is not used directly; it's
115 // produced as part of the AST of a "for" loop in a template.
116 type TemplateJoinExpr struct {
117 Tuple Expression
118 }
119
120 func (e *TemplateJoinExpr) walkChildNodes(w internalWalkFunc) {
121 w(e.Tuple)
122 }
123
124 func (e *TemplateJoinExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
125 tuple, diags := e.Tuple.Value(ctx)
126
127 if tuple.IsNull() {
128 // This indicates a bug in the code that constructed the AST.
129 panic("TemplateJoinExpr got null tuple")
130 }
131 if tuple.Type() == cty.DynamicPseudoType {
132 return cty.UnknownVal(cty.String), diags
133 }
134 if !tuple.Type().IsTupleType() {
135 // This indicates a bug in the code that constructed the AST.
136 panic("TemplateJoinExpr got non-tuple tuple")
137 }
138 if !tuple.IsKnown() {
139 return cty.UnknownVal(cty.String), diags
140 }
141
142 buf := &bytes.Buffer{}
143 it := tuple.ElementIterator()
144 for it.Next() {
145 _, val := it.Element()
146
147 if val.IsNull() {
148 diags = append(diags, &hcl.Diagnostic{
149 Severity: hcl.DiagError,
150 Summary: "Invalid template interpolation value",
151 Detail: fmt.Sprintf(
152 "An iteration result is null. Cannot include a null value in a string template.",
153 ),
154 Subject: e.Range().Ptr(),
155 Expression: e,
156 EvalContext: ctx,
157 })
158 continue
159 }
160 if val.Type() == cty.DynamicPseudoType {
161 return cty.UnknownVal(cty.String), diags
162 }
163 strVal, err := convert.Convert(val, cty.String)
164 if err != nil {
165 diags = append(diags, &hcl.Diagnostic{
166 Severity: hcl.DiagError,
167 Summary: "Invalid template interpolation value",
168 Detail: fmt.Sprintf(
169 "Cannot include one of the interpolation results into the string template: %s.",
170 err.Error(),
171 ),
172 Subject: e.Range().Ptr(),
173 Expression: e,
174 EvalContext: ctx,
175 })
176 continue
177 }
178 if !val.IsKnown() {
179 return cty.UnknownVal(cty.String), diags
180 }
181
182 buf.WriteString(strVal.AsString())
183 }
184
185 return cty.StringVal(buf.String()), diags
186 }
187
188 func (e *TemplateJoinExpr) Range() hcl.Range {
189 return e.Tuple.Range()
190 }
191
192 func (e *TemplateJoinExpr) StartRange() hcl.Range {
193 return e.Tuple.StartRange()
194 }
195
196 // TemplateWrapExpr is used instead of a TemplateExpr when a template
197 // consists _only_ of a single interpolation sequence. In that case, the
198 // template's result is the single interpolation's result, verbatim with
199 // no type conversions.
200 type TemplateWrapExpr struct {
201 Wrapped Expression
202
203 SrcRange hcl.Range
204 }
205
206 func (e *TemplateWrapExpr) walkChildNodes(w internalWalkFunc) {
207 w(e.Wrapped)
208 }
209
210 func (e *TemplateWrapExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
211 return e.Wrapped.Value(ctx)
212 }
213
214 func (e *TemplateWrapExpr) Range() hcl.Range {
215 return e.SrcRange
216 }
217
218 func (e *TemplateWrapExpr) StartRange() hcl.Range {
219 return e.SrcRange
220 }