func (fs *remoteFS) Walk(ctx context.Context) ([]lsp.DocumentURI, error) {
	params := lspext.FilesParams{}
	var res []lsp.TextDocumentIdentifier
	if err := fs.conn.Call(ctx, "workspace/xfiles", &params, &res); err != nil {
		return nil, errors.Wrap(err, "calling workspace/xfiles failed")
	}
	var fileURIs []lsp.DocumentURI
	for _, ident := range res {
		fileURIs = append(fileURIs, ident.URI)
	}
	return fileURIs, nil
}
Walk returns a list of all file uris.
package main
import (
	"context"
	"io/ioutil"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"sync"
	"github.com/neelance/parallel"
	"github.com/pkg/errors"
	"github.com/sourcegraph/go-langserver/pkg/lsp"
	"github.com/sourcegraph/go-langserver/pkg/lspext"
	"github.com/sourcegraph/jsonrpc2"
	nettrace "golang.org/x/net/trace"
)
type remoteFS struct {
	conn    *jsonrpc2.Conn
	traceID string
}
func (fs *remoteFS) BatchOpen(ctx context.Context, fileURIs []lsp.DocumentURI) ([]batchFile, error) {
	par := parallel.NewRun(8)
	var mut sync.Mutex
	var batchFiles []batchFile
	for _, fileURI := range fileURIs {
		par.Acquire()
		go func(uri lsp.DocumentURI) {
			defer par.Release()
			text, err := fs.Open(ctx, uri)
			if err != nil {
				par.Error(err)
				return
			}
			mut.Lock()
			defer mut.Unlock()
			batchFiles = append(batchFiles, batchFile{uri: uri, content: text})
		}(fileURI)
	}
	if err := par.Wait(); err != nil {
		return nil, err
	}
	return batchFiles, nil
}
type batchFile struct {
	uri     lsp.DocumentURI
	content string
}
func (fs *remoteFS) Open(ctx context.Context, fileURI lsp.DocumentURI) (string, error) {
	params := lspext.ContentParams{TextDocument: lsp.TextDocumentIdentifier{URI: fileURI}}
	var res lsp.TextDocumentItem
	if err := fs.conn.Call(ctx, "textDocument/xcontent", params, &res); err != nil {
		return "", errors.Wrap(err, "calling textDocument/xcontent failed")
	}
	return res.Text, nil
}