json: parse strings as zclsyntax templates
This is the same idea as our existing HIL template support, but uses the zclsyntax template parser instead of HIL's parser.
This commit is contained in:
parent
a0be779c9c
commit
b878a4ef98
@ -24,6 +24,78 @@ func TestParse_nonObject(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTemplate(t *testing.T) {
|
||||
src := `{"greeting": "hello ${\"world\"}"}`
|
||||
file, diags := Parse([]byte(src), "")
|
||||
if len(diags) != 0 {
|
||||
t.Errorf("got %d diagnostics on parse; want 0", len(diags))
|
||||
for _, diag := range diags {
|
||||
t.Logf("- %s", diag.Error())
|
||||
}
|
||||
}
|
||||
if file == nil {
|
||||
t.Errorf("got nil File; want actual file")
|
||||
}
|
||||
if file.Body == nil {
|
||||
t.Fatalf("got nil Body; want actual body")
|
||||
}
|
||||
attrs, diags := file.Body.JustAttributes()
|
||||
if len(diags) != 0 {
|
||||
t.Errorf("got %d diagnostics on decode; want 0", len(diags))
|
||||
for _, diag := range diags {
|
||||
t.Logf("- %s", diag.Error())
|
||||
}
|
||||
}
|
||||
|
||||
val, diags := attrs["greeting"].Expr.Value(&zcl.EvalContext{})
|
||||
if len(diags) != 0 {
|
||||
t.Errorf("got %d diagnostics on eval; want 0", len(diags))
|
||||
for _, diag := range diags {
|
||||
t.Logf("- %s", diag.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if !val.RawEquals(cty.StringVal("hello world")) {
|
||||
t.Errorf("wrong result %#v; want %#v", val, cty.StringVal("hello world"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTemplateUnwrap(t *testing.T) {
|
||||
src := `{"greeting": "${true}"}`
|
||||
file, diags := Parse([]byte(src), "")
|
||||
if len(diags) != 0 {
|
||||
t.Errorf("got %d diagnostics on parse; want 0", len(diags))
|
||||
for _, diag := range diags {
|
||||
t.Logf("- %s", diag.Error())
|
||||
}
|
||||
}
|
||||
if file == nil {
|
||||
t.Errorf("got nil File; want actual file")
|
||||
}
|
||||
if file.Body == nil {
|
||||
t.Fatalf("got nil Body; want actual body")
|
||||
}
|
||||
attrs, diags := file.Body.JustAttributes()
|
||||
if len(diags) != 0 {
|
||||
t.Errorf("got %d diagnostics on decode; want 0", len(diags))
|
||||
for _, diag := range diags {
|
||||
t.Logf("- %s", diag.Error())
|
||||
}
|
||||
}
|
||||
|
||||
val, diags := attrs["greeting"].Expr.Value(&zcl.EvalContext{})
|
||||
if len(diags) != 0 {
|
||||
t.Errorf("got %d diagnostics on eval; want 0", len(diags))
|
||||
for _, diag := range diags {
|
||||
t.Logf("- %s", diag.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if !val.RawEquals(cty.True) {
|
||||
t.Errorf("wrong result %#v; want %#v", val, cty.True)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTemplateWithHIL(t *testing.T) {
|
||||
src := `{"greeting": "hello ${\"world\"}"}`
|
||||
file, diags := ParseWithHIL([]byte(src), "")
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-zcl/zcl"
|
||||
"github.com/zclconf/go-zcl/zcl/hclhil"
|
||||
"github.com/zclconf/go-zcl/zcl/zclsyntax"
|
||||
)
|
||||
|
||||
// body is the implementation of "Body" used for files processed with the JSON
|
||||
@ -255,9 +256,6 @@ func (b *body) unpackBlock(v node, typeName string, typeRange *zcl.Range, labels
|
||||
}
|
||||
|
||||
func (e *expression) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
|
||||
// TEMP: Since we've not yet implemented the zcl native template language
|
||||
// parser, for the moment we'll support only literal values here.
|
||||
|
||||
switch v := e.src.(type) {
|
||||
case *stringVal:
|
||||
if e.useHIL && ctx != nil {
|
||||
@ -281,6 +279,35 @@ func (e *expression) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
|
||||
return val, diags
|
||||
}
|
||||
|
||||
if ctx != nil {
|
||||
// Parse string contents as a zcl native language expression.
|
||||
// We only do this if we have a context, so passing a nil context
|
||||
// is how the caller specifies that interpolations are not allowed
|
||||
// and that the string should just be returned verbatim.
|
||||
templateSrc := v.Value
|
||||
expr, diags := zclsyntax.ParseTemplate(
|
||||
[]byte(templateSrc),
|
||||
v.SrcRange.Filename,
|
||||
|
||||
// This won't produce _exactly_ the right result, since
|
||||
// the zclsyntax parser can't "see" any escapes we removed
|
||||
// while parsing JSON, but it's better than nothing.
|
||||
zcl.Pos{
|
||||
Line: v.SrcRange.Start.Line,
|
||||
|
||||
// skip over the opening quote mark
|
||||
Byte: v.SrcRange.Start.Byte + 1,
|
||||
Column: v.SrcRange.Start.Column + 1,
|
||||
},
|
||||
)
|
||||
if diags.HasErrors() {
|
||||
return cty.DynamicVal, diags
|
||||
}
|
||||
val, evalDiags := expr.Value(ctx)
|
||||
diags = append(diags, evalDiags...)
|
||||
return val, diags
|
||||
}
|
||||
|
||||
// FIXME: Once the native zcl template language parser is implemented,
|
||||
// parse string values as templates and evaluate them.
|
||||
return cty.StringVal(v.Value), nil
|
||||
|
Loading…
Reference in New Issue
Block a user