diff --git a/internal/lsp/regtest/diagnostics_test.go b/internal/lsp/regtest/diagnostics_test.go index aff0c9e25e..bf3bfc750d 100644 --- a/internal/lsp/regtest/diagnostics_test.go +++ b/internal/lsp/regtest/diagnostics_test.go @@ -5,9 +5,12 @@ package regtest import ( + "context" "fmt" + "log" "os" "testing" + "time" "golang.org/x/tools/internal/lsp" "golang.org/x/tools/internal/lsp/fake" @@ -176,6 +179,52 @@ const a = http.MethodGet }) } +// Tests golang/go#38878: good a.go, bad a_test.go, remove a_test.go but its errors remain +// If the file is open in the editor, this is working as intended +// If the file is not open in the editor, the errors go away +const test38878 = ` +-- go.mod -- +module foo + +-- a.go -- +package x + +func f() {} + +-- a_test.go -- +package x + +import "testing" + +func TestA(t *testing.T) { + f(3) +} +` + +func TestRmTest38878Close(t *testing.T) { + runner.Run(t, test38878, func(t *testing.T, env *Env) { + env.OpenFile("a_test.go") + env.Await(DiagnosticAt("a_test.go", 5, 3)) + env.CloseBuffer("a_test.go") + env.RemoveFileFromWorkspace("a_test.go") + // diagnostics go away + env.Await(EmptyDiagnostics("a_test.go")) + }) +} +func TestRmTest38878(t *testing.T) { + log.SetFlags(log.Lshortfile) + runner.Run(t, test38878, func(t *testing.T, env *Env) { + env.OpenFile("a_test.go") + env.Await(DiagnosticAt("a_test.go", 5, 3)) + env.Sandbox.Workdir.RemoveFile(context.Background(), "a_test.go") + // diagnostics remain after giving gopls a chance to do something + // (there is not yet a better way to decide gopls isn't going + // to do anything) + time.Sleep(time.Second) + env.Await(DiagnosticAt("a_test.go", 5, 3)) + }) +} + // TestNoMod confirms that gopls continues to work when a user adds a go.mod // file to their workspace. func TestNoMod(t *testing.T) { diff --git a/internal/lsp/text_synchronization.go b/internal/lsp/text_synchronization.go index eaee00d423..f52684da83 100644 --- a/internal/lsp/text_synchronization.go +++ b/internal/lsp/text_synchronization.go @@ -134,7 +134,7 @@ func (s *Server) didChangeWatchedFiles(ctx context.Context, params *protocol.Did if err != nil { return err } - // Clear the diagnostics for any deleted files. + // Clear the diagnostics for any deleted files that are not open in the editor. for uri := range deletions { if snapshot := snapshots[uri]; snapshot == nil || snapshot.IsOpen(uri) { continue