gopls version

gopls -v version

Build info
----------
golang.org/x/tools/gopls v0.19.0
    golang.org/x/tools/gopls@v0.19.0 h1:DjtDZYqBkh8vFWotyXeBhqsu5rTx1E5CW9N2KDoMruk=
    github.com/BurntSushi/toml@v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
    github.com/fatih/camelcase@v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
    github.com/fatih/gomodifytags@v1.17.1-0.20250423142747-f3939df9aa3c h1:dDSgAjoOMp8da3egfz0t2S+t8RGOpEmEXZubcGuc0Bg=
    github.com/fatih/structtag@v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
    github.com/google/go-cmp@v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
    golang.org/x/exp/typeparams@v0.0.0-20250218142911-aa4b98e5adaa h1:Br3+0EZZohShrmVVc85znGpxw7Ca8hsUJlrdT/JQGw8=
    golang.org/x/mod@v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
    golang.org/x/sync@v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
    golang.org/x/telemetry@v0.0.0-20250417124945-06ef541f3fa3 h1:RXY2+rSHXvxO2Y+gKrPjYVaEoGOqh3VEXFhnWAt1Irg=
    golang.org/x/text@v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
    golang.org/x/tools@v0.34.1-0.20250610180157-87f68886ec5f h1:OQ4h61FPxSOC5Y6JY92YS4wZ9X4XDD5RBNRd72FSx2A=
    golang.org/x/vuln@v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I=
    honnef.co/go/tools@v0.7.0-0.dev.0.20250523013057-bbc2f4dd71ea h1:fj8r9irJSpolAGUdZBxJIRY3lLc4jH2Dt4lwnWyWwpw=
    mvdan.cc/gofumpt@v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
    mvdan.cc/xurls/v2@v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI=
go: go1.24.4

Vscode's Go: Locate Configured Go Tools

# Tools Configuration

## Tools

    go: /usr/local/go/bin/go: go version go1.24.4 linux/amd64

    gopls:  /home/nightjar/go/bin/gopls (version: v0.19.0 built with go: go1.24.4)
    gotests:    /home/nightjar/go/bin/gotests   (version: v1.6.0 built with go: go1.24.4)
    gomodifytags:   /home/nightjar/go/bin/gomodifytags  (version: v1.17.0 built with go: go1.24.4)
    impl:   /home/nightjar/go/bin/impl  (version: v1.4.0 built with go: go1.24.4)
    goplay: /home/nightjar/go/bin/goplay    (version: v1.0.0 built with go: go1.24.4)
    dlv:    /home/nightjar/go/bin/dlv   (version: v1.25.0 built with go: go1.24.4)
    staticcheck:    /home/nightjar/go/bin/staticcheck   (version: v0.6.1 built with go: go1.24.4)

go env

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/nightjar/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/nightjar/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1013662506=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/nightjar/somewhere/go.mod'
GOMODCACHE='/home/nightjar/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/nightjar/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/nightjar/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.4'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

Ignore lint-offending line using //lint:ignore

e.g.

//lint:ignore SA4000 we do what we must
if 1 == 1 {
}

What did you see happen?

Image

Image

What did you expect to see?

Lint warning is ignored.

Editor and settings

No response

Logs

No response

Comment From: gabyhelp

Related Issues

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

Comment From: adonovan

Retitling; this is not a gopls 0.19 regression: gopls has never processed the //lint:ignore directives that staticcheck's analysis driver parses. There are various ongoing discussion about whether the analysis framework should standardize how this is done. See for example: - https://github.com/golang/go/issues/58340 - https://github.com/golang/go/issues/65682 - https://github.com/golang/go/issues/50764

My own thoughts on the matter are expressed in https://github.com/golang/go/issues/50764#issuecomment-1777962402.

(I was going to mark this as a feature request--to implement directive parsing at parity with staticcheck--but it is actually a bug that gopls' documentation includes that of staticcheck's analyzers, which state that these annotations may be used when in fact they cannot [example].)

Comment From: kafji

If I got that right. In 0.19.0 a subset of staticcheck rules are adopted by gopls but gopls does not honor staticcheck's directive. The lint warning I got come from gopls.

From the perspective of user that treat gopls as a blackbox, finding the lint ignore stop working after upgrading to 0.19.0 comes as a surprise. Though I don't have opinion whether this outweigh the pitfalls introduced by allowing lint ignore.

One small improvement that can be made here is to make the hyperlink in Vscode's tooltip open gopls documentation instead of staticcheck's. Currently clicking default in my second image opens https://staticcheck.dev/docs/checks#SA4000

Comment From: adonovan

If I got that right. In 0.19.0 a subset of staticcheck rules are adopted by gopls but gopls does not honor staticcheck's directive. [...] finding the lint ignore stop working after upgrading to 0.19.0 comes as a surprise.

My understanding is that we have merely changed the set of staticcheck analyzers that are enabled by default, from none to just over half. The behavior of the analyzers should not have changed. If you enable the same subset of analyzers explicitly in gopls 18 you should observe the same behavior. (Do let me know if that is not what you observe.)

One small improvement that can be made here is to make the hyperlink in Vscode's tooltip open gopls documentation instead of staticcheck's. Currently clicking default in my second image opens https://staticcheck.dev/docs/checks#SA4000

Each Analyzer specifies its documentation URL, and that's the URL specified by SA4000 itself. I'm not what is gained by altering this URL to point to gopls' analyzer documentation , which is generated from exactly the same upstream information. (We have neither the desire nor the resources to maintain parallel documentation for each analyzer specific to its use in the context of gopls; ideally the context should not really matter.)

Comment From: frankli0324

+1 on this, and I want to mention that it's SO ** FRUSTRATING to pin down the source of the issue. the extension itself runs staticcheck, and emits a message that says there's no issue with the code, but disabling the extension makes the issue go away. It confuses me, until I find this change in gopls. until then, there's absolutely NO LOGS emitted in extension output indicating that gopls also lints the code, especially when it runs side by side with the ts part of the extension. also want to add a link to staticcheck's documented behavior: https://staticcheck.dev/docs/configuration/#ignoring-problems

Comment From: adonovan

Point taken; I have updated the release notes at https://github.com/golang/tools/releases/tag/gopls%2Fv0.19.0 to flag the potential confusion for others in the same situation.

Comment From: findleyr

CC @dominikh

I actually believe that this is either a gopls bug, or a staticcheck bug: If staticcheck analyzers honor this directive, so should gopls, and if staticcheck exposes the analyzer as an API, it should probably implement these suppression mechanisms in the analyzer rather than the driver.

IMO either staticcheck has a bug, or we're using it wrong, since the goal is for us to offer gopls as a consolidated analyzer host.

Comment From: dominikh

See https://github.com/golang/go/issues/50764#issuecomment-2667405624 for previous discussion on this.

Comment From: adonovan

[@dominikh] See https://github.com/golang/go/issues/50764#issuecomment-2667405624 for previous discussion on this.

I agree with @findleyr that ideally the comment extraction could be expressed as a helper analyzer that staticcheck analyzers would require. This would solve both the technical problem of having to duplicate the comment extraction in gopls, and the policy problem that such annotations are not a standard feature of the Go analysis ecosystem (though it is clear that we need something like it).

I'll see if I can come up with a sketch that you can use. (Or you can do it yourself if you prefer.)

Comment From: dominikh

could be expressed as a helper analyzer that staticcheck analyzers would require

Personally I'm leaning towards the wrapper approach, that wraps an analysis and adds processing of ignore directives to it. For staticcheck (i.e. my CLI), we'll still want the runner to take care of ignore directives to emit warnings for unmatched ignore directives, without having to add an epilogue to every analyzer.

I'll see if I can come up with a sketch that you can use. (Or you can do it yourself if you prefer.)

I'm pretty clear on how to do it. I'll try to fit it in time-wise next week.