From 5a667787ee0915aca58d5ddf36fc4ec78fb61fe9 Mon Sep 17 00:00:00 2001 From: Rebecca Stambler Date: Wed, 5 May 2021 20:47:34 -0400 Subject: [PATCH] internal/lsp: do not reinitialize the workspace for didOpen events Previously, we would treat file opens/closes as workspace reinitialization events. Change-Id: Ib8ca490fe7a44768a757311b058093d0bf3888c6 Reviewed-on: https://go-review.googlesource.com/c/tools/+/317450 Trust: Rebecca Stambler Run-TryBot: Rebecca Stambler gopls-CI: kokoro TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../regtest/diagnostics/diagnostics_test.go | 24 +++++++++++++++++++ internal/lsp/cache/session.go | 21 +++++++++++----- internal/lsp/cache/workspace.go | 5 ++-- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/gopls/internal/regtest/diagnostics/diagnostics_test.go b/gopls/internal/regtest/diagnostics/diagnostics_test.go index ecdd8daebc..019ba657d5 100644 --- a/gopls/internal/regtest/diagnostics/diagnostics_test.go +++ b/gopls/internal/regtest/diagnostics/diagnostics_test.go @@ -1912,3 +1912,27 @@ func foo() int { ) }) } + +// This test confirms that the view does not reinitialize when a go.mod file is +// opened. +func TestNoReinitialize(t *testing.T) { + const files = ` +-- go.mod -- +module mod.com + +go 1.12 +-- main.go -- +package main + +func main() {} +` + Run(t, files, func(t *testing.T, env *Env) { + env.OpenFile("go.mod") + env.Await( + OnceMet( + env.DoneWithOpen(), + LogMatching(protocol.Info, `.*query=\[builtin mod.com/...\].*`, 1), + ), + ) + }) +} diff --git a/internal/lsp/cache/session.go b/internal/lsp/cache/session.go index ba155c7b4e..657a0ee7b4 100644 --- a/internal/lsp/cache/session.go +++ b/internal/lsp/cache/session.go @@ -408,6 +408,11 @@ type fileChange struct { content []byte exists bool fileHandle source.VersionedFileHandle + + // isUnchanged indicates whether the file action is one that does not + // change the actual contents of the file. Opens and closes should not + // be treated like other changes, since the file content doesn't change. + isUnchanged bool } func (s *Session) DidModifyFiles(ctx context.Context, changes []source.FileModification) (map[source.Snapshot][]span.URI, []func(), error) { @@ -448,6 +453,8 @@ func (s *Session) DidModifyFiles(ctx context.Context, changes []source.FileModif } affectedViews[c.URI] = changedViews + isUnchanged := c.Action == source.Open || c.Action == source.Close + // Apply the changes to all affected views. for _, view := range changedViews { // Make sure that the file is added to the view. @@ -457,9 +464,10 @@ func (s *Session) DidModifyFiles(ctx context.Context, changes []source.FileModif } if fh, ok := overlays[c.URI]; ok { views[view][c.URI] = &fileChange{ - content: fh.text, - exists: true, - fileHandle: fh, + content: fh.text, + exists: true, + fileHandle: fh, + isUnchanged: isUnchanged, } } else { fsFile, err := s.cache.getFile(ctx, c.URI) @@ -469,9 +477,10 @@ func (s *Session) DidModifyFiles(ctx context.Context, changes []source.FileModif content, err := fsFile.Read() fh := &closedFile{fsFile} views[view][c.URI] = &fileChange{ - content: content, - exists: err == nil, - fileHandle: fh, + content: content, + exists: err == nil, + fileHandle: fh, + isUnchanged: isUnchanged, } } } diff --git a/internal/lsp/cache/workspace.go b/internal/lsp/cache/workspace.go index 6b62d2951c..d4b5303c96 100644 --- a/internal/lsp/cache/workspace.go +++ b/internal/lsp/cache/workspace.go @@ -277,7 +277,8 @@ func (w *workspace) invalidate(ctx context.Context, changes map[span.URI]*fileCh // If gopls.mod has changed we need to either re-read it if it exists or // walk the filesystem if it has been deleted. gmURI := goplsModURI(w.root) - if change, ok := changes[gmURI]; ok { + // File opens/closes are just no-ops. + if change, ok := changes[gmURI]; ok && !change.isUnchanged { if change.exists { // Only invalidate if the gopls.mod actually parses. // Otherwise, stick with the current gopls.mod. @@ -326,7 +327,7 @@ func (w *workspace) invalidate(ctx context.Context, changes map[span.URI]*fileCh // here. if result.moduleSource != goplsModWorkspace { for uri, change := range changes { - if !isGoMod(uri) || !source.InDir(result.root.Filename(), uri.Filename()) { + if change.isUnchanged || !isGoMod(uri) || !source.InDir(result.root.Filename(), uri.Filename()) { continue } changed = true