bblfsh / go-client

Babelfish Go client
https://doc.bblf.sh/using-babelfish/clients.html
Apache License 2.0
37 stars 20 forks source link
babelfish client golang

go-client GoDoc Build Status Build status codecov

Babelfish Go client library provides functionality to both connecting to the Babelfish server for parsing code (obtaining an UAST as a result) and for analysing UASTs with the functionality provided by libuast.

Installation

The recommended way to install go-client is:

go get -u github.com/bblfsh/go-client/v4/...

Example

CLI

Although go-client is a library, this codebase also includes an example of bblfsh-cli application at ./cmd/bblfsh-cli. When installed, it allows to parse a single file, query it with XPath and print the resulting UAST structure immediately. See $ bblfsh-cli -h for list of all available CLI options.

Code

This small example illustrates how to retrieve the UAST from a small Python script.

If you don't have a bblfsh server installed, please read the getting started guide, to learn more about how to use and deploy a bblfsh server.

Go to the quick start to discover how to run Babelfish with Docker.

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/bblfsh/go-client/v4"
    "github.com/bblfsh/go-client/v4/tools"

    "github.com/bblfsh/sdk/v3/uast/nodes"
    "github.com/bblfsh/sdk/v3/uast/uastyaml"

    "google.golang.org/grpc"
    "google.golang.org/grpc/keepalive"
)

func main() {
    ctx := context.Background()
    client, err := bblfsh.NewClientContext(ctx, "0.0.0.0:9432",
        // Set an extra grpc DialOptions to avoid "transport closing" errors when client is idle.
        // Passing keepalive params here, you can overwrite defaults:
        // Time: 2 minutes, PermitWithoutStream: true
        grpc.WithKeepaliveParams(keepalive.ClientParameters{
            // Time is a duration after this if the client doesn't see any activity it
            // pings the server to see if the transport is still alive.
            Time:                2 * time.Minute,

            // PermitWithoutStream is a boolean flag.
            // If true, client sends keepalive pings even with no active RPCs.
            PermitWithoutStream: true,
        }),
    )
    if err != nil {
        panic(err)
    }

    python := "import foo"
    res, _, err := client.NewParseRequest().Context(ctx).
        Language("python").Content(python).UAST()
    if err != nil {
        panic(err)
    }

    query := "//*[self::uast:Import or self::uast:RuntimeImport]"
    it, _ := tools.Filter(res, query)
    var nodeAr nodes.Array
    for it.Next() {
        nodeAr = append(nodeAr, it.Node().(nodes.Node))
    }

    // The example below emits YAML.
    //
    // Alternative 1: encode UAST nodes to JSON.
    //   data, err := json.MarshalIndent(nodeAr, "", "  ")
    //
    // Alternative 2: encode UAST nodes to protobuf.
    //   import "github.com/bblfsh/sdk/v3/uast/nodes/nodesproto"
    //   ...
    //   for _, node := range nodesAr {
    //      err := nodesproto.WriteTo(os.Stdout, nodeAr) // check
    //      ...
    //   }
    //
    data, err := uastyaml.Marshal(nodeAr)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(data))
}

produces

   { '@type': "uast:RuntimeImport",
      '@pos': { '@type': "uast:Positions",
         start: { '@type': "uast:Position",
            offset: 0,
            line: 1,
            col: 1,
         },
      },
      All: false,
      Names: ~,
      Path: { '@type': "uast:Identifier",
         '@pos': { '@type': "uast:Positions",
         },
         Name: "foo",
      },
      Target: ~,
   },
]
iter := tools.NewIterator(res, tools.PreOrder)
for node := range tools.Iterate(iter) {
    fmt.Println(node)
}

// For XPath expressions returning a boolean/numeric/string value, you must
// use the right typed Filter function:

boolres, err := tools.FilterBool(res, "boolean(//*[@start-offset or @end-offset])")
strres, err := tools.FilterString(res, "name(//*[1])")
numres, err := tools.FilterNumber(res, "count(//*)")

Please read the Babelfish clients guide section to learn more about babelfish clients and their query language.

License

Apache License 2.0, see LICENSE