Skip to content

Commit

Permalink
Add autocomplete support for bazel mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhong Wang committed Jul 25, 2016
1 parent 1be2565 commit 725b543
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 0 deletions.
3 changes: 3 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
type config struct {
ProposeBuiltins bool `json:"propose-builtins"`
LibPath string `json:"lib-path"`
CustomPkgPrefix string `json:"custom-pkg-prefix"`
CustomVendorDir string `json:"custom-vendor-dir"`
Autobuild bool `json:"autobuild"`
ForceDebugOutput string `json:"force-debug-output"`
PackageLookupMode string `json:"package-lookup-mode"`
Expand All @@ -30,6 +32,7 @@ type config struct {
var g_config = config{
ProposeBuiltins: false,
LibPath: "",
CustomPkgPrefix: "",
Autobuild: false,
ForceDebugOutput: "",
PackageLookupMode: "go",
Expand Down
36 changes: 36 additions & 0 deletions declcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ func log_build_context(context *package_lookup_context) {
log.Printf(" GOPATH: %s\n", context.GOPATH)
log.Printf(" GOOS: %s\n", context.GOOS)
log.Printf(" GOARCH: %s\n", context.GOARCH)
log.Printf(" BzlProjectRoot: %q\n", context.BzlProjectRoot)
log.Printf(" GBProjectRoot: %q\n", context.GBProjectRoot)
log.Printf(" lib-path: %q\n", g_config.LibPath)
}
Expand Down Expand Up @@ -320,6 +321,40 @@ func find_global_file(imp string, context *package_lookup_context) (string, bool
}
}

// bzl-specific lookup mode, only if the root dir was found
if g_config.PackageLookupMode == "bzl" && context.BzlProjectRoot != "" {
var root, impath string
if strings.HasPrefix(imp, g_config.CustomPkgPrefix+"/") {
root = filepath.Join(context.BzlProjectRoot, "bazel-bin")
impath = imp[len(g_config.CustomPkgPrefix)+1:]
} else if g_config.CustomVendorDir != "" {
// Try custom vendor dir.
root = filepath.Join(context.BzlProjectRoot, "bazel-bin", g_config.CustomVendorDir)
impath = imp
}

if root != "" && impath != "" {
// There might be more than one ".a" files in the pkg path with bazel.
// But the best practice is to keep one go_library build target in each
// pakcage directory so that it follows the standard Go package
// structure. Thus here we assume there is at most one ".a" file existing
// in the pkg path.
if d, err := os.Open(filepath.Join(root, impath)); err == nil {
defer d.Close()

if fis, err := d.Readdir(-1); err == nil {
for _, fi := range fis {
if !fi.IsDir() && filepath.Ext(fi.Name()) == ".a" {
pkg_path := filepath.Join(root, impath, fi.Name())
log_found_package_maybe(imp, pkg_path)
return pkg_path, true
}
}
}
}
}
}

if context.CurrentPackagePath != "" {
// Try vendor path first, see GO15VENDOREXPERIMENT.
// We don't check this environment variable however, seems like there is
Expand Down Expand Up @@ -382,6 +417,7 @@ func package_name(file *ast.File) string {

type package_lookup_context struct {
build.Context
BzlProjectRoot string
GBProjectRoot string
CurrentPackagePath string
}
Expand Down
9 changes: 9 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ func server_auto_complete(file []byte, filename string, cursor int, context_pack
g_daemon.drop_cache()
}
switch g_config.PackageLookupMode {
case "bzl":
// when package lookup mode is bzl, we set GOPATH to "" explicitly and
// BzlProjectRoot becomes valid (or empty)
var err error
g_daemon.context.GOPATH = ""
g_daemon.context.BzlProjectRoot, err = find_bzl_project_root(g_config.LibPath, filename)
if *g_debug && err != nil {
log.Printf("Bzl project root not found: %s", err)
}
case "gb":
// when package lookup mode is gb, we set GOPATH to "" explicitly and
// GBProjectRoot becomes valid (or empty)
Expand Down
26 changes: 26 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,32 @@ func has_prefix(s, prefix string, ignorecase bool) bool {
return strings.HasPrefix(s, prefix)
}

func find_bzl_project_root(libpath, path string) (string, error) {
if libpath == "" {
return "", fmt.Errorf("could not find project root, libpath is empty")
}

pathMap := map[string]struct{}{}
for _, lp := range strings.Split(libpath, ":") {
lp := strings.TrimSpace(lp)
pathMap[filepath.Clean(lp)] = struct{}{}
}

path = filepath.Dir(path)
if path == "" {
return "", fmt.Errorf("project root is blank")
}

start := path
for path != "/" {
if _, ok := pathMap[filepath.Clean(path)]; ok {
return path, nil
}
path = filepath.Dir(path)
}
return "", fmt.Errorf("could not find project root in %q or its parents", start)
}

// Code taken directly from `gb`, I hope author doesn't mind.
func find_gb_project_root(path string) (string, error) {
path = filepath.Dir(path)
Expand Down

0 comments on commit 725b543

Please sign in to comment.