From 2a1a307944f14b383f75fb8d1041bf48ccec3736 Mon Sep 17 00:00:00 2001 From: Denys Smirnov Date: Wed, 5 Dec 2018 21:29:49 +0200 Subject: [PATCH] uast: properly load node arrays with registered types Signed-off-by: Denys Smirnov --- uast/types.go | 29 +++++++++++++++++++---- uast/types_test.go | 57 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/uast/types.go b/uast/types.go index 4603296b..4a3e93e7 100644 --- a/uast/types.go +++ b/uast/types.go @@ -237,10 +237,11 @@ func fieldName(f reflect.StructField) (string, bool, error) { } var ( - reflString = reflect.TypeOf("") - reflAny = reflect.TypeOf((*Any)(nil)).Elem() - reflNode = reflect.TypeOf((*nodes.Node)(nil)).Elem() - reflNodeExt = reflect.TypeOf((*nodes.External)(nil)).Elem() + reflString = reflect.TypeOf("") + reflAny = reflect.TypeOf((*Any)(nil)).Elem() + reflAnySlice = reflect.TypeOf([]Any{}) + reflNode = reflect.TypeOf((*nodes.Node)(nil)).Elem() + reflNodeExt = reflect.TypeOf((*nodes.External)(nil)).Elem() ) // ToNode converts generic values returned by schema-less encodings such as JSON to Node objects. @@ -384,6 +385,26 @@ func setAnyOrNode(dst reflect.Value, n nodes.External) (bool, error) { } dst.Set(reflect.ValueOf(nd)) return true, nil + } else if rt == reflAnySlice { + narr, ok := n.(nodes.ExternalArray) + if !ok { + return false, nil + } + sz := narr.Size() + arr := make([]Any, 0, sz) + for i := 0; i < sz; i++ { + e := narr.ValueAt(i) + var v Any = e + if nv, err := NewValue(TypeOf(e)); err == nil { + if err = nodeAs(e, nv); err != nil { + return false, err + } + v = nv.Interface() + } + arr = append(arr, v) + } + dst.Set(reflect.ValueOf(arr)) + return true, nil } return false, nil } diff --git a/uast/types_test.go b/uast/types_test.go index c7cf3052..3c54877f 100644 --- a/uast/types_test.go +++ b/uast/types_test.go @@ -1,14 +1,18 @@ -package uast +package uast_test import ( - "testing" - "reflect" + "testing" "github.com/stretchr/testify/require" + . "gopkg.in/bblfsh/sdk.v2/uast" "gopkg.in/bblfsh/sdk.v2/uast/nodes" ) +func init() { + RegisterPackage("test", arrayNode{}) +} + var casesTypeOf = []struct { name string typ interface{} @@ -38,6 +42,11 @@ func expPos(off int, line int, col int) nodes.Object { } } +type arrayNode struct { + GenNode + Array []Any `json:"Array"` +} + var casesToNode = []struct { name string obj interface{} @@ -173,6 +182,46 @@ var casesToNode = []struct { }, }, }, + { + name: "arrayNode", + obj: arrayNode{ + GenNode: GenNode{ + Positions: Positions{ + KeyStart: {Offset: 3, Line: 2, Col: 1}, + KeyEnd: {Offset: 8, Line: 2, Col: 6}, + }, + }, + Array: []Any{ + Identifier{Name: "a", GenNode: GenNode{ + Positions: Positions{}, + }}, + String{Value: "a", GenNode: GenNode{ + Positions: Positions{}, + }}, + }, + }, + exp: nodes.Object{ + KeyType: nodes.String("test:arrayNode"), + KeyPos: nodes.Object{ + KeyType: nodes.String(TypePositions), + KeyStart: expPos(3, 2, 1), + KeyEnd: expPos(8, 2, 6), + }, + "Array": nodes.Array{ + nodes.Object{ + KeyType: nodes.String("uast:Identifier"), + KeyPos: nodes.Object{KeyType: nodes.String(TypePositions)}, + "Name": nodes.String("a"), + }, + nodes.Object{ + KeyType: nodes.String("uast:String"), + KeyPos: nodes.Object{KeyType: nodes.String(TypePositions)}, + "Value": nodes.String("a"), + "Format": nodes.String(""), + }, + }, + }, + }, } func TestToNode(t *testing.T) { @@ -183,7 +232,7 @@ func TestToNode(t *testing.T) { require.Equal(t, c.exp, got) nv := reflect.New(reflect.TypeOf(c.obj)).Elem() - err = nodeAs(got, nv) + err = NodeAs(got, nv) require.NoError(t, err) expObj := c.expObj if expObj == nil {