golang / vscode-go

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

Linter does not support go workspaces (go.work) #2666

Open Chamuelm opened 1 year ago

Chamuelm commented 1 year ago

What version of Go, VS Code & VS Code Go extension are you using?

Version Information
* Run `go version` to get version of Go from _the VS Code integrated terminal_. - go1.20 linux/amd64 * Run `gopls -v version` to get version of Gopls from _the VS Code integrated terminal_. - golang.org/x/tools/gopls v0.11.0 * Run `code -v` or `code-insiders -v` to get version of VS Code or VS Code Insiders. - 1.75.0 e2816fe719a4026ffa1ee0189dc89bdfdbafb164 x64 * Check your installed extensions to get the version of the VS Code Go extension - v0.37.1 * Run Ctrl+Shift+P (Cmd+Shift+P on Mac OS) > `Go: Locate Configured Go Tools` command. ``` Checking configured tools.... GOBIN: undefined toolsGopath: gopath: /go GOROOT: /usr/local/go PATH: /go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PATH (vscode launched with): /vscode/vscode-server/bin/linux-x64/e2816fe719a4026ffa1ee0189dc89bdfdbafb164/bin/remote-cli:/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin go: /usr/local/go/bin/go: go version go1.20 linux/amd64 gotests: not installed gomodifytags: /go/bin/gomodifytags (version: v1.16.0 built with go: go1.20) impl: not installed goplay: not installed dlv: /go/bin/dlv (version: v1.20.1 built with go: go1.20) golangci-lint: /go/bin/golangci-lint (version: (devel) built with go: go1.20) gopls: /go/bin/gopls (version: v0.11.0 built with go: go1.20) go env Workspace Folder (activitylogs): /workspaces/activitylogs GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/home/unbiased/.cache/go-build" GOENV="/home/unbiased/.config/go/env" GOEXE="" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOINSECURE="" GOMODCACHE="/go/pkg/mod" GONOPROXY="github.com/unbiased-security" GONOSUMDB="github.com/unbiased-security" GOOS="linux" GOPATH="/go" GOPRIVATE="github.com/unbiased-security" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64" GOVCS="" GOVERSION="go1.20" GCCGO="gccgo" GOAMD64="v1" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="/dev/null" GOWORK="/workspaces/activitylogs/go.work" CGO_CFLAGS="-O2 -g" CGO_CPPFLAGS="" CGO_CXXFLAGS="-O2 -g" CGO_FFLAGS="-O2 -g" CGO_LDFLAGS="-O2 -g" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2929876491=/tmp/go-build -gno-record-gcc-switches" ```

Share the Go related settings you have added/edited

Go settings
``` "go.buildOnSave": "off", "go.lintOnSave": "workspace", "go.vetOnSave": "workspace", "go.buildTags": "", "go.buildFlags": [], "go.lintTool": "golangci-lint", "go.lintFlags": [ "--fast" ], "go.vetFlags": [], "go.testOnSave": true, "go.coverOnSave": false, "go.useCodeSnippetsOnFunctionSuggest": true, "editor.formatOnSave": true, "go.formatTool": "goimports", "go.formatFlags": [], "go.goroot": "", "go.gopath": "", "go.inferGopath": false, "go.gocodeAutoBuild": false, "go.testFlags": [ "-v" ], "go.useLanguageServer": true, "go.docsTool": "gogetdoc", "go.liveErrors": { "enabled": true, "delay": 500, }, ```

Describe the bug

The lint feature does not work in a go-workspace (go.work) workspace, this also happens if you run the linter manually:

> golangci-lint run
ERRO [linters_context] typechecking error: pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies

You have to run the linter separatly for each sub-module. This is how I solved it in our CI: go work edit -json | jq -r '.Use[].DiskPath' | xargs --verbose -I{} golangci-lint run {}/...

The "Lint Current Package" still works.

We use the repository as monorepo so we actually need all of the go tools for all of the submodules.

Steps to reproduce the behavior:

  1. Create a new workspace with submodules and a golangci-lint as a linter
  2. Trigger lint on whole workspace

Screenshots or recordings

The error message from the extension output:

Starting linting the current workspace at /workspaces/activitylogs
Error while running tool: /go/bin/golangci-lint run --fast --print-issued-lines=false --out-format=colored-line-number --issues-exit-code=0 ./...
level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies"
jamalc commented 1 year ago

This isn't something vscode has any effect on. Did you mean to file this in golang/go?

Related issue at golangci/golangci-lint#2654.

Chamuelm commented 1 year ago

It's relate to the way vscode execute the lint command

adonovan commented 1 year ago

As @jamalc pointed out, this is a bug in golangci-lint: it appears to be running go list ./..., which is not going to work in a tree that has a go.work file that doesn't specify . as a workspace module. The gopls tool parses the workspace file to ascertain the set of modules; I think golangci-lint may need to do something similar.

Unfortunately this is not something we have any control over.

hyangah commented 1 year ago

I am reopening this issue because vscode-go is involved too. Currently there is no standard way of running all tests from all modules included in the workspace. Before go.work or even before Go modules, we could run lint, build, test with ./... pattern easily and that's how this extension has implemented workspace/repo-wide linting/analysis/test/generate features. However, after the Go modules and go.work, ./... is no longer suitable for editor-perceived workspace-wide operations. https://github.com/golang/go/issues/50745

The extension still relies on ./... and feeds this to golangci-lint, go test, staticcheck unconditionally if user requests editor's workspace-wide linting and testing. This needs to be changed.

Options:

  1. wait until go command comes up with a solution and switch to it.
  2. replace ./... with something equivalent with golangci-lint $(go list -f '{{.Dir}}/...' -m | xargs)).
  3. retrieve the list of modules or patterns from our oracle gopls.
aksanart commented 1 year ago

hello i'm facing the same issue when use golangci-lint with jenkins golangci-lint run --fix ./... level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies change to golangci-lint run --fix $(go list -f '{{.Dir}}/...' -m | xargs) level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies still got the same error

MemoryLeak55 commented 1 year ago

I have found a temporary workaround to get golanglint-ci to work until a proper fix comes around.

Find your golangci-lint binary with

which golangci-lint

Change into that directory

cd <dir name>

Backup golangci-lint. (don't delete it, or move it anywhere else)

mv golangci-lint golangci-lint.bak

make a new file called golangci-lint with your favorite editor, add the following bash

#!/bin/bash

# remove ./... from argument list
for arg do
  shift
  [ "$arg" = "./..." ] && continue
  set -- "$@" "$arg"
done

# If our current directory has a go.work file then we are in a workspace and we run golangci-lint run go list -f '{{.Dir}}/...' -m 
# I am explicitly calling golangci-lint.bak (the original binary, not this script. That would not work)
if [ -f go.work ]; then
     go list -f '{{.Dir}}/...' -m | xargs golangci-lint.bak $@
else
    golangci-lint.bak $@
fi

Set the file to be executable

chmod +x golangci-lint

And setup golangci-lint as your linter in vscode as per usual.

Note: This is likely to break in weird ways, but it works for my simple projects. It's a stopgap until a better solution comes around. Additionally if you update golangci-lint it will likely override your script. You will then need to delete the backup you made, and redo the process

e-compton-bb commented 7 months ago

Golangci-lint seem to have concluded that their linter is not meant to run directly on a workspace and has provided a number of different commands to iterate over all the modules. Seems like this extension should be updated to use one of them instead? https://github.com/golangci/golangci-lint/issues/2654#issuecomment-1606439587

gopherbot commented 7 months ago

Change https://go.dev/cl/567715 mentions this issue: Fixes golang/vscode-go#2666