internal/lsp: invalidate package on go.mod change with go.work

If a go.mod file is updated, the packages
in that module may have updated type check
errors since the go version can affect errors.

Fixes golang/go#51732

Change-Id: I3a8cd8b9ab267336ccc5c841a14c5ec5f6c986e5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/393534
Trust: Suzy Mueller <suzmue@golang.org>
Run-TryBot: Suzy Mueller <suzmue@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Suzy Mueller 2022-03-16 20:47:11 -06:00
parent c7b0e9aca6
commit 779dfa4fb2
2 changed files with 55 additions and 21 deletions

View File

@ -2199,7 +2199,41 @@ package main
func F[T any](_ T) {
}
`
Run(t, files, func(t *testing.T, env *Env) { // Create a new workspace-level directory and empty file.
Run(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.
var d protocol.PublishDiagnosticsParams
env.Await(
OnceMet(
env.DiagnosticAtRegexpWithMessage("main.go", `T any`, "type parameters require"),
ReadDiagnostics("main.go", &d),
),
)
env.ApplyQuickFixes("main.go", d.Diagnostics)
env.Await(
EmptyDiagnostics("main.go"),
)
})
}
func TestEditGoDirectiveWorkspace(t *testing.T) {
testenv.NeedsGo1Point(t, 18)
const files = `
-- go.mod --
module mod.com
go 1.16
-- go.work --
go 1.18
use .
-- main.go --
package main
func F[T any](_ T) {
}
`
Run(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.
var d protocol.PublishDiagnosticsParams
env.Await(
OnceMet(

View File

@ -301,27 +301,27 @@ func (w *workspace) invalidate(ctx context.Context, changes map[span.URI]*fileCh
// we need to either re-read it if it exists or walk the filesystem if it
// has been deleted. go.work should override the gopls.mod if both exist.
changed, reload = handleWorkspaceFileChanges(ctx, result, changes, fs)
// Next, handle go.mod changes that could affect our workspace. If we're
// reading our tracked modules from the gopls.mod, there's nothing to do
// here.
if result.moduleSource != goplsModWorkspace && result.moduleSource != goWorkWorkspace {
for uri, change := range changes {
// Otherwise, we only care about go.mod files in the workspace directory.
if change.isUnchanged || !isGoMod(uri) || !source.InDir(result.root.Filename(), uri.Filename()) {
continue
}
changed = true
active := result.moduleSource != legacyWorkspace || source.CompareURI(modURI(w.root), uri) == 0
reload = reload || (active && change.fileHandle.Saved())
if change.exists {
result.knownModFiles[uri] = struct{}{}
if active {
result.activeModFiles[uri] = struct{}{}
}
} else {
delete(result.knownModFiles, uri)
delete(result.activeModFiles, uri)
// Next, handle go.mod changes that could affect our workspace.
for uri, change := range changes {
// Otherwise, we only care about go.mod files in the workspace directory.
if change.isUnchanged || !isGoMod(uri) || !source.InDir(result.root.Filename(), uri.Filename()) {
continue
}
changed = true
active := result.moduleSource != legacyWorkspace || source.CompareURI(modURI(w.root), uri) == 0
reload = reload || (active && change.fileHandle.Saved())
// Don't mess with the list of mod files if using go.work or gopls.mod.
if result.moduleSource == goplsModWorkspace || result.moduleSource == goWorkWorkspace {
continue
}
if change.exists {
result.knownModFiles[uri] = struct{}{}
if active {
result.activeModFiles[uri] = struct{}{}
}
} else {
delete(result.knownModFiles, uri)
delete(result.activeModFiles, uri)
}
}