Skip to content

Commit d1ba8c0

Browse files
authored
Merge pull request #944 from erizocosmico/feature/uast-imports
function: implement uast_imports UDF
2 parents 69b10c9 + 1e3ca76 commit d1ba8c0

File tree

7 files changed

+148
-5
lines changed

7 files changed

+148
-5
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Added
10+
11+
- `uast_imports` function to gather import paths from an UAST.
12+
913
## [0.24.0-beta2] - 2019-07-31
1014

1115
### Changed

docs/using-gitbase/examples.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,27 @@ As result, you will get an array showing a list of the retrieved information. Ea
227227
+-------------------+-----------------------------------------------------------------------------------------------+
228228
```
229229

230+
## Extracting all import paths
231+
232+
```sql
233+
SELECT file_path,
234+
uast_imports(uast(blob_content, LANGUAGE(file_path, blob_content))) AS imports
235+
FROM refs
236+
NATURAL JOIN commit_files
237+
NATURAL JOIN blobs
238+
WHERE ref_name = 'HEAD' AND LANGUAGE(file_path) = 'Go';
239+
```
240+
241+
As result, you will get an array with an array of import paths for each node in the UAST.
242+
243+
```sh
244+
+-------------------------------------------------------------------------------------------------------------------+
245+
| file_path | imports |
246+
+-------------------+-----------------------------------------------------------------------------------------------+
247+
| _example/main.go | [["fmt","database/sql","github.com/sirupsen/logrus"]] |
248+
+-------------------+-----------------------------------------------------------------------------------------------+
249+
```
250+
230251
## Monitor the progress of a query
231252

232253
You can monitor the progress of a gitbase query (either a regular query or an index creation query using `SHOW PROCESSLIST`).

go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.12
44

55
require (
66
github.com/bblfsh/go-client/v4 v4.1.0
7-
github.com/bblfsh/sdk/v3 v3.1.0
7+
github.com/bblfsh/sdk/v3 v3.2.2
88
github.com/gliderlabs/ssh v0.2.0 // indirect
99
github.com/go-kit/kit v0.8.0
1010
github.com/go-sql-driver/mysql v1.4.1
@@ -14,7 +14,7 @@ require (
1414
github.com/miekg/dns v1.1.1 // indirect
1515
github.com/opentracing/opentracing-go v1.1.0
1616
github.com/prometheus/client_golang v1.0.0
17-
github.com/sirupsen/logrus v1.3.0
17+
github.com/sirupsen/logrus v1.4.2
1818
github.com/src-d/enry/v2 v2.0.0
1919
github.com/src-d/go-borges v0.0.0-20190628121335-da12a84d60fd
2020
github.com/src-d/go-git v4.7.0+incompatible
@@ -25,7 +25,6 @@ require (
2525
github.com/uber/jaeger-client-go v2.16.0+incompatible
2626
github.com/uber/jaeger-lib v2.0.0+incompatible // indirect
2727
go.uber.org/atomic v1.4.0 // indirect
28-
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 // indirect
2928
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b // indirect
3029
golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect
3130
golang.org/x/sys v0.0.0-20190618155005-516e3c20635f // indirect

go.sum

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2+
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
23
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
34
github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
45
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
@@ -33,9 +34,12 @@ github.com/bblfsh/go-client/v4 v4.1.0 h1:z9S5GrUSB0uiipbWauc5fV6D/R0LNBi65dhfP5u
3334
github.com/bblfsh/go-client/v4 v4.1.0/go.mod h1:UUAG7jrxSr7WHlFL/U8den1kLHfysZWJ9jA1Y0IiQ+0=
3435
github.com/bblfsh/sdk/v3 v3.1.0 h1:V+4DqGlqbxiAEAU0XlpTjjbq/g0ljfiFoh9jsIkfbtU=
3536
github.com/bblfsh/sdk/v3 v3.1.0/go.mod h1:juMiu8rP3lYJN1e4neEkSyzNieqiFceZzN4AOo0Rm1Q=
37+
github.com/bblfsh/sdk/v3 v3.2.2 h1:+Kr5hTK8ZklcjRQgfiMnM6JNI5faN1bsW/JZAHD8kyI=
38+
github.com/bblfsh/sdk/v3 v3.2.2/go.mod h1:LSY0KJDbK4tQHGIk3rEYX4sAeWgZzNqV1E3Bp30/Nrw=
3639
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
3740
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
3841
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
42+
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
3943
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
4044
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
4145
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
@@ -219,6 +223,8 @@ github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjM
219223
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
220224
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
221225
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
226+
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
227+
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
222228
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
223229
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
224230
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
@@ -230,6 +236,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
230236
github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
231237
github.com/src-d/enry/v2 v2.0.0 h1:2ADqfDHhroFwL1RGhMS9e15NkEwln8P4AABwVvIdAlo=
232238
github.com/src-d/enry/v2 v2.0.0/go.mod h1:qQeCMRwzMF3ckeGr+h0tJLdxXnq+NVZsIDMELj0t028=
239+
github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc=
233240
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
234241
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
235242
github.com/src-d/go-borges v0.0.0-20190628121335-da12a84d60fd h1:jUbtZFWSqGX1DfD2evCwA4y7LIrWV0W8h06sjWZANf0=
@@ -278,8 +285,8 @@ golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnf
278285
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
279286
golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
280287
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
281-
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU=
282-
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
288+
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
289+
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
283290
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
284291
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
285292
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -289,6 +296,7 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
289296
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
290297
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
291298
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
299+
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
292300
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
293301
golang.org/x/net v0.0.0-20190227022144-312bce6e941f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
294302
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -299,6 +307,7 @@ golang.org/x/net v0.0.0-20190607181551-461777fb6f67/go.mod h1:z5CRVTTTmAJ677TzLL
299307
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b h1:lkjdUzSyJ5P1+eal9fxXX9Xg2BTfswsonKUse48C0uE=
300308
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
301309
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
310+
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
302311
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
303312
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
304313
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -364,6 +373,7 @@ gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzW
364373
gopkg.in/src-d/go-git.v4 v4.11.0/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk=
365374
gopkg.in/src-d/go-git.v4 v4.12.0 h1:CKgvBCJCcdfNnyXPYI4Cp8PaDDAmAPEN0CtfEdEAbd8=
366375
gopkg.in/src-d/go-git.v4 v4.12.0/go.mod h1:zjlNnzc1Wjn43v3Mtii7RVxiReNP0fIu9npcXKzuNp4=
376+
gopkg.in/src-d/go-log.v1 v1.0.2/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
367377
gopkg.in/src-d/go-siva.v1 v1.5.0 h1:WowvbZTlz0SPoV7WNCGktPSi2yRK78HPyXl7wYqDeHE=
368378
gopkg.in/src-d/go-siva.v1 v1.5.0/go.mod h1:tk1jnIXawd/PTlRNWdr5V5lC0PttNJmu1fv7wt7IZlw=
369379
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=

internal/function/registry.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ var Functions = []sql.Function{
1515
sql.Function2{Name: "uast_xpath", Fn: NewUASTXPath},
1616
sql.Function2{Name: "uast_extract", Fn: NewUASTExtract},
1717
sql.Function1{Name: "uast_children", Fn: NewUASTChildren},
18+
sql.Function1{Name: "uast_imports", Fn: NewUASTImports},
1819
sql.Function1{Name: "is_vendor", Fn: NewIsVendor},
1920
}

internal/function/uast.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,3 +759,70 @@ func getChildren(node nodes.Object) nodes.Array {
759759

760760
return children
761761
}
762+
763+
// UASTImports finds the imports in UAST nodes.
764+
type UASTImports struct {
765+
expression.UnaryExpression
766+
}
767+
768+
// NewUASTImports creates a new UASTImports node.
769+
func NewUASTImports(child sql.Expression) sql.Expression {
770+
return &UASTImports{expression.UnaryExpression{Child: child}}
771+
}
772+
773+
// Type implements the sql.Expression interface.
774+
func (f *UASTImports) Type() sql.Type {
775+
return sql.Array(sql.Array(sql.Text))
776+
}
777+
778+
// IsNullable implements the sql.Expression interface.
779+
func (f *UASTImports) IsNullable() bool { return true }
780+
781+
// Eval implements the sql.Expression interface.
782+
func (f *UASTImports) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
783+
span, ctx := ctx.Span("function.UASTImports")
784+
defer span.Finish()
785+
786+
child, err := f.Child.Eval(ctx, row)
787+
if err != nil {
788+
return nil, err
789+
}
790+
791+
nodes, err := getNodes(child)
792+
if err != nil {
793+
return nil, err
794+
}
795+
796+
if nodes == nil {
797+
return nil, nil
798+
}
799+
800+
var result = make([]interface{}, nodes.Size())
801+
for i := 0; i < nodes.Size(); i++ {
802+
node := nodes.ValueAt(i)
803+
imports := uast.AllImportPaths(node)
804+
nodeImports := make([]interface{}, len(imports))
805+
for j, imp := range imports {
806+
nodeImports[j] = imp
807+
}
808+
result[i] = nodeImports
809+
}
810+
811+
return result, nil
812+
}
813+
814+
func (f *UASTImports) String() string {
815+
return fmt.Sprintf("uast_imports(%s)", f.Child)
816+
}
817+
818+
// Children implements the sql.Expression interface.
819+
func (f *UASTImports) Children() []sql.Expression { return []sql.Expression{f.Child} }
820+
821+
// WithChildren implements the sql.Expression interface.
822+
func (f *UASTImports) WithChildren(children ...sql.Expression) (sql.Expression, error) {
823+
if len(children) != 1 {
824+
return nil, sql.ErrInvalidChildrenNumber.New(f, len(children), 1)
825+
}
826+
827+
return NewUASTImports(children[0]), nil
828+
}

internal/function/uast_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,47 @@ func TestExtractAnyProp(t *testing.T) {
360360
require.Nil(t, props)
361361
}
362362

363+
func TestUASTImports(t *testing.T) {
364+
code := `
365+
package foo
366+
367+
import "fmt"
368+
import "github.com/src-d/foo"
369+
import "gopkg.in/src-d/bar"
370+
371+
func main() {
372+
fmt.Println("Hello", foo.Foo, bar.Bar)
373+
}
374+
`
375+
376+
ctx, cleanup := setup(t)
377+
defer cleanup()
378+
379+
require := require.New(t)
380+
381+
f, err := NewUAST(
382+
expression.NewLiteral([]byte(code), sql.Blob),
383+
expression.NewLiteral("Go", sql.Text),
384+
)
385+
require.NoError(err)
386+
result, err := f.Eval(ctx, nil)
387+
require.NoError(err)
388+
require.NotNil(result)
389+
390+
result, err = NewUASTImports(expression.NewLiteral(result, sql.Blob)).Eval(ctx, nil)
391+
require.NoError(err)
392+
393+
expected := []interface{}{
394+
[]interface{}{
395+
"fmt",
396+
"github.com/src-d/foo",
397+
"gopkg.in/src-d/bar",
398+
},
399+
}
400+
401+
require.Equal(expected, result)
402+
}
403+
363404
func assertUASTBlobs(t *testing.T, ctx *sql.Context, a, b interface{}) {
364405
t.Helper()
365406
var require = require.New(t)

0 commit comments

Comments
 (0)