Skip to content
Andrew Muldowney edited this page Oct 18, 2024 · 11 revisions

Usage

The GOPACKAGESDRIVER allows gopls and any package using x/tools/packages to expose package data. Configuring the rules_go's packages driver is simple.

1. gopls

gopls >= v0.6.10 (released on Apr 13th 2021) is required.

Install it in your path. If you have $GOBIN in your PATH, this should do the trick:

$ go install golang.org/x/tools/gopls@v0.7.2

If you are using Visual Studio Code, it should have been automatically updated by now.

2. Launcher script

Create a launcher script, say tools/gopackagesdriver.sh. If your repo is loading rules_go in its MODULE.bazel, give it these contents:

#!/usr/bin/env bash
# See https://github.com/bazelbuild/rules_go/wiki/Editor-setup#3-editor-setup
exec bazel run -- @rules_go//go/tools/gopackagesdriver "${@}"

If your repo is still loading rules_go in the WORKSPACE file:

#!/usr/bin/env bash
# See https://github.com/bazelbuild/rules_go/wiki/Editor-setup#3-editor-setup
exec bazel run -- @io_bazel_rules_go//go/tools/gopackagesdriver "${@}"

3. Editor Setup

You might want to replace github.com/my/mypkg with your package. When first opening a file in the workspace, give the driver some time to load.

Neovim

nvim_lsp.gopls.setup {
  on_attach = on_attach,
  settings = {
    gopls = {
      env = {
        GOPACKAGESDRIVER = './tools/gopackagesdriver.sh'
      },
      directoryFilters = {
        "-bazel-bin",
        "-bazel-out",
        "-bazel-testlogs",
        "-bazel-mypkg",
      },
      ...
    },
  },
}

Visual Studio Code

In the .vscode/settings.json of your workspace, you'll need to one of the two following JSON blobs, depending on if your repo is using MODULE.bazel or WORKSPACE to load rules_go (the difference is in the go.goroot). Also, for both of these, you'll need to edit two lines:

  1. In build.directoryFilters replace mypkg in bazel-mypkg with your repo's module name.
  2. In formatting.local replace the import path there with the import path of your repo's code.

If you're using MODULE.bazel, use a JSON blob like:

{
  // Settings for go/bazel are based on editor setup instructions at
  // https://github.com/bazelbuild/rules_go/wiki/Editor-setup#visual-studio-code
  "go.goroot": "${workspaceFolder}/bazel-${workspaceFolderBasename}/external/rules_go~~go_sdk~${workspaceFolderBasename}__download_0/",
  "go.toolsEnvVars": {
    "GOPACKAGESDRIVER": "${workspaceFolder}/tools/gopackagesdriver.sh"
  },
  "go.enableCodeLens": {
    "runtest": false
  },
  "gopls": {
    "build.directoryFilters": [
      "-bazel-bin",
      "-bazel-out",
      "-bazel-testlogs",
      "-bazel-mypkg",
    ],
    "formatting.gofumpt": true,
    "formatting.local": "github.com/my/mypkg",
    "ui.completion.usePlaceholders": true,
    "ui.semanticTokens": true,
    "ui.codelenses": {
      "gc_details": false,
      "regenerate_cgo": false,
      "generate": false,
      "test": false,
      "tidy": false,
      "upgrade_dependency": false,
      "vendor": false
    },
  },
  "go.useLanguageServer": true,
  "go.buildOnSave": "off",
  "go.lintOnSave": "off",
  "go.vetOnSave": "off",
}

If your repo is using WORKSPACE to load rules_go, use this json blob:

{
  // Settings for go/bazel are based on editor setup instructions at
  // https://github.com/bazelbuild/rules_go/wiki/Editor-setup#visual-studio-code
  "go.goroot": "${workspaceFolder}/bazel-${workspaceFolderBasename}/external/go_sdk",
  "go.toolsEnvVars": {
    "GOPACKAGESDRIVER": "${workspaceFolder}/tools/gopackagesdriver.sh"
  },
  "go.enableCodeLens": {
    "runtest": false
  },
  "gopls": {
    "build.directoryFilters": [
      "-bazel-bin",
      "-bazel-out",
      "-bazel-testlogs",
      "-bazel-mypkg",
    ],
    "formatting.gofumpt": true,
    "formatting.local": "github.com/my/mypkg",
    "ui.completion.usePlaceholders": true,
    "ui.semanticTokens": true,
    "ui.codelenses": {
      "gc_details": false,
      "regenerate_cgo": false,
      "generate": false,
      "test": false,
      "tidy": false,
      "upgrade_dependency": false,
      "vendor": false
    },
  },
  "go.useLanguageServer": true,
  "go.buildOnSave": "off",
  "go.lintOnSave": "off",
  "go.vetOnSave": "off",
}

Sublime Text

Here is a sample .sublime-project:

{
  "folders": [
    {
      "path": ".",
      "folder_exclude_patterns": ["bazel-*"]
    }
  ],
  "settings": {
    "lsp_format_on_save": true,
    "LSP": {
      "gopls": {
        "enabled": true,
        "command": ["~/go/bin/gopls"],
        "selector": "source.go",
        "settings": {
          "gopls.directoryFilters": [
            "-bazel-bin",
            "-bazel-out",
            "-bazel-testlogs",
            "-bazel-mypkg",
          ],
          "gopls.allowImplicitNetworkAccess": false,
          "gopls.usePlaceholders": true,
          "gopls.gofumpt": true,
          "gopls.local": "github.com/my/mypkg",
          "gopls.semanticTokens": true,
          "gopls.codelenses": {
            "gc_details": false,
            "regenerate_cgo": false,
            "generate": false,
            "test": false,
            "tidy": false,
            "upgrade_dependency": false,
            "vendor": false
          }
        },
        "env": {
          "GOPACKAGESDRIVER": "./tools/gopackagesdriver.sh"
        }
      }
    }
  }
}

Helix Editor

Here is a sample .helix/languages.toml:

[[language]]
name = "go"

[language.config]
env = { GOPACKAGESDRIVER = './tools/gopackagesdriver.sh' }
gofumpt     = true
staticcheck = true
local = "github.com/my/mypkg"
directoryFilters = ["-bazel-bin","-bazel-out","-bazel-testlogs","-bazel-mypkg"]
usePlaceholders = true
semanticTokens = true
codelenses = {gc_details=false, generate=false, regenerate_cgo=false, tidy=false, upgrade_dependency=false, vendor=false}

Environment variables

The package driver has a few environment configuration variables, although most won't need to configure them:

  • GOPACKAGESDRIVER_BAZEL: bazel binary, defaults to bazel
  • BUILD_WORKSPACE_DIRECTORY: directory of the bazel workspace (auto detected when using a launcher script because it invokes bazel run)
  • GOPACKAGESDRIVER_BAZEL_FLAGS which will be passed to bazel invocations
  • GOPACKAGESDRIVER_BAZEL_QUERY_FLAGS which will be passed to bazel query invocations
  • GOPACKAGESDRIVER_BAZEL_QUERY_SCOPE which specifies the scope for importpath queries (since gopls only issues file= queries, so use if you know what you're doing!)
  • GOPACKAGESDRIVER_BAZEL_BUILD_FLAGS which will be passed to bazel build invocations

Debugging

It is possible to debug driver issues by calling it directly and looking at the errors in the outputs:

$ echo {} | ./tools/gopackagesdriver.sh file=relative/path.go

Limitations

  • CGo completion may not work, but at least it's not explicitly supported.
  • Errors are not handled