@@ -10,9 +10,9 @@ import (
10
10
"sync"
11
11
12
12
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 "
16
16
17
17
"gopkg.in/src-d/go-mysql-server.v0/sql"
18
18
"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
141
141
return nil , err
142
142
}
143
143
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
154
147
}
155
148
156
149
blob , err := u .Blob .Eval (ctx , row )
@@ -201,10 +194,10 @@ func (u *uastFunc) getUAST(
201
194
return nil , err
202
195
}
203
196
204
- var node * uast .Node
197
+ var node nodes .Node
205
198
value , ok := uastCache .Get (key )
206
199
if ok {
207
- node = value .(* uast .Node )
200
+ node = value .(nodes .Node )
208
201
} else {
209
202
var err error
210
203
node , err = getUASTFromBblfsh (ctx , blob , lang , xpath , mode )
@@ -219,18 +212,18 @@ func (u *uastFunc) getUAST(
219
212
uastCache .Add (key , node )
220
213
}
221
214
222
- var nodes [] * uast. Node
215
+ var nodeArray nodes. Array
223
216
if xpath == "" {
224
- nodes = [] * uast. Node { node }
217
+ nodeArray = append ( nodeArray , node )
225
218
} else {
226
219
var err error
227
- nodes , err = tools . Filter (node , xpath )
220
+ nodeArray , err = applyXpath (node , xpath )
228
221
if err != nil {
229
222
return nil , err
230
223
}
231
224
}
232
225
233
- return marshalNodes (nodes )
226
+ return marshalNodes (nodeArray )
234
227
}
235
228
236
229
// 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
349
342
span , ctx := ctx .Span ("gitbase.UASTXPath" )
350
343
defer span .Finish ()
351
344
352
- left , err := f . Left . Eval (ctx , row )
345
+ xpath , err := exprToString (ctx , f . Right , row )
353
346
if err != nil {
354
347
return nil , err
355
348
}
356
349
357
- nodes , err := getNodes (left )
358
- if err != nil {
359
- return nil , err
350
+ if xpath == "" {
351
+ return nil , nil
360
352
}
361
353
362
- if nodes == nil {
363
- return nil , nil
354
+ left , err := f .Left .Eval (ctx , row )
355
+ if err != nil {
356
+ return nil , err
364
357
}
365
358
366
- xpath , err := exprToString ( ctx , f . Right , row )
359
+ ns , err := getNodes ( left )
367
360
if err != nil {
368
361
return nil , err
369
362
}
370
363
371
- if xpath == "" {
364
+ if ns == nil {
372
365
return nil , nil
373
366
}
374
367
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 )
378
371
if err != nil {
379
372
return nil , err
380
373
}
381
374
382
- filtered = append (filtered , ns ... )
375
+ filtered = append (filtered , partial ... )
383
376
}
384
377
385
378
return marshalNodes (filtered )
@@ -440,12 +433,12 @@ func (u *UASTExtract) Eval(ctx *sql.Context, row sql.Row) (out interface{}, err
440
433
return nil , err
441
434
}
442
435
443
- nodes , err := getNodes (left )
436
+ ns , err := getNodes (left )
444
437
if err != nil {
445
438
return nil , err
446
439
}
447
440
448
- if nodes == nil {
441
+ if ns == nil {
449
442
return nil , nil
450
443
}
451
444
@@ -459,60 +452,140 @@ func (u *UASTExtract) Eval(ctx *sql.Context, row sql.Row) (out interface{}, err
459
452
}
460
453
461
454
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 ... )
466
459
}
467
460
}
468
461
469
462
return extracted , nil
470
463
}
471
464
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
+ }
479
470
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 {}
482
488
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 )
486
493
}
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 )
490
498
}
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 ()
496
505
}
497
506
498
- info = append (info , roles ... )
507
+ extracted = append (extracted , roles ... )
499
508
}
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
+ }
503
515
}
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 , ", " )
507
535
}
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 )
512
581
}
513
582
}
514
583
515
- return info
584
+ return values , nil
585
+ }
586
+
587
+ func valueToString (n nodes.Value ) (interface {}, error ) {
588
+ return sql .Text .Convert (n .Native ())
516
589
}
517
590
518
591
// TransformUp implements the sql.Expression interface.
@@ -589,11 +662,44 @@ func (u *UASTChildren) Eval(ctx *sql.Context, row sql.Row) (out interface{}, err
589
662
return marshalNodes (children )
590
663
}
591
664
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
+ }
597
703
}
598
704
}
599
705
0 commit comments