Skip to content

Commit fadf93f

Browse files
committed
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: microsoft/vscode-languageserver-node#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>
1 parent 7480c7b commit fadf93f

File tree

3 files changed

+59
-19
lines changed

3 files changed

+59
-19
lines changed

internal/lsp/cache/view.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,36 @@ func basename(filename string) string {
519519
return strings.ToLower(filepath.Base(filename))
520520
}
521521

522+
func (v *View) WorkspaceDirectories(ctx context.Context) ([]string, error) {
523+
// If the view does not have a go.mod file, only the root directory
524+
// is known. In GOPATH mode, we should really watch the entire GOPATH,
525+
// but that's probably too expensive.
526+
// TODO(rstambler): Figure out a better approach in the future.
527+
if v.modURI == "" {
528+
return []string{v.folder.Filename()}, nil
529+
}
530+
// Anything inside of the module root is known.
531+
dirs := []string{filepath.Dir(v.modURI.Filename())}
532+
533+
// Keep track of any directories mentioned in replace targets.
534+
fh, err := v.session.GetFile(ctx, v.modURI)
535+
if err != nil {
536+
return nil, err
537+
}
538+
pmh, err := v.Snapshot().ParseModHandle(ctx, fh)
539+
if err != nil {
540+
return nil, err
541+
}
542+
parsed, _, _, err := pmh.Parse(ctx)
543+
if err != nil {
544+
return nil, err
545+
}
546+
for _, replace := range parsed.Replace {
547+
dirs = append(dirs, replace.New.Path)
548+
}
549+
return dirs, nil
550+
}
551+
522552
func (v *View) relevantChange(c source.FileModification) bool {
523553
// If the file is known to the view, the change is relevant.
524554
known := v.knownFile(c.URI)

internal/lsp/general.go

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -152,25 +152,6 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa
152152
)
153153
}
154154

155-
if options.DynamicWatchedFilesSupported {
156-
registrations = append(registrations, protocol.Registration{
157-
ID: "workspace/didChangeWatchedFiles",
158-
Method: "workspace/didChangeWatchedFiles",
159-
RegisterOptions: protocol.DidChangeWatchedFilesRegistrationOptions{
160-
Watchers: []protocol.FileSystemWatcher{{
161-
GlobPattern: "**/*.go",
162-
Kind: float64(protocol.WatchChange + protocol.WatchDelete + protocol.WatchCreate),
163-
}},
164-
},
165-
})
166-
}
167-
168-
if len(registrations) > 0 {
169-
s.client.RegisterCapability(ctx, &protocol.RegistrationParams{
170-
Registrations: registrations,
171-
})
172-
}
173-
174155
// TODO: this event logging may be unnecessary. The version info is included in the initialize response.
175156
buf := &bytes.Buffer{}
176157
debug.PrintVersionInfo(ctx, buf, true, debug.PlainText)
@@ -179,6 +160,31 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa
179160
s.addFolders(ctx, s.pendingFolders)
180161
s.pendingFolders = nil
181162

163+
if options.DynamicWatchedFilesSupported {
164+
for _, view := range s.session.Views() {
165+
dirs, err := view.WorkspaceDirectories(ctx)
166+
if err != nil {
167+
return err
168+
}
169+
for _, dir := range dirs {
170+
registrations = append(registrations, protocol.Registration{
171+
ID: "workspace/didChangeWatchedFiles",
172+
Method: "workspace/didChangeWatchedFiles",
173+
RegisterOptions: protocol.DidChangeWatchedFilesRegistrationOptions{
174+
Watchers: []protocol.FileSystemWatcher{{
175+
GlobPattern: fmt.Sprintf("%s/**.go", dir),
176+
Kind: float64(protocol.WatchChange + protocol.WatchDelete + protocol.WatchCreate),
177+
}},
178+
},
179+
})
180+
}
181+
}
182+
if len(registrations) > 0 {
183+
s.client.RegisterCapability(ctx, &protocol.RegistrationParams{
184+
Registrations: registrations,
185+
})
186+
}
187+
}
182188
return nil
183189
}
184190

internal/lsp/source/view.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ type View interface {
177177
// IgnoredFile reports if a file would be ignored by a `go list` of the whole
178178
// workspace.
179179
IgnoredFile(uri span.URI) bool
180+
181+
// WorkspaceDirectories returns any directory known by the view. For views
182+
// within a module, this is the module root and any replace targets.
183+
WorkspaceDirectories(ctx context.Context) ([]string, error)
180184
}
181185

182186
type BuiltinPackage interface {

0 commit comments

Comments
 (0)