gozcl: DecodeExpression implementation
This is really just a wrapper around converting the value to a Go native value with gocty, but is convenient to provide since it can attempt type conversion and produce diagnostics automatically.
This commit is contained in:
parent
bb5044d015
commit
5b8d54380b
@ -1,6 +1,10 @@
|
||||
package gozcl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/apparentlymart/go-cty/cty/convert"
|
||||
"github.com/apparentlymart/go-cty/cty/gocty"
|
||||
"github.com/apparentlymart/go-zcl/zcl"
|
||||
)
|
||||
|
||||
@ -40,6 +44,35 @@ func DecodeBody(body zcl.Body, ctx *zcl.EvalContext, val interface{}) zcl.Diagno
|
||||
// may still be accessed by a careful caller for static analysis and editor
|
||||
// integration use-cases.
|
||||
func DecodeExpression(expr zcl.Expression, ctx *zcl.EvalContext, val interface{}) zcl.Diagnostics {
|
||||
// TODO: Implement
|
||||
return nil
|
||||
srcVal, diags := expr.Value(ctx)
|
||||
|
||||
convTy, err := gocty.ImpliedType(val)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("unsuitable DecodeExpression target: %s", err))
|
||||
}
|
||||
|
||||
srcVal, err = convert.Convert(srcVal, convTy)
|
||||
if err != nil {
|
||||
diags = append(diags, &zcl.Diagnostic{
|
||||
Severity: zcl.DiagError,
|
||||
Summary: "Unsuitable value type",
|
||||
Detail: fmt.Sprintf("Incorrect value type: %s", err.Error()),
|
||||
Subject: expr.StartRange().Ptr(),
|
||||
Context: expr.Range().Ptr(),
|
||||
})
|
||||
return diags
|
||||
}
|
||||
|
||||
err = gocty.FromCtyValue(srcVal, val)
|
||||
if err != nil {
|
||||
diags = append(diags, &zcl.Diagnostic{
|
||||
Severity: zcl.DiagError,
|
||||
Summary: "Unsuitable value type",
|
||||
Detail: fmt.Sprintf("Incorrect value type: %s", err.Error()),
|
||||
Subject: expr.StartRange().Ptr(),
|
||||
Context: expr.Range().Ptr(),
|
||||
})
|
||||
}
|
||||
|
||||
return diags
|
||||
}
|
||||
|
97
gozcl/decode_test.go
Normal file
97
gozcl/decode_test.go
Normal file
@ -0,0 +1,97 @@
|
||||
package gozcl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/apparentlymart/go-cty/cty"
|
||||
"github.com/apparentlymart/go-zcl/zcl"
|
||||
)
|
||||
|
||||
func TestDecodeExpression(t *testing.T) {
|
||||
tests := []struct {
|
||||
Value cty.Value
|
||||
Target interface{}
|
||||
Want interface{}
|
||||
DiagCount int
|
||||
}{
|
||||
{
|
||||
cty.StringVal("hello"),
|
||||
"",
|
||||
"hello",
|
||||
0,
|
||||
},
|
||||
{
|
||||
cty.StringVal("hello"),
|
||||
cty.NilVal,
|
||||
cty.StringVal("hello"),
|
||||
0,
|
||||
},
|
||||
{
|
||||
cty.NumberIntVal(2),
|
||||
"",
|
||||
"2",
|
||||
0,
|
||||
},
|
||||
{
|
||||
cty.StringVal("true"),
|
||||
false,
|
||||
true,
|
||||
0,
|
||||
},
|
||||
{
|
||||
cty.NullVal(cty.String),
|
||||
"",
|
||||
"",
|
||||
1, // null value is not allowed
|
||||
},
|
||||
{
|
||||
cty.UnknownVal(cty.String),
|
||||
"",
|
||||
"",
|
||||
1, // value must be known
|
||||
},
|
||||
{
|
||||
cty.ListVal([]cty.Value{cty.True}),
|
||||
false,
|
||||
false,
|
||||
1, // bool required
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
|
||||
expr := &fixedExpression{test.Value}
|
||||
|
||||
targetVal := reflect.New(reflect.TypeOf(test.Target))
|
||||
|
||||
diags := DecodeExpression(expr, nil, targetVal.Interface())
|
||||
if len(diags) != test.DiagCount {
|
||||
t.Errorf("wrong number of diagnostics %d; want %d", len(diags), test.DiagCount)
|
||||
for _, diag := range diags {
|
||||
t.Logf(" - %s", diag.Error())
|
||||
}
|
||||
}
|
||||
got := targetVal.Elem().Interface()
|
||||
if !reflect.DeepEqual(got, test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type fixedExpression struct {
|
||||
val cty.Value
|
||||
}
|
||||
|
||||
func (e *fixedExpression) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
|
||||
return e.val, nil
|
||||
}
|
||||
|
||||
func (e *fixedExpression) Range() (r zcl.Range) {
|
||||
return
|
||||
}
|
||||
func (e *fixedExpression) StartRange() (r zcl.Range) {
|
||||
return
|
||||
}
|
Loading…
Reference in New Issue
Block a user