diff --git a/gopls/internal/regtest/diagnostics/diagnostics_test.go b/gopls/internal/regtest/diagnostics/diagnostics_test.go index b9802e2457..c18dfbf91a 100644 --- a/gopls/internal/regtest/diagnostics/diagnostics_test.go +++ b/gopls/internal/regtest/diagnostics/diagnostics_test.go @@ -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( diff --git a/internal/lsp/cache/workspace.go b/internal/lsp/cache/workspace.go index 16f97dbe63..7a75b21567 100644 --- a/internal/lsp/cache/workspace.go +++ b/internal/lsp/cache/workspace.go @@ -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) } }