1
0
mirror of https://github.com/golang/go synced 2024-09-30 14:28:33 -06:00

internal/lsp: watch all files in the module and replace target

Previously, our file watching only considered the root directory of the
view, which may not include the entire module or its replaced
dependencies. Now we expand our watching to include the whole module.

As part of testing this, I noticed that VS Code's file watcher actually
only sends updates for files in the workspace, even if we request
notifications for all files in the module. I filed an issue to ask about
this: https://github.com/microsoft/vscode-languageserver-node/issues/641.

Change-Id: I9499d31aff273f69e9c117511e7985ff58b7fdc4
Reviewed-on: https://go-review.googlesource.com/c/tools/+/239198
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
Rebecca Stambler 2020-06-20 16:11:01 -04:00
parent 7480c7b454
commit fadf93ffb2
3 changed files with 59 additions and 19 deletions

View File

@ -519,6 +519,36 @@ func basename(filename string) string {
return strings.ToLower(filepath.Base(filename))
}
func (v *View) WorkspaceDirectories(ctx context.Context) ([]string, error) {
// If the view does not have a go.mod file, only the root directory
// is known. In GOPATH mode, we should really watch the entire GOPATH,
// but that's probably too expensive.
// TODO(rstambler): Figure out a better approach in the future.
if v.modURI == "" {
return []string{v.folder.Filename()}, nil
}
// Anything inside of the module root is known.
dirs := []string{filepath.Dir(v.modURI.Filename())}
// Keep track of any directories mentioned in replace targets.
fh, err := v.session.GetFile(ctx, v.modURI)
if err != nil {
return nil, err
}
pmh, err := v.Snapshot().ParseModHandle(ctx, fh)
if err != nil {
return nil, err
}
parsed, _, _, err := pmh.Parse(ctx)
if err != nil {
return nil, err
}
for _, replace := range parsed.Replace {
dirs = append(dirs, replace.New.Path)
}
return dirs, nil
}
func (v *View) relevantChange(c source.FileModification) bool {
// If the file is known to the view, the change is relevant.
known := v.knownFile(c.URI)

View File

@ -152,25 +152,6 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa
)
}
if options.DynamicWatchedFilesSupported {
registrations = append(registrations, protocol.Registration{
ID: "workspace/didChangeWatchedFiles",
Method: "workspace/didChangeWatchedFiles",
RegisterOptions: protocol.DidChangeWatchedFilesRegistrationOptions{
Watchers: []protocol.FileSystemWatcher{{
GlobPattern: "**/*.go",
Kind: float64(protocol.WatchChange + protocol.WatchDelete + protocol.WatchCreate),
}},
},
})
}
if len(registrations) > 0 {
s.client.RegisterCapability(ctx, &protocol.RegistrationParams{
Registrations: registrations,
})
}
// TODO: this event logging may be unnecessary. The version info is included in the initialize response.
buf := &bytes.Buffer{}
debug.PrintVersionInfo(ctx, buf, true, debug.PlainText)
@ -179,6 +160,31 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa
s.addFolders(ctx, s.pendingFolders)
s.pendingFolders = nil
if options.DynamicWatchedFilesSupported {
for _, view := range s.session.Views() {
dirs, err := view.WorkspaceDirectories(ctx)
if err != nil {
return err
}
for _, dir := range dirs {
registrations = append(registrations, protocol.Registration{
ID: "workspace/didChangeWatchedFiles",
Method: "workspace/didChangeWatchedFiles",
RegisterOptions: protocol.DidChangeWatchedFilesRegistrationOptions{
Watchers: []protocol.FileSystemWatcher{{
GlobPattern: fmt.Sprintf("%s/**.go", dir),
Kind: float64(protocol.WatchChange + protocol.WatchDelete + protocol.WatchCreate),
}},
},
})
}
}
if len(registrations) > 0 {
s.client.RegisterCapability(ctx, &protocol.RegistrationParams{
Registrations: registrations,
})
}
}
return nil
}

View File

@ -177,6 +177,10 @@ type View interface {
// IgnoredFile reports if a file would be ignored by a `go list` of the whole
// workspace.
IgnoredFile(uri span.URI) bool
// WorkspaceDirectories returns any directory known by the view. For views
// within a module, this is the module root and any replace targets.
WorkspaceDirectories(ctx context.Context) ([]string, error)
}
type BuiltinPackage interface {