Skip to content

Commit ac612af

Browse files
committed
internal/lsp: fix the logic to avoid duplicate file watching
The logic that checked if a file was already being watched by the default glob pattern was incorrect. Fix it, and use the newly added InDir function. Change-Id: Ia7e3851ab5b9fa1fa7590cae3b370676201a9141 Reviewed-on: https://go-review.googlesource.com/c/tools/+/267119 Trust: Rebecca Stambler <rstambler@golang.org> Run-TryBot: Rebecca Stambler <rstambler@golang.org> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com>
1 parent 6d1a7fa commit ac612af

File tree

5 files changed

+87
-80
lines changed

5 files changed

+87
-80
lines changed

internal/lsp/cache/snapshot.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ func (s *snapshot) CachedImportPaths(ctx context.Context) (map[string]source.Pac
694694
func (s *snapshot) GoModForFile(ctx context.Context, uri span.URI) span.URI {
695695
var match span.URI
696696
for modURI := range s.workspace.activeModFiles() {
697-
if !inDir(dirURI(modURI).Filename(), uri.Filename()) {
697+
if !source.InDir(dirURI(modURI).Filename(), uri.Filename()) {
698698
continue
699699
}
700700
if len(modURI) > len(match) {
@@ -1377,7 +1377,7 @@ func (s *snapshot) shouldInvalidateMetadata(ctx context.Context, newSnapshot *sn
13771377
}
13781378
// If a go.mod in the workspace has been changed, invalidate metadata.
13791379
if kind := originalFH.Kind(); kind == source.Mod {
1380-
return inDir(filepath.Dir(s.view.rootURI.Filename()), filepath.Dir(originalFH.URI().Filename()))
1380+
return source.InDir(filepath.Dir(s.view.rootURI.Filename()), filepath.Dir(originalFH.URI().Filename()))
13811381
}
13821382
// Get the original and current parsed files in order to check package name
13831383
// and imports. Use the new snapshot to parse to avoid modifying the

internal/lsp/cache/view.go

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -698,87 +698,13 @@ func validBuildConfiguration(folder span.URI, ws *workspaceInformation, modFiles
698698
// The user may have a multiple directories in their GOPATH.
699699
// Check if the workspace is within any of them.
700700
for _, gp := range filepath.SplitList(ws.gopath) {
701-
if inDir(filepath.Join(gp, "src"), folder.Filename()) {
701+
if source.InDir(filepath.Join(gp, "src"), folder.Filename()) {
702702
return true
703703
}
704704
}
705705
return false
706706
}
707707

708-
// Copied and slightly adjusted from go/src/cmd/go/internal/search/search.go.
709-
//
710-
// inDir checks whether path is in the file tree rooted at dir.
711-
// If so, InDir returns an equivalent path relative to dir.
712-
// If not, InDir returns an empty string.
713-
// InDir makes some effort to succeed even in the presence of symbolic links.
714-
func inDir(dir, path string) bool {
715-
if rel := inDirLex(path, dir); rel != "" {
716-
return true
717-
}
718-
xpath, err := filepath.EvalSymlinks(path)
719-
if err != nil || xpath == path {
720-
xpath = ""
721-
} else {
722-
if rel := inDirLex(xpath, dir); rel != "" {
723-
return true
724-
}
725-
}
726-
727-
xdir, err := filepath.EvalSymlinks(dir)
728-
if err == nil && xdir != dir {
729-
if rel := inDirLex(path, xdir); rel != "" {
730-
return true
731-
}
732-
if xpath != "" {
733-
if rel := inDirLex(xpath, xdir); rel != "" {
734-
return true
735-
}
736-
}
737-
}
738-
return false
739-
}
740-
741-
// Copied from go/src/cmd/go/internal/search/search.go.
742-
//
743-
// inDirLex is like inDir but only checks the lexical form of the file names.
744-
// It does not consider symbolic links.
745-
// TODO(rsc): This is a copy of str.HasFilePathPrefix, modified to
746-
// return the suffix. Most uses of str.HasFilePathPrefix should probably
747-
// be calling InDir instead.
748-
func inDirLex(path, dir string) string {
749-
pv := strings.ToUpper(filepath.VolumeName(path))
750-
dv := strings.ToUpper(filepath.VolumeName(dir))
751-
path = path[len(pv):]
752-
dir = dir[len(dv):]
753-
switch {
754-
default:
755-
return ""
756-
case pv != dv:
757-
return ""
758-
case len(path) == len(dir):
759-
if path == dir {
760-
return "."
761-
}
762-
return ""
763-
case dir == "":
764-
return path
765-
case len(path) > len(dir):
766-
if dir[len(dir)-1] == filepath.Separator {
767-
if path[:len(dir)] == dir {
768-
return path[len(dir):]
769-
}
770-
return ""
771-
}
772-
if path[len(dir)] == filepath.Separator && path[:len(dir)] == dir {
773-
if len(path) == len(dir)+1 {
774-
return "."
775-
}
776-
return path[len(dir)+1:]
777-
}
778-
return ""
779-
}
780-
}
781-
782708
// getGoEnv gets the view's various GO* values.
783709
func (s *Session) getGoEnv(ctx context.Context, folder string, configEnv []string) (environmentVariables, map[string]string, error) {
784710
envVars := environmentVariables{}

internal/lsp/cache/workspace.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ func (wm *workspace) invalidate(ctx context.Context, changes map[span.URI]*fileC
258258
// Legacy mode only considers a module a workspace root.
259259
continue
260260
}
261-
if !inDir(wm.root.Filename(), uri.Filename()) {
261+
if !source.InDir(wm.root.Filename(), uri.Filename()) {
262262
// Otherwise, the module must be contained within the workspace root.
263263
continue
264264
}

internal/lsp/general.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,13 +348,20 @@ func (s *Server) registerWatchedDirectoriesLocked(ctx context.Context, dirs map[
348348
}}
349349
for dir := range dirs {
350350
filename := dir.Filename()
351+
351352
// If the directory is within a workspace folder, we're already
352353
// watching it via the relative path above.
354+
var matched bool
353355
for _, view := range s.session.Views() {
354-
if isSubdirectory(view.Folder().Filename(), filename) {
355-
continue
356+
if source.InDir(view.Folder().Filename(), filename) {
357+
matched = true
358+
break
356359
}
357360
}
361+
if matched {
362+
continue
363+
}
364+
358365
// If microsoft/vscode#100870 is resolved before
359366
// microsoft/vscode#104387, we will need a work-around for Windows
360367
// drive letter casing.

internal/lsp/source/util.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,3 +441,77 @@ func isDirective(c string) bool {
441441
}
442442
return true
443443
}
444+
445+
// InDir checks whether path is in the file tree rooted at dir.
446+
// If so, InDir returns an equivalent path relative to dir.
447+
// If not, InDir returns an empty string.
448+
// InDir makes some effort to succeed even in the presence of symbolic links.
449+
//
450+
// Copied and slightly adjusted from go/src/cmd/go/internal/search/search.go.
451+
func InDir(dir, path string) bool {
452+
if rel := inDirLex(path, dir); rel != "" {
453+
return true
454+
}
455+
xpath, err := filepath.EvalSymlinks(path)
456+
if err != nil || xpath == path {
457+
xpath = ""
458+
} else {
459+
if rel := inDirLex(xpath, dir); rel != "" {
460+
return true
461+
}
462+
}
463+
464+
xdir, err := filepath.EvalSymlinks(dir)
465+
if err == nil && xdir != dir {
466+
if rel := inDirLex(path, xdir); rel != "" {
467+
return true
468+
}
469+
if xpath != "" {
470+
if rel := inDirLex(xpath, xdir); rel != "" {
471+
return true
472+
}
473+
}
474+
}
475+
return false
476+
}
477+
478+
// Copied from go/src/cmd/go/internal/search/search.go.
479+
//
480+
// inDirLex is like inDir but only checks the lexical form of the file names.
481+
// It does not consider symbolic links.
482+
// TODO(rsc): This is a copy of str.HasFilePathPrefix, modified to
483+
// return the suffix. Most uses of str.HasFilePathPrefix should probably
484+
// be calling InDir instead.
485+
func inDirLex(path, dir string) string {
486+
pv := strings.ToUpper(filepath.VolumeName(path))
487+
dv := strings.ToUpper(filepath.VolumeName(dir))
488+
path = path[len(pv):]
489+
dir = dir[len(dv):]
490+
switch {
491+
default:
492+
return ""
493+
case pv != dv:
494+
return ""
495+
case len(path) == len(dir):
496+
if path == dir {
497+
return "."
498+
}
499+
return ""
500+
case dir == "":
501+
return path
502+
case len(path) > len(dir):
503+
if dir[len(dir)-1] == filepath.Separator {
504+
if path[:len(dir)] == dir {
505+
return path[len(dir):]
506+
}
507+
return ""
508+
}
509+
if path[len(dir)] == filepath.Separator && path[:len(dir)] == dir {
510+
if len(path) == len(dir)+1 {
511+
return "."
512+
}
513+
return path[len(dir)+1:]
514+
}
515+
return ""
516+
}
517+
}

0 commit comments

Comments
 (0)