golang / vscode-go

Go extension for Visual Studio Code
https://marketplace.visualstudio.com/items?itemName=golang.Go
Other
3.89k stars 754 forks source link

Optional configuration paths for gopls, go-outline, godef & C. #2874

Closed bigluck closed 1 year ago

bigluck commented 1 year ago

Is your feature request related to a problem? Please describe. Using devenv in conjunction with nix makes it hard to have a "portable" and "reproducible" development environment with go & vscode-go.

devenv, when activated, will install golang and other system packages in a subshell. Env variables are updated in the sub-shell, but are not readable by VS Code.

Example of my devenv.nix file:

{ pkgs, ... }:

# See full reference at https://devenv.sh/reference/options/
{
  # https://devenv.sh/packages/
  packages = [
    pkgs.git
    pkgs.pre-commit
    pkgs.gopls
    pkgs.godef
    pkgs.go-outline
  ];
  # https://devenv.sh/languages/
  languages.go = {
    enable = true;
    package = pkgs.go_1_20;
  };
}

With the current version of the plugin I can manually set the go.gopath:

{
  "go.gopath": "${workspaceRoot}/.devenv/profile/share/go"
}

It points to a sandboxed folder of the golang interpreter, but that folder only contains the standard go binaries. Indeed godef, gopls and go-outline are installed in different sendboxed folders (because this is what Nix does and what makes Nix a fully reproducible package manager):

$ ls -la .devenv/profile/bin | grep go
lrwxr-xr-x@  1 root  wheel    61 Jan  1  1970 go -> /nix/store/9r7k2lwqyqhz4zr0pg5kz88ynpqkrp1n-go-1.19.11/bin/go
lrwxr-xr-x@  1 root  wheel    77 Jan  1  1970 go-contrib-init -> /nix/store/dp2ypzb90jm9bqjwx8ijzl4zixkd7ymj-gotools-0.7.0/bin/go-contrib-init
lrwxr-xr-x@  1 root  wheel    89 Jan  1  1970 go-outline -> /nix/store/diia4bvrw4jbh33gpy38lkkk5y5y2jc6-go-outline-unstable-2021-06-08/bin/go-outline
lrwxr-xr-x@  1 root  wheel    65 Jan  1  1970 godef -> /nix/store/d3dnkbdl4mkfvv278jnnh4a7kb9niabj-godef-1.1.2/bin/godef
lrwxr-xr-x@  1 root  wheel    67 Jan  1  1970 godex -> /nix/store/dp2ypzb90jm9bqjwx8ijzl4zixkd7ymj-gotools-0.7.0/bin/godex
lrwxr-xr-x@  1 root  wheel    67 Jan  1  1970 godoc -> /nix/store/dp2ypzb90jm9bqjwx8ijzl4zixkd7ymj-gotools-0.7.0/bin/godoc
lrwxr-xr-x@  1 root  wheel    64 Jan  1  1970 gofmt -> /nix/store/9r7k2lwqyqhz4zr0pg5kz88ynpqkrp1n-go-1.19.11/bin/gofmt
lrwxr-xr-x@  1 root  wheel    72 Jan  1  1970 gogrep -> /nix/store/d5x4lldr12wc7m82r4wf0r0ylsjw9j9w-go-tools-2023.1.3/bin/gogrep
lrwxr-xr-x@  1 root  wheel    71 Jan  1  1970 goimports -> /nix/store/dp2ypzb90jm9bqjwx8ijzl4zixkd7ymj-gotools-0.7.0/bin/goimports
lrwxr-xr-x@  1 root  wheel    80 Jan  1  1970 gomodifytags -> /nix/store/r5iwzpq4nx1am5l94phq0d2irmnc5phm-gomodifytags-1.16.0/bin/gomodifytags
lrwxr-xr-x@  1 root  wheel    69 Jan  1  1970 gomvpkg -> /nix/store/dp2ypzb90jm9bqjwx8ijzl4zixkd7ymj-gotools-0.7.0/bin/gomvpkg
lrwxr-xr-x@  1 root  wheel    72 Jan  1  1970 gopackages -> /nix/store/dp2ypzb90jm9bqjwx8ijzl4zixkd7ymj-gotools-0.7.0/bin/gopackages
lrwxr-xr-x@  1 root  wheel    66 Jan  1  1970 gopls -> /nix/store/zjkinl7ifxcsjzmxfpl5qm7vbgwq8csb-gopls-0.12.4/bin/gopls
lrwxr-xr-x@  1 root  wheel    70 Jan  1  1970 gorename -> /nix/store/dp2ypzb90jm9bqjwx8ijzl4zixkd7ymj-gotools-0.7.0/bin/gorename
lrwxr-xr-x@  1 root  wheel    73 Jan  1  1970 gosmith -> /nix/store/d5x4lldr12wc7m82r4wf0r0ylsjw9j9w-go-tools-2023.1.3/bin/gosmith
lrwxr-xr-x@  1 root  wheel    70 Jan  1  1970 gostacks -> /nix/store/dp2ypzb90jm9bqjwx8ijzl4zixkd7ymj-gotools-0.7.0/bin/gostacks
lrwxr-xr-x@  1 root  wheel    69 Jan  1  1970 gotests -> /nix/store/nzfyxvd3azhn4zxfw7jgypjyw81yl2cy-gotests-1.6.0/bin/gotests
lrwxr-xr-x@  1 root  wheel    68 Jan  1  1970 gotype -> /nix/store/dp2ypzb90jm9bqjwx8ijzl4zixkd7ymj-gotools-0.7.0/bin/gotype
lrwxr-xr-x@  1 root  wheel    68 Jan  1  1970 goyacc -> /nix/store/dp2ypzb90jm9bqjwx8ijzl4zixkd7ymj-gotools-0.7.0/bin/goyacc

Describe the solution you'd like The easier solution is to replicate what the Python plugin does. In Python the end user can configure the full path (or just the name) of a command, as you can see in this screenshot:

Screenshot 2023-07-17 at 14 19 36

This is a common problem in Python, especially when you need to run your code in a virtual environment (python3 -m venv .venv).

By following this approach, the go plugin should be updated by exposing a configuration entry for every optional package, allowing the user to set its full path if needed (or by using as a fallback the actual value).

This will not be a breaking change but will unlock advanced usage.

hyangah commented 1 year ago

Have you looked into the "go.alternateTools" setting? Assuming that the extension currently requires gopls, dlv, and gotests, gomodifytags depending on your workflow, I think you just need to configure the absolute paths for a couple of tools. Note that go-outline, godef, etc are no longer needed. (see https://github.com/golang/vscode-go/issues/2799 for details)

You can even specify the full path of the go command line with "go.alternateTools".

Let us know if this doesn't work for you.

Lastly, "go.gopath" is to configure GOPATH. That shouldn't point to the path that contain standard libraries or go command.

bigluck commented 1 year ago

Waw, I completely missed that config, thanks so much @hyangah !

Screenshot 2023-07-17 at 15 54 08

Now I have something like:

{
  "go.alternateTools": {
    "go": "${workspaceRoot}/.devenv/profile/bin/go",
    "gomodifytags": "${workspaceRoot}/.devenv/profile/bin/gomodifytags",
    "godef": "${workspaceRoot}/.devenv/profile/bin/godef",
    "gofmt": "${workspaceRoot}/.devenv/profile/bin/gofmt",
    "goimports": "${workspaceRoot}/.devenv/profile/bin/goimports",
    "gopls": "${workspaceRoot}/.devenv/profile/bin/gopls",
    "godoc": "${workspaceRoot}/.devenv/profile/bin/godoc",
    "gotests": "${workspaceRoot}/.devenv/profile/bin/gotests",
    "godex": "${workspaceRoot}/.devenv/profile/bin/godex",
    "dlv": "${workspaceRoot}/.devenv/profile/bin/dlv"
  },
  "go.formatTool": "gofmt",
  "editor.formatOnSave": true
}

And it works! Is there any room for additional optimization? Essentially all the binaries are in the same folder (${workspaceRoot}/.devenv/profile/bin/), but looks like I have to manually define all of them.

Thanks

hyangah commented 1 year ago

Good to know that that works. As I mentioned earlier, godef, gofmt, goimports, godoc, godex are not used by this extension, so you can delete the entries.