Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/tools/gopls: workspace/didChangeWatchedFiles RegisterCapability globs are too broad #41504

Open
myitcv opened this issue Sep 20, 2020 · 3 comments

Comments

@myitcv
Copy link
Member

@myitcv myitcv commented Sep 20, 2020

What version of Go are you using (go version)?

$ go version
go version devel +06f7e655d1 Fri Sep 18 07:56:50 2020 +0000 linux/amd64
$ go list -m golang.org/x/tools
golang.org/x/tools v0.0.0-20200918232735-d647fc253266
$ go list -m golang.org/x/tools/gopls
golang.org/x/tools/gopls v0.0.0-20200918232735-d647fc253266

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/myitcv/.cache/go-build"
GOENV="/home/myitcv/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/myitcv/gostuff/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/myitcv/gostuff"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/myitcv/gos"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/myitcv/gos/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/myitcv/gostuff/src/github.com/myitcv/govim/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build962924290=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Given the following setup:

-- blah/blah.go --
package blah

const Message = "hello"
-- blah/go.mod --
module blah.com

go 1.16
-- go.mod --
module mod.com

go 1.16

require blah.com v0.0.0-00010101000000-000000000000

replace blah.com => ./blah
-- go.sum --
-- main.go --
package main

import (
	"fmt"

	"blah.com"
)

func main() {
	fmt.Println(blah.Message)
}

I loaded govim.

What did you expect to see?

Precise workspace/didChangeWatchedFiles globls in any RegisterCapability call.

What did you see instead?

RegisterCapability: &protocol.RegistrationParams{
    Registrations: {
        {
            ID:              "workspace/didChangeWatchedFiles-0",
            Method:          "workspace/didChangeWatchedFiles",
            RegisterOptions: map[string]interface {}{
                "watchers": []interface {}{
                    map[string]interface {}{
                        "globPattern": "**/*.{go,mod,sum}",
                        "kind":        float64(7),
                    },
                    map[string]interface {}{
                        "globPattern": "/home/myitcv/gostuff/src/github.com/myitcv/playground/blah/**/*.{go,mod,sum}",
                        "kind":        float64(7),
                    },
                    map[string]interface {}{
                        "globPattern": "/home/myitcv/gostuff/src/github.com/myitcv/playground/**/*.{go,mod,sum}",
                        "kind":        float64(7),
                    },
                },
            },
        },
    },
}

Side note: the working directory of govim (and therefore gopls) in this case was /home/myitcv/gostuff/src/github.com/myitcv/playground, so the first and third watchers appear to be duplicates.

If I understand the glob spec, **/*.{go,mod,sum} means "all .go, .mod and .sum files in all subdirectories".

The recursive descent into subdirectories does not stop at directories whose names start with . or _, or those that contain go.mod files. This can, and does, make this watch very expensive if, for example, you have a directory like node_modules that contains lots of files that are and always will be totally irrelevant to gopls (the advice here is to put a go.mod in that directory).

I suspect this situation is somewhat a function of the LSP spec, but can these globs be made more specific in some way?

An approach to .gitignore patterns would work for example.


cc @stamblerre

FYI @leitzler

@gopherbot gopherbot added the Tools label Sep 20, 2020
@gopherbot gopherbot added this to the Unreleased milestone Sep 20, 2020
@stamblerre
Copy link
Contributor

@stamblerre stamblerre commented Sep 21, 2020

I think we can ignore any of the directories that match these cases: https://github.com/golang/tools/blob/ccabf82fa1aef57afc4686de4b7881718f7b7d27/internal/lsp/cache/view.go#L662.

Ignoring something like node_modules is more difficult, and likely not doable if you open a module that contains a node_modules directory.

@stamblerre stamblerre modified the milestones: Unreleased, gopls/v1.0.0 Sep 21, 2020
@myitcv
Copy link
Member Author

@myitcv myitcv commented Sep 22, 2020

I think we can ignore any of the directories that match these cases

When you say "we", do you mean gopls? If so, that's too late because the client will already have setup watchers on those directories, and that's the cost I'm raising here.

Ignoring something like node_modules is more difficult, and likely not doable if you open a module that contains a node_modules directory.

As I explained in the original description, the advice with node_modules directories is to place a go.mod file in that directory (rather than special case ignore it), hence pruning it from the watch space.

@stamblerre
Copy link
Contributor

@stamblerre stamblerre commented Sep 22, 2020

I think we can ignore any of the directories that match these cases

When you say "we", do you mean gopls? If so, that's too late because the client will already have setup watchers on those directories, and that's the cost I'm raising here.

Yep, sorry for not being clearer - I linked that function to show the different cases that we know the Go command ignores and that we could also ignore in the GlobPattern.

Ignoring something like node_modules is more difficult, and likely not doable if you open a module that contains a node_modules directory.

As I explained in the original description, the advice with node_modules directories is to place a go.mod file in that directory (rather than special case ignore it), hence pruning it from the watch space.

Yep--I thought you might be asking for an alternative method of ignoring it.

@stamblerre stamblerre added this to Bugs in gopls/v1.0.0 Sep 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.