hclsyntax: Pass marks through template expressions
If a template expression interpolates values which have marks, we should apply all of those marks to the output value. This allows template expressions to function like native cty functions with respect to marks.
This commit is contained in:
parent
bf0a7fe4fe
commit
876b4237a0
@ -26,6 +26,9 @@ func (e *TemplateExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)
|
||||
var diags hcl.Diagnostics
|
||||
isKnown := true
|
||||
|
||||
// Maintain a set of marks for values used in the template
|
||||
marks := make(cty.ValueMarks)
|
||||
|
||||
for _, part := range e.Parts {
|
||||
partVal, partDiags := part.Value(ctx)
|
||||
diags = append(diags, partDiags...)
|
||||
@ -71,14 +74,24 @@ func (e *TemplateExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)
|
||||
continue
|
||||
}
|
||||
|
||||
buf.WriteString(strVal.AsString())
|
||||
// Unmark the part and merge its marks into the set
|
||||
unmarked, partMarks := strVal.Unmark()
|
||||
for k, v := range partMarks {
|
||||
marks[k] = v
|
||||
}
|
||||
|
||||
buf.WriteString(unmarked.AsString())
|
||||
}
|
||||
|
||||
var ret cty.Value
|
||||
if !isKnown {
|
||||
return cty.UnknownVal(cty.String), diags
|
||||
ret = cty.UnknownVal(cty.String)
|
||||
} else {
|
||||
ret = cty.StringVal(buf.String())
|
||||
}
|
||||
|
||||
return cty.StringVal(buf.String()), diags
|
||||
// Apply the full set of marks to the returned value
|
||||
return ret.WithMarks(marks), diags
|
||||
}
|
||||
|
||||
func (e *TemplateExpr) Range() hcl.Range {
|
||||
|
@ -283,6 +283,27 @@ trim`,
|
||||
cty.UnknownVal(cty.String),
|
||||
1, // Unexpected endfor directive
|
||||
},
|
||||
{ // marks from uninterpolated values are ignored
|
||||
`hello%{ if false } ${target}%{ endif }`,
|
||||
&hcl.EvalContext{
|
||||
Variables: map[string]cty.Value{
|
||||
"target": cty.StringVal("world").WithMarks(cty.NewValueMarks("sensitive")),
|
||||
},
|
||||
},
|
||||
cty.StringVal("hello"),
|
||||
0,
|
||||
},
|
||||
{ // marks from interpolated values are passed through
|
||||
`${greeting} ${target}`,
|
||||
&hcl.EvalContext{
|
||||
Variables: map[string]cty.Value{
|
||||
"greeting": cty.StringVal("hello").WithMarks(cty.NewValueMarks("english")),
|
||||
"target": cty.StringVal("world").WithMarks(cty.NewValueMarks("sensitive")),
|
||||
},
|
||||
},
|
||||
cty.StringVal("hello world").WithMarks(cty.NewValueMarks("english", "sensitive")),
|
||||
0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
Loading…
Reference in New Issue
Block a user