@@ -10,9 +10,9 @@ import (
1010 "sync"
1111
1212 lru "github.com/hashicorp/golang-lru"
13- bblfsh "gopkg.in/bblfsh/client-go.v2 "
14- "gopkg.in/bblfsh/client-go .v2/tools "
15- "gopkg.in/bblfsh/sdk.v1 /uast"
13+ bblfsh "gopkg.in/bblfsh/client-go.v3 "
14+ "gopkg.in/bblfsh/sdk .v2/uast "
15+ "gopkg.in/bblfsh/sdk.v2 /uast/nodes "
1616
1717 "gopkg.in/src-d/go-mysql-server.v0/sql"
1818 "gopkg.in/src-d/go-mysql-server.v0/sql/expression"
@@ -141,16 +141,9 @@ func (u *uastFunc) Eval(ctx *sql.Context, row sql.Row) (out interface{}, err err
141141 return nil , err
142142 }
143143
144- var mode bblfsh.Mode
145- switch m {
146- case "semantic" :
147- mode = bblfsh .Semantic
148- case "annotated" :
149- mode = bblfsh .Annotated
150- case "native" :
151- mode = bblfsh .Native
152- default :
153- return nil , fmt .Errorf ("invalid uast mode %s" , m )
144+ mode , err := bblfsh .ParseMode (m )
145+ if err != nil {
146+ return nil , err
154147 }
155148
156149 blob , err := u .Blob .Eval (ctx , row )
@@ -201,10 +194,10 @@ func (u *uastFunc) getUAST(
201194 return nil , err
202195 }
203196
204- var node * uast .Node
197+ var node nodes .Node
205198 value , ok := uastCache .Get (key )
206199 if ok {
207- node = value .(* uast .Node )
200+ node = value .(nodes .Node )
208201 } else {
209202 var err error
210203 node , err = getUASTFromBblfsh (ctx , blob , lang , xpath , mode )
@@ -219,18 +212,18 @@ func (u *uastFunc) getUAST(
219212 uastCache .Add (key , node )
220213 }
221214
222- var nodes [] * uast. Node
215+ var nodeArray nodes. Array
223216 if xpath == "" {
224- nodes = [] * uast. Node { node }
217+ nodeArray = append ( nodeArray , node )
225218 } else {
226219 var err error
227- nodes , err = tools . Filter (node , xpath )
220+ nodeArray , err = applyXpath (node , xpath )
228221 if err != nil {
229222 return nil , err
230223 }
231224 }
232225
233- return marshalNodes (nodes )
226+ return marshalNodes (nodeArray )
234227}
235228
236229// UAST returns an array of UAST nodes as blobs.
@@ -349,37 +342,37 @@ func (f *UASTXPath) Eval(ctx *sql.Context, row sql.Row) (out interface{}, err er
349342 span , ctx := ctx .Span ("gitbase.UASTXPath" )
350343 defer span .Finish ()
351344
352- left , err := f . Left . Eval (ctx , row )
345+ xpath , err := exprToString (ctx , f . Right , row )
353346 if err != nil {
354347 return nil , err
355348 }
356349
357- nodes , err := getNodes (left )
358- if err != nil {
359- return nil , err
350+ if xpath == "" {
351+ return nil , nil
360352 }
361353
362- if nodes == nil {
363- return nil , nil
354+ left , err := f .Left .Eval (ctx , row )
355+ if err != nil {
356+ return nil , err
364357 }
365358
366- xpath , err := exprToString ( ctx , f . Right , row )
359+ ns , err := getNodes ( left )
367360 if err != nil {
368361 return nil , err
369362 }
370363
371- if xpath == "" {
364+ if ns == nil {
372365 return nil , nil
373366 }
374367
375- var filtered [] * uast. Node
376- for _ , n := range nodes {
377- ns , err := tools . Filter (n , xpath )
368+ var filtered nodes. Array
369+ for _ , n := range ns {
370+ partial , err := applyXpath (n , xpath )
378371 if err != nil {
379372 return nil , err
380373 }
381374
382- filtered = append (filtered , ns ... )
375+ filtered = append (filtered , partial ... )
383376 }
384377
385378 return marshalNodes (filtered )
@@ -440,12 +433,12 @@ func (u *UASTExtract) Eval(ctx *sql.Context, row sql.Row) (out interface{}, err
440433 return nil , err
441434 }
442435
443- nodes , err := getNodes (left )
436+ ns , err := getNodes (left )
444437 if err != nil {
445438 return nil , err
446439 }
447440
448- if nodes == nil {
441+ if ns == nil {
449442 return nil , nil
450443 }
451444
@@ -459,60 +452,140 @@ func (u *UASTExtract) Eval(ctx *sql.Context, row sql.Row) (out interface{}, err
459452 }
460453
461454 extracted := []interface {}{}
462- for _ , n := range nodes {
463- info := extractInfo (n , key )
464- if len (info ) > 0 {
465- extracted = append (extracted , info ... )
455+ for _ , n := range ns {
456+ props := extractProperties (n , key )
457+ if len (props ) > 0 {
458+ extracted = append (extracted , props ... )
466459 }
467460 }
468461
469462 return extracted , nil
470463}
471464
472- const (
473- keyType = "@type"
474- keyToken = "@token"
475- keyRoles = "@role"
476- keyStartPos = "@startpos"
477- keyEndPos = "@endpos"
478- )
465+ func extractProperties (n nodes.Node , key string ) []interface {} {
466+ node , ok := n .(nodes.Object )
467+ if ! ok {
468+ return nil
469+ }
479470
480- func extractInfo (n * uast.Node , key string ) []interface {} {
481- var info []interface {}
471+ var extracted []interface {}
472+ if isCommonProp (key ) {
473+ extracted = extractCommonProp (node , key )
474+ } else {
475+ extracted = extractAnyProp (node , key )
476+ }
477+
478+ return extracted
479+ }
480+
481+ func isCommonProp (key string ) bool {
482+ return key == uast .KeyType || key == uast .KeyToken ||
483+ key == uast .KeyRoles || key == uast .KeyPos
484+ }
485+
486+ func extractCommonProp (node nodes.Object , key string ) []interface {} {
487+ var extracted []interface {}
482488 switch key {
483- case keyType :
484- if n .InternalType != "" {
485- info = append (info , n .InternalType )
489+ case uast .KeyType :
490+ t := uast .TypeOf (node )
491+ if t != "" {
492+ extracted = append (extracted , t )
486493 }
487- case keyToken :
488- if n .Token != "" {
489- info = append (info , n .Token )
494+ case uast .KeyToken :
495+ t := uast .TokenOf (node )
496+ if t != "" {
497+ extracted = append (extracted , t )
490498 }
491- case keyRoles :
492- if len (n .Roles ) > 0 {
493- roles := make ([]interface {}, len (n .Roles ))
494- for i , rol := range n .Roles {
495- roles [i ] = rol .String ()
499+ case uast .KeyRoles :
500+ r := uast .RolesOf (node )
501+ if len (r ) > 0 {
502+ roles := make ([]interface {}, len (r ))
503+ for i , role := range r {
504+ roles [i ] = role .String ()
496505 }
497506
498- info = append (info , roles ... )
507+ extracted = append (extracted , roles ... )
499508 }
500- case keyStartPos :
501- if n .StartPosition != nil {
502- info = append (info , n .StartPosition .String ())
509+ case uast .KeyPos :
510+ p := uast .PositionsOf (node )
511+ if p != nil {
512+ if s := posToString (p ); s != "" {
513+ extracted = append (extracted , s )
514+ }
503515 }
504- case keyEndPos :
505- if n .StartPosition != nil {
506- info = append (info , n .EndPosition .String ())
516+ }
517+
518+ return extracted
519+ }
520+
521+ func posToString (pos uast.Positions ) string {
522+ var b strings.Builder
523+
524+ start := pos .Start ()
525+ end := pos .End ()
526+
527+ if start != nil {
528+ fmt .Fprintf (& b , "Start: [Offset:%d Line:%d Col:%d]" ,
529+ start .Offset , start .Line , start .Col )
530+ }
531+
532+ if pos .End () != nil {
533+ if pos .Start () != nil {
534+ fmt .Fprint (& b , ", " )
507535 }
508- default :
509- v , ok := n .Properties [key ]
510- if ok {
511- info = append (info , v )
536+
537+ fmt .Fprintf (& b , "End: [Offset:%d Line:%d Col:%d]" ,
538+ end .Offset , end .Line , end .Col )
539+ }
540+
541+ return b .String ()
542+ }
543+
544+ func extractAnyProp (node nodes.Object , key string ) []interface {} {
545+ v , ok := node [key ]
546+ if ! ok {
547+ return nil
548+ }
549+
550+ if v .Kind ().In (nodes .KindsValues ) {
551+ value , err := valueToString (v .(nodes.Value ))
552+ if err != nil {
553+ return nil
554+ }
555+
556+ return []interface {}{value }
557+ }
558+
559+ if v .Kind () == nodes .KindArray {
560+ values , err := valuesFromNodeArray (v .(nodes.Array ))
561+ if err != nil {
562+ return nil
563+ }
564+
565+ return values
566+ }
567+
568+ return nil
569+ }
570+
571+ func valuesFromNodeArray (arr nodes.Array ) ([]interface {}, error ) {
572+ var values []interface {}
573+ for _ , n := range arr {
574+ if n .Kind ().In (nodes .KindsValues ) {
575+ s , err := valueToString (n .(nodes.Value ))
576+ if err != nil {
577+ return nil , err
578+ }
579+
580+ values = append (values , s )
512581 }
513582 }
514583
515- return info
584+ return values , nil
585+ }
586+
587+ func valueToString (n nodes.Value ) (interface {}, error ) {
588+ return sql .Text .Convert (n .Native ())
516589}
517590
518591// TransformUp implements the sql.Expression interface.
@@ -589,11 +662,44 @@ func (u *UASTChildren) Eval(ctx *sql.Context, row sql.Row) (out interface{}, err
589662 return marshalNodes (children )
590663}
591664
592- func flattenChildren (nodes []* uast.Node ) []* uast.Node {
593- children := []* uast.Node {}
594- for _ , n := range nodes {
595- if len (n .Children ) > 0 {
596- children = append (children , n .Children ... )
665+ func flattenChildren (arr nodes.Array ) nodes.Array {
666+ var children nodes.Array
667+ for _ , n := range arr {
668+ o , ok := n .(nodes.Object )
669+ if ! ok {
670+ continue
671+ }
672+
673+ c := getChildren (o )
674+ if len (c ) > 0 {
675+ children = append (children , c ... )
676+ }
677+ }
678+
679+ return children
680+ }
681+
682+ func getChildren (node nodes.Object ) nodes.Array {
683+ var children nodes.Array
684+ for _ , key := range node .Keys () {
685+ if isCommonProp (key ) {
686+ continue
687+ }
688+
689+ c , ok := node [key ]
690+ if ! ok {
691+ continue
692+ }
693+
694+ switch c .Kind () {
695+ case nodes .KindObject :
696+ children = append (children , c )
697+ case nodes .KindArray :
698+ for _ , n := range c .(nodes.Array ) {
699+ if n .Kind () == nodes .KindObject {
700+ children = append (children , n )
701+ }
702+ }
597703 }
598704 }
599705
0 commit comments