diff --git a/uast/types.go b/uast/types.go index ef9e4ea2..73cce74f 100644 --- a/uast/types.go +++ b/uast/types.go @@ -212,6 +212,7 @@ func fieldName(f reflect.StructField) (string, bool, error) { var ( reflString = reflect.TypeOf("") reflAny = reflect.TypeOf((*Any)(nil)).Elem() + reflAnyArr = reflect.TypeOf([]Any{}) reflNode = reflect.TypeOf((*nodes.Node)(nil)).Elem() reflNodeExt = reflect.TypeOf((*nodes.External)(nil)).Elem() ) @@ -354,6 +355,26 @@ func setAnyOrNode(dst reflect.Value, n nodes.External) (bool, error) { } dst.Set(reflect.ValueOf(nd)) return true, nil + } else if rt == reflAnyArr { + 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 ad1c1d29..66d4386d 100644 --- a/uast/types_test.go +++ b/uast/types_test.go @@ -71,6 +71,46 @@ var casesToNode = []struct { KeyEnd: expPos(4, 2, 2), }, }, + { + name: "Ambiguity", + obj: Ambiguity{ + GenNode: GenNode{ + Positions: Positions{ + KeyStart: {Offset: 3, Line: 2, Col: 1}, + KeyEnd: {Offset: 8, Line: 2, Col: 6}, + }, + }, + Alternatives: []Any{ + Identifier{Name: "a", GenNode: GenNode{ + Positions: Positions{}, + }}, + String{Value: "a", GenNode: GenNode{ + Positions: Positions{}, + }}, + }, + }, + exp: nodes.Object{ + KeyType: nodes.String("uast:Ambiguity"), + KeyPos: nodes.Object{ + KeyType: nodes.String(TypePositions), + KeyStart: expPos(3, 2, 1), + KeyEnd: expPos(8, 2, 6), + }, + "Alternatives": 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(""), + }, + }, + }, + }, { name: "Alias", obj: Alias{ diff --git a/uast/uast.go b/uast/uast.go index 04e4ee60..c0c02c6e 100644 --- a/uast/uast.go +++ b/uast/uast.go @@ -29,6 +29,7 @@ func init() { Position{}, Positions{}, GenNode{}, + Ambiguity{}, Identifier{}, String{}, QualifiedIdentifier{}, @@ -266,6 +267,16 @@ type GenNode struct { Positions Positions `json:"@pos,omitempty"` } +// Ambiguity node can be used when the driver cannot interpret the node without additional information, but can propose +// a small number of possible meanings of this node. +// +// An example might be an ambiguity between a builtin identifier like "true" versus the local definition of the same +// identifier. +type Ambiguity struct { + GenNode + Alternatives []Any `json:"Alternatives"` +} + type Identifier struct { GenNode Name string `json:"Name"`