diff --git a/hclsyntax/expression_template.go b/hclsyntax/expression_template.go index 9d42511..ff9a6e5 100644 --- a/hclsyntax/expression_template.go +++ b/hclsyntax/expression_template.go @@ -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 { diff --git a/hclsyntax/expression_template_test.go b/hclsyntax/expression_template_test.go index 81dda0b..90e0eb6 100644 --- a/hclsyntax/expression_template_test.go +++ b/hclsyntax/expression_template_test.go @@ -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 {