gopls/internal/regtest: simplify OnceMet expressions with an env helper

Simplify env.Await(OnceMet(...)) to env.OnceMet(...). Aside from
avoiding boilerplate, this makes it easier to identify where we're still
using Await.

Updates golang/go#39384

Change-Id: I57a18242ce6b48e371e5ce4876ef01a6774fe15c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/461917
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
diff --git a/gopls/internal/lsp/regtest/env.go b/gopls/internal/lsp/regtest/env.go
index c3f48bf..73e8ef3 100644
--- a/gopls/internal/lsp/regtest/env.go
+++ b/gopls/internal/lsp/regtest/env.go
@@ -302,6 +302,12 @@
 	return finalVerdict, summary.String()
 }
 
+// Await blocks until the given expectations are all simultaneously met.
+//
+// Generally speaking Await should be avoided because it can block indefinitely
+// if gopls ends up in a state where the expectations are never going to be
+// met. Use AfterChange or OnceMet instead, so that the runner knows when to
+// stop waiting.
 func (e *Env) Await(expectations ...Expectation) {
 	e.T.Helper()
 	if err := e.Awaiter.Await(e.Ctx, expectations...); err != nil {
@@ -309,6 +315,12 @@
 	}
 }
 
+// OnceMet blocks until precondition is met or unmeetable; if the precondition
+// is met, it atomically checks that all expectations in mustMeets are met.
+func (e *Env) OnceMet(precondition Expectation, mustMeets ...Expectation) {
+	e.Await(OnceMet(precondition, mustMeets...))
+}
+
 // Await waits for all expectations to simultaneously be met. It should only be
 // called from the main test goroutine.
 func (a *Awaiter) Await(ctx context.Context, expectations ...Expectation) error {
diff --git a/gopls/internal/lsp/regtest/expectation.go b/gopls/internal/lsp/regtest/expectation.go
index 43c9af2..410e778 100644
--- a/gopls/internal/lsp/regtest/expectation.go
+++ b/gopls/internal/lsp/regtest/expectation.go
@@ -291,11 +291,9 @@
 // expectations.
 func (e *Env) AfterChange(expectations ...Expectation) {
 	e.T.Helper()
-	e.Await(
-		OnceMet(
-			e.DoneDiagnosingChanges(),
-			expectations...,
-		),
+	e.OnceMet(
+		e.DoneDiagnosingChanges(),
+		expectations...,
 	)
 }
 
diff --git a/gopls/internal/regtest/codelens/codelens_test.go b/gopls/internal/regtest/codelens/codelens_test.go
index 13ba4e1..56e6cca 100644
--- a/gopls/internal/regtest/codelens/codelens_test.go
+++ b/gopls/internal/regtest/codelens/codelens_test.go
@@ -208,16 +208,14 @@
 				env.OpenFile("b/go.mod")
 				env.ExecuteCodeLensCommand("a/go.mod", command.CheckUpgrades, nil)
 				d := &protocol.PublishDiagnosticsParams{}
-				env.Await(
-					OnceMet(
-						env.DiagnosticAtRegexpWithMessage("a/go.mod", `require`, "can be upgraded"),
-						ReadDiagnostics("a/go.mod", d),
-						// We do not want there to be a diagnostic for b/go.mod,
-						// but there may be some subtlety in timing here, where this
-						// should always succeed, but may not actually test the correct
-						// behavior.
-						NoMatchingDiagnostics(env.AtRegexp("b/go.mod", `require`)),
-					),
+				env.OnceMet(
+					env.DiagnosticAtRegexpWithMessage("a/go.mod", `require`, "can be upgraded"),
+					ReadDiagnostics("a/go.mod", d),
+					// We do not want there to be a diagnostic for b/go.mod,
+					// but there may be some subtlety in timing here, where this
+					// should always succeed, but may not actually test the correct
+					// behavior.
+					NoMatchingDiagnostics(env.AtRegexp("b/go.mod", `require`)),
 				)
 				// Check for upgrades in b/go.mod and then clear them.
 				env.ExecuteCodeLensCommand("b/go.mod", command.CheckUpgrades, nil)
diff --git a/gopls/internal/regtest/codelens/gcdetails_test.go b/gopls/internal/regtest/codelens/gcdetails_test.go
index 5f812f4..1b2c346 100644
--- a/gopls/internal/regtest/codelens/gcdetails_test.go
+++ b/gopls/internal/regtest/codelens/gcdetails_test.go
@@ -45,11 +45,9 @@
 		env.OpenFile("main.go")
 		env.ExecuteCodeLensCommand("main.go", command.GCDetails, nil)
 		d := &protocol.PublishDiagnosticsParams{}
-		env.Await(
-			OnceMet(
-				DiagnosticAt("main.go", 5, 13),
-				ReadDiagnostics("main.go", d),
-			),
+		env.OnceMet(
+			DiagnosticAt("main.go", 5, 13),
+			ReadDiagnostics("main.go", d),
 		)
 		// Confirm that the diagnostics come from the gc details code lens.
 		var found bool
diff --git a/gopls/internal/regtest/diagnostics/builtin_test.go b/gopls/internal/regtest/diagnostics/builtin_test.go
index 8de47bc..5baf1dc 100644
--- a/gopls/internal/regtest/diagnostics/builtin_test.go
+++ b/gopls/internal/regtest/diagnostics/builtin_test.go
@@ -30,9 +30,6 @@
 		if !strings.HasSuffix(name, "builtin.go") {
 			t.Fatalf("jumped to %q, want builtin.go", name)
 		}
-		env.Await(OnceMet(
-			env.DoneWithOpen(),
-			NoDiagnostics("builtin.go"),
-		))
+		env.AfterChange(NoDiagnostics("builtin.go"))
 	})
 }
diff --git a/gopls/internal/regtest/diagnostics/diagnostics_test.go b/gopls/internal/regtest/diagnostics/diagnostics_test.go
index b7ccb5b..62585b9 100644
--- a/gopls/internal/regtest/diagnostics/diagnostics_test.go
+++ b/gopls/internal/regtest/diagnostics/diagnostics_test.go
@@ -48,13 +48,8 @@
 		// diagnostic.
 		env.OpenFile("main.go")
 		env.RegexpReplace("main.go", "Printl(n)", "")
-		env.Await(
-			// Once we have gotten diagnostics for the change above, we should
-			// satisfy the DiagnosticAtRegexp assertion.
-			OnceMet(
-				env.DoneWithChange(),
-				env.DiagnosticAtRegexp("main.go", "Printl"),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("main.go", "Printl"),
 			// Assert that this test has sent no error logs to the client. This is not
 			// strictly necessary for testing this regression, but is included here
 			// as an example of using the NoErrorLogs() expectation. Feel free to
@@ -235,9 +230,7 @@
 		env.OpenFile("a_test.go")
 		env.Await(DiagnosticAt("a_test.go", 5, 3))
 		env.Sandbox.Workdir.RemoveFile(context.Background(), "a_test.go")
-		env.Await(OnceMet(
-			env.DoneWithChangeWatchedFiles(),
-			DiagnosticAt("a_test.go", 5, 3)))
+		env.AfterChange(DiagnosticAt("a_test.go", 5, 3))
 	})
 }
 
@@ -263,26 +256,20 @@
 
 	t.Run("manual", func(t *testing.T) {
 		Run(t, noMod, func(t *testing.T, env *Env) {
-			env.Await(
-				OnceMet(
-					InitialWorkspaceLoad,
-					env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`),
-				),
+			env.OnceMet(
+				InitialWorkspaceLoad,
+				env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`),
 			)
 			env.CreateBuffer("go.mod", `module mod.com
 
 	go 1.12
 `)
 			env.SaveBuffer("go.mod")
+			var d protocol.PublishDiagnosticsParams
 			env.AfterChange(
 				NoDiagnostics("main.go"),
-			)
-			var d protocol.PublishDiagnosticsParams
-			env.Await(
-				OnceMet(
-					env.DiagnosticAtRegexp("bob/bob.go", "x"),
-					ReadDiagnostics("bob/bob.go", &d),
-				),
+				env.DiagnosticAtRegexp("bob/bob.go", "x"),
+				ReadDiagnostics("bob/bob.go", &d),
 			)
 			if len(d.Diagnostics) != 1 {
 				t.Fatalf("expected 1 diagnostic, got %v", len(d.Diagnostics))
@@ -527,11 +514,9 @@
 	Run(t, generated, func(t *testing.T, env *Env) {
 		env.OpenFile("main.go")
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				DiagnosticAt("main.go", 5, 8),
-				ReadDiagnostics("main.go", &d),
-			),
+		env.AfterChange(
+			DiagnosticAt("main.go", 5, 8),
+			ReadDiagnostics("main.go", &d),
 		)
 		if fixes := env.GetQuickFixes("main.go", d.Diagnostics); len(fixes) != 0 {
 			t.Errorf("got quick fixes %v, wanted none", fixes)
@@ -608,7 +593,7 @@
 		EnvVars{"GO111MODULE": "off"},
 	).Run(t, collision, func(t *testing.T, env *Env) {
 		env.OpenFile("x/x.go")
-		env.Await(
+		env.AfterChange(
 			env.DiagnosticAtRegexpWithMessage("x/x.go", `^`, "found packages main (main.go) and x (x.go)"),
 			env.DiagnosticAtRegexpWithMessage("x/main.go", `^`, "found packages main (main.go) and x (x.go)"),
 		)
@@ -616,9 +601,9 @@
 		// We don't recover cleanly from the errors without good overlay support.
 		if testenv.Go1Point() >= 16 {
 			env.RegexpReplace("x/x.go", `package x`, `package main`)
-			env.Await(OnceMet(
-				env.DoneWithChange(),
-				env.DiagnosticAtRegexp("x/main.go", `fmt`)))
+			env.AfterChange(
+				env.DiagnosticAtRegexp("x/main.go", `fmt`),
+			)
 		}
 	})
 }
@@ -658,11 +643,9 @@
 		env.OpenFile("go.mod")
 		env.OpenFile("main.go")
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`),
-				ReadDiagnostics("main.go", &d),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`),
+			ReadDiagnostics("main.go", &d),
 		)
 		env.ApplyQuickFixes("main.go", d.Diagnostics)
 		env.SaveBuffer("go.mod")
@@ -672,7 +655,7 @@
 		// Comment out the line that depends on conf and expect a
 		// diagnostic and a fix to remove the import.
 		env.RegexpReplace("main.go", "_ = conf.ErrHelpWanted", "//_ = conf.ErrHelpWanted")
-		env.Await(
+		env.AfterChange(
 			env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`),
 		)
 		env.SaveBuffer("main.go")
@@ -718,11 +701,9 @@
 `)
 		env.SaveBuffer("main.go")
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexpWithMessage("main.go", `"github.com/ardanlabs/conf"`, "no required module"),
-				ReadDiagnostics("main.go", &d),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexpWithMessage("main.go", `"github.com/ardanlabs/conf"`, "no required module"),
+			ReadDiagnostics("main.go", &d),
 		)
 		env.ApplyQuickFixes("main.go", d.Diagnostics)
 		env.AfterChange(
@@ -872,12 +853,9 @@
 	Run(t, mod, func(t *testing.T, env *Env) {
 		env.OpenFile("foo/bar_test.go")
 		env.RegexpReplace("foo/bar_test.go", "package foo_", "package foo_test")
-		env.Await(
-			OnceMet(
-				env.DoneWithChange(),
-				NoDiagnostics("foo/bar_test.go"),
-				NoDiagnostics("foo/foo.go"),
-			),
+		env.AfterChange(
+			NoDiagnostics("foo/bar_test.go"),
+			NoDiagnostics("foo/foo.go"),
 		)
 	})
 }
@@ -1076,12 +1054,7 @@
 }`)
 		env.OpenFile("foo/foo_test.go")
 		env.RegexpReplace("foo/foo_test.go", `package main`, `package foo`)
-		env.Await(
-			OnceMet(
-				env.DoneWithChange(),
-				NoDiagnostics("foo/foo.go"),
-			),
-		)
+		env.AfterChange(NoDiagnostics("foo/foo.go"))
 	})
 }
 
@@ -1102,12 +1075,7 @@
 			env.DoneWithOpen(),
 		)
 		env.CloseBuffer("foo.go")
-		env.Await(
-			OnceMet(
-				env.DoneWithClose(),
-				NoLogMatching(protocol.Info, "packages=0"),
-			),
-		)
+		env.AfterChange(NoLogMatching(protocol.Info, "packages=0"))
 	})
 }
 
@@ -1346,11 +1314,9 @@
 		Settings{"allExperiments": true},
 	).Run(t, mod, func(t *testing.T, env *Env) {
 		// Confirm that the setting doesn't cause any warnings.
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				NoShownMessage(""), // empty substring to match any message
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			NoShownMessage(""), // empty substring to match any message
 		)
 	})
 }
@@ -1401,11 +1367,9 @@
 }
 `
 	Run(t, mod, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				NoMatchingDiagnostics(WithMessageContaining("illegal character U+0023 '#'")),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			NoMatchingDiagnostics(WithMessageContaining("illegal character U+0023 '#'")),
 		)
 	})
 }
@@ -1527,11 +1491,9 @@
 }
 `
 	Run(t, mod, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				FileWatchMatching("bob"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			FileWatchMatching("bob"),
 		)
 		env.RemoveWorkspaceFile("bob")
 		env.AfterChange(
@@ -1610,17 +1572,14 @@
 	Run(t, mod, func(t *testing.T, env *Env) {
 		env.OpenFile("a/a.go")
 		env.OpenFile("b/b.go")
-		env.Await(
-			OnceMet(
-				env.DoneWithOpen(),
-				// The Go command sometimes tells us about only one of the import cycle
-				// errors below. For robustness of this test, succeed if we get either.
-				//
-				// TODO(golang/go#52904): we should get *both* of these errors.
-				AnyOf(
-					env.DiagnosticAtRegexpWithMessage("a/a.go", `"mod.test/b"`, "import cycle"),
-					env.DiagnosticAtRegexpWithMessage("b/b.go", `"mod.test/a"`, "import cycle"),
-				),
+		env.AfterChange(
+			// The Go command sometimes tells us about only one of the import cycle
+			// errors below. For robustness of this test, succeed if we get either.
+			//
+			// TODO(golang/go#52904): we should get *both* of these errors.
+			AnyOf(
+				env.DiagnosticAtRegexpWithMessage("a/a.go", `"mod.test/b"`, "import cycle"),
+				env.DiagnosticAtRegexpWithMessage("b/b.go", `"mod.test/a"`, "import cycle"),
 			),
 		)
 		env.RegexpReplace("b/b.go", `const B = a\.B`, "")
@@ -1715,20 +1674,10 @@
 	).Run(t, nested, func(t *testing.T, env *Env) {
 		// Expect a diagnostic in a nested module.
 		env.OpenFile("nested/hello/hello.go")
-		didOpen := env.DoneWithOpen()
-		env.Await(
-			OnceMet(
-				didOpen,
-				env.DiagnosticAtRegexp("nested/hello/hello.go", "helloHelper"),
-			),
-			OnceMet(
-				didOpen,
-				env.DiagnosticAtRegexpWithMessage("nested/hello/hello.go", "package hello", "nested module"),
-			),
-			OnceMet(
-				didOpen,
-				OutstandingWork(lsp.WorkspaceLoadFailure, "nested module"),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("nested/hello/hello.go", "helloHelper"),
+			env.DiagnosticAtRegexpWithMessage("nested/hello/hello.go", "package hello", "nested module"),
+			OutstandingWork(lsp.WorkspaceLoadFailure, "nested module"),
 		)
 	})
 }
@@ -1743,12 +1692,7 @@
 	Run(t, nomod, func(t *testing.T, env *Env) {
 		env.OpenFile("main.go")
 		env.RegexpReplace("main.go", "{}", "{ var x int; }") // simulate typing
-		env.Await(
-			OnceMet(
-				env.DoneWithChange(),
-				NoLogMatching(protocol.Info, "packages=1"),
-			),
-		)
+		env.AfterChange(NoLogMatching(protocol.Info, "packages=1"))
 	})
 }
 
@@ -1808,11 +1752,9 @@
 		)
 		env.SetBufferContent("other.go", "package main\n\nasdf")
 		// The new diagnostic in other.go should not suppress diagnostics in main.go.
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexpWithMessage("other.go", "asdf", "expected declaration"),
-				env.DiagnosticAtRegexp("main.go", "asdf"),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexpWithMessage("other.go", "asdf", "expected declaration"),
+			env.DiagnosticAtRegexp("main.go", "asdf"),
 		)
 	})
 }
@@ -1831,11 +1773,8 @@
 		env.Await(env.DoneWithOpen())
 		env.RegexpReplace("go.mod", "module", "modul")
 		env.SaveBufferWithoutActions("go.mod")
-		env.Await(
-			OnceMet(
-				env.DoneWithSave(),
-				NoLogMatching(protocol.Error, "initial workspace load failed"),
-			),
+		env.AfterChange(
+			NoLogMatching(protocol.Error, "initial workspace load failed"),
 		)
 	})
 }
@@ -1855,11 +1794,8 @@
 `
 	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, false),
-			),
+		env.AfterChange(
+			LogMatching(protocol.Info, `.*query=\[builtin mod.com/...\].*`, 1, false),
 		)
 	})
 }
@@ -1877,11 +1813,9 @@
 const C = 0b10
 `
 	Run(t, files, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexpWithMessage("main.go", `0b10`, "go1.13 or later"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexpWithMessage("main.go", `0b10`, "go1.13 or later"),
 		)
 		env.WriteWorkspaceFile("go.mod", "module mod.com \n\ngo 1.13\n")
 		env.AfterChange(
@@ -1906,11 +1840,10 @@
 
 	Run(t, files, func(t *testing.T, env *Env) {
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexp("main.go", `C`),
-				ReadDiagnostics("main.go", &d),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexp("main.go", `C`),
+			ReadDiagnostics("main.go", &d),
 		)
 		if fixes := env.GetQuickFixes("main.go", d.Diagnostics); len(fixes) != 0 {
 			t.Errorf("got quick fixes %v, wanted none", fixes)
@@ -1933,12 +1866,10 @@
 `
 	Run(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexpWithMessage("main.go", `T any`, "type parameter"),
-				ReadDiagnostics("main.go", &d),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexpWithMessage("main.go", `T any`, "type parameter"),
+			ReadDiagnostics("main.go", &d),
 		)
 
 		env.ApplyQuickFixes("main.go", d.Diagnostics)
@@ -1968,14 +1899,11 @@
 	Run(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.
 		var d protocol.PublishDiagnosticsParams
 
-		// Once the initial workspace load is complete, we should have a diagnostic
-		// because generics are not supported at 1.16.
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexpWithMessage("main.go", `T any`, "type parameter"),
-				ReadDiagnostics("main.go", &d),
-			),
+		// We should have a diagnostic because generics are not supported at 1.16.
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexpWithMessage("main.go", `T any`, "type parameter"),
+			ReadDiagnostics("main.go", &d),
 		)
 
 		// This diagnostic should have a quick fix to edit the go version.
diff --git a/gopls/internal/regtest/diagnostics/invalidation_test.go b/gopls/internal/regtest/diagnostics/invalidation_test.go
index 2f0b173..f5097f3 100644
--- a/gopls/internal/regtest/diagnostics/invalidation_test.go
+++ b/gopls/internal/regtest/diagnostics/invalidation_test.go
@@ -30,30 +30,21 @@
 	Run(t, files, func(_ *testing.T, env *Env) { // Create a new workspace-level directory and empty file.
 		env.OpenFile("main.go")
 		var afterOpen protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DoneWithOpen(),
-				ReadDiagnostics("main.go", &afterOpen),
-			),
+		env.AfterChange(
+			ReadDiagnostics("main.go", &afterOpen),
 		)
 		env.CloseBuffer("main.go")
 		var afterClose protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DoneWithClose(),
-				ReadDiagnostics("main.go", &afterClose),
-			),
+		env.AfterChange(
+			ReadDiagnostics("main.go", &afterClose),
 		)
 		if afterOpen.Version == afterClose.Version {
 			t.Errorf("publishDiagnostics: got the same version after closing (%d) as after opening", afterOpen.Version)
 		}
 		env.OpenFile("main.go")
 		var afterReopen protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DoneWithOpen(),
-				ReadDiagnostics("main.go", &afterReopen),
-			),
+		env.AfterChange(
+			ReadDiagnostics("main.go", &afterReopen),
 		)
 		if afterReopen.Version == afterClose.Version {
 			t.Errorf("pubslishDiagnostics: got the same version after reopening (%d) as after closing", afterClose.Version)
@@ -87,11 +78,8 @@
 
 		env.OpenFile("main.go")
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DoneWithOpen(),
-				ReadDiagnostics("main.go", &d),
-			),
+		env.AfterChange(
+			ReadDiagnostics("main.go", &d),
 		)
 
 		if len(d.Diagnostics) != 1 {
@@ -102,11 +90,8 @@
 		for i := 0; i < 5; i++ {
 			before := d.Version
 			env.RegexpReplace("main.go", "Irrelevant comment #.", fmt.Sprintf("Irrelevant comment #%d", i))
-			env.Await(
-				OnceMet(
-					env.DoneWithChange(),
-					ReadDiagnostics("main.go", &d),
-				),
+			env.AfterChange(
+				ReadDiagnostics("main.go", &d),
 			)
 
 			if d.Version == before {
diff --git a/gopls/internal/regtest/misc/configuration_test.go b/gopls/internal/regtest/misc/configuration_test.go
index 15aeeb4..4164d6c 100644
--- a/gopls/internal/regtest/misc/configuration_test.go
+++ b/gopls/internal/regtest/misc/configuration_test.go
@@ -72,11 +72,9 @@
 	WithOptions(
 		Settings{"staticcheck": true},
 	).Run(t, files, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				ShownMessage("staticcheck is not supported"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			ShownMessage("staticcheck is not supported"),
 		)
 	})
 }
@@ -87,11 +85,9 @@
 	WithOptions(
 		Settings{"gofumpt": true},
 	).Run(t, "", func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				ShownMessage("gofumpt is not supported"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			ShownMessage("gofumpt is not supported"),
 		)
 	})
 }
@@ -104,13 +100,11 @@
 			"experimentalWorkspaceModule":    true,
 		},
 	).Run(t, "", func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				ShownMessage("experimentalWorkspaceModule"),
-				ShownMessage("experimentalUseInvalidMetadata"),
-				ShownMessage("experimentalWatchedFileDelay"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			ShownMessage("experimentalWorkspaceModule"),
+			ShownMessage("experimentalUseInvalidMetadata"),
+			ShownMessage("experimentalWatchedFileDelay"),
 		)
 	})
 }
diff --git a/gopls/internal/regtest/misc/imports_test.go b/gopls/internal/regtest/misc/imports_test.go
index 9e77d54..6558491 100644
--- a/gopls/internal/regtest/misc/imports_test.go
+++ b/gopls/internal/regtest/misc/imports_test.go
@@ -200,10 +200,8 @@
 		env.OpenFile("a/a.go")
 		var d protocol.PublishDiagnosticsParams
 		env.AfterChange(
-			OnceMet(
-				env.DiagnosticAtRegexp("a/a.go", "os.Stat"),
-				ReadDiagnostics("a/a.go", &d),
-			),
+			env.DiagnosticAtRegexp("a/a.go", "os.Stat"),
+			ReadDiagnostics("a/a.go", &d),
 		)
 		env.ApplyQuickFixes("a/a.go", d.Diagnostics)
 		env.AfterChange(
diff --git a/gopls/internal/regtest/misc/rename_test.go b/gopls/internal/regtest/misc/rename_test.go
index ef94ae2..b46b3d0 100644
--- a/gopls/internal/regtest/misc/rename_test.go
+++ b/gopls/internal/regtest/misc/rename_test.go
@@ -403,12 +403,10 @@
 		// Rename files and verify that diagnostics are affected accordingly.
 
 		// Initially, we should have diagnostics on both X's, for their duplicate declaration.
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexp("a/a.go", "X"),
-				env.DiagnosticAtRegexp("a/x.go", "X"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexp("a/a.go", "X"),
+			env.DiagnosticAtRegexp("a/x.go", "X"),
 		)
 
 		// Moving x.go should make the diagnostic go away.
diff --git a/gopls/internal/regtest/misc/vendor_test.go b/gopls/internal/regtest/misc/vendor_test.go
index 3210461..06e34b5 100644
--- a/gopls/internal/regtest/misc/vendor_test.go
+++ b/gopls/internal/regtest/misc/vendor_test.go
@@ -51,15 +51,14 @@
 	).Run(t, pkgThatUsesVendoring, func(t *testing.T, env *Env) {
 		env.OpenFile("a/a1.go")
 		d := &protocol.PublishDiagnosticsParams{}
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexpWithMessage("go.mod", "module mod.com", "Inconsistent vendoring"),
-				ReadDiagnostics("go.mod", d),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexpWithMessage("go.mod", "module mod.com", "Inconsistent vendoring"),
+			ReadDiagnostics("go.mod", d),
 		)
 		env.ApplyQuickFixes("go.mod", d.Diagnostics)
 
-		env.Await(
+		env.AfterChange(
 			env.DiagnosticAtRegexpWithMessage("a/a1.go", `q int`, "not used"),
 		)
 	})
diff --git a/gopls/internal/regtest/misc/vuln_test.go b/gopls/internal/regtest/misc/vuln_test.go
index 1b44caf..9556ab3 100644
--- a/gopls/internal/regtest/misc/vuln_test.go
+++ b/gopls/internal/regtest/misc/vuln_test.go
@@ -225,12 +225,10 @@
 			Arguments: lens.Command.Arguments,
 		}, &result)
 
-		env.Await(
-			OnceMet(
-				CompletedProgress(result.Token, nil),
-				ShownMessage("Found GOSTDLIB"),
-				NoDiagnostics("go.mod"),
-			),
+		env.OnceMet(
+			CompletedProgress(result.Token, nil),
+			ShownMessage("Found GOSTDLIB"),
+			NoDiagnostics("go.mod"),
 		)
 		testFetchVulncheckResult(t, env, map[string]fetchVulncheckResult{
 			"go.mod": {IDs: []string{"GOSTDLIB"}, Mode: govulncheck.ModeGovulncheck}})
@@ -586,17 +584,13 @@
 					var result command.RunVulncheckResult
 					env.ExecuteCodeLensCommand("go.mod", command.RunGovulncheck, &result)
 					gotDiagnostics := &protocol.PublishDiagnosticsParams{}
-					env.Await(
-						OnceMet(
-							CompletedProgress(result.Token, nil),
-							ShownMessage("Found"),
-						),
+					env.OnceMet(
+						CompletedProgress(result.Token, nil),
+						ShownMessage("Found"),
 					)
-					env.Await(
-						OnceMet(
-							env.DiagnosticAtRegexp("go.mod", "golang.org/bmod"),
-							ReadDiagnostics("go.mod", gotDiagnostics),
-						),
+					env.OnceMet(
+						env.DiagnosticAtRegexp("go.mod", "golang.org/bmod"),
+						ReadDiagnostics("go.mod", gotDiagnostics),
 					)
 					// We expect only one diagnostic for GO-2022-02.
 					count := 0
@@ -636,18 +630,14 @@
 		var result command.RunVulncheckResult
 		env.ExecuteCodeLensCommand("go.mod", command.RunGovulncheck, &result)
 		gotDiagnostics := &protocol.PublishDiagnosticsParams{}
-		env.Await(
-			OnceMet(
-				CompletedProgress(result.Token, nil),
-				ShownMessage("Found"),
-			),
+		env.OnceMet(
+			CompletedProgress(result.Token, nil),
+			ShownMessage("Found"),
 		)
 		// Vulncheck diagnostics asynchronous to the vulncheck command.
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexp("go.mod", `golang.org/amod`),
-				ReadDiagnostics("go.mod", gotDiagnostics),
-			),
+		env.OnceMet(
+			env.DiagnosticAtRegexp("go.mod", `golang.org/amod`),
+			ReadDiagnostics("go.mod", gotDiagnostics),
 		)
 
 		testFetchVulncheckResult(t, env, map[string]fetchVulncheckResult{
@@ -806,19 +796,15 @@
 		var result command.RunVulncheckResult
 		env.ExecuteCodeLensCommand("go.mod", command.RunGovulncheck, &result)
 		gotDiagnostics := &protocol.PublishDiagnosticsParams{}
-		env.Await(
-			OnceMet(
-				CompletedProgress(result.Token, nil),
-				ShownMessage("No vulnerabilities found"), // only count affecting vulnerabilities.
-			),
+		env.OnceMet(
+			CompletedProgress(result.Token, nil),
+			ShownMessage("No vulnerabilities found"), // only count affecting vulnerabilities.
 		)
 
 		// Vulncheck diagnostics asynchronous to the vulncheck command.
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexp("go.mod", "golang.org/bmod"),
-				ReadDiagnostics("go.mod", gotDiagnostics),
-			),
+		env.OnceMet(
+			env.DiagnosticAtRegexp("go.mod", "golang.org/bmod"),
+			ReadDiagnostics("go.mod", gotDiagnostics),
 		)
 
 		testFetchVulncheckResult(t, env, map[string]fetchVulncheckResult{"go.mod": {IDs: []string{"GO-2022-02"}, Mode: govulncheck.ModeGovulncheck}})
diff --git a/gopls/internal/regtest/modfile/modfile_test.go b/gopls/internal/regtest/modfile/modfile_test.go
index 9c2ad63..e870096 100644
--- a/gopls/internal/regtest/modfile/modfile_test.go
+++ b/gopls/internal/regtest/modfile/modfile_test.go
@@ -92,11 +92,8 @@
 			// modify the go.mod file.
 			goModContent := env.ReadWorkspaceFile("a/go.mod")
 			env.OpenFile("a/main.go")
-			env.Await(
-				OnceMet(
-					env.DoneWithOpen(),
-					env.DiagnosticAtRegexp("a/main.go", "\"example.com/blah\""),
-				),
+			env.AfterChange(
+				env.DiagnosticAtRegexp("a/main.go", "\"example.com/blah\""),
 			)
 			if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent {
 				t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got))
@@ -145,11 +142,8 @@
 			)
 
 			env.WriteWorkspaceFile("a/main.go", mainContent)
-			env.Await(
-				OnceMet(
-					env.DoneWithChangeWatchedFiles(),
-					env.DiagnosticAtRegexp("a/main.go", "\"example.com/blah\""),
-				),
+			env.AfterChange(
+				env.DiagnosticAtRegexp("a/main.go", "\"example.com/blah\""),
 			)
 			if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent {
 				t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got))
@@ -189,11 +183,9 @@
 		}
 		env.OpenFile("a/main.go")
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexp("a/main.go", `"example.com/blah"`),
-				ReadDiagnostics("a/main.go", &d),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("a/main.go", `"example.com/blah"`),
+			ReadDiagnostics("a/main.go", &d),
 		)
 		var goGetDiag protocol.Diagnostic
 		for _, diag := range d.Diagnostics {
@@ -238,11 +230,9 @@
 	}.Run(t, mod, func(t *testing.T, env *Env) {
 		env.OpenFile("a/main.go")
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexp("a/main.go", `"random.org/blah"`),
-				ReadDiagnostics("a/main.go", &d),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("a/main.go", `"random.org/blah"`),
+			ReadDiagnostics("a/main.go", &d),
 		)
 		var randomDiag protocol.Diagnostic
 		for _, diag := range d.Diagnostics {
@@ -294,11 +284,9 @@
 	}.Run(t, mod, func(t *testing.T, env *Env) {
 		env.OpenFile("a/main.go")
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexp("a/main.go", `"random.org/blah"`),
-				ReadDiagnostics("a/main.go", &d),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("a/main.go", `"random.org/blah"`),
+			ReadDiagnostics("a/main.go", &d),
 		)
 		var randomDiag protocol.Diagnostic
 		for _, diag := range d.Diagnostics {
@@ -345,11 +333,9 @@
 	}.Run(t, mod, func(t *testing.T, env *Env) {
 		env.OpenFile("a/go.mod")
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexp("a/go.mod", "// indirect"),
-				ReadDiagnostics("a/go.mod", &d),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("a/go.mod", "// indirect"),
+			ReadDiagnostics("a/go.mod", &d),
 		)
 		env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
 		if got := env.BufferText("a/go.mod"); got != want {
@@ -389,11 +375,9 @@
 	}.Run(t, files, func(t *testing.T, env *Env) {
 		env.OpenFile("a/go.mod")
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexp("a/go.mod", `require example.com`),
-				ReadDiagnostics("a/go.mod", &d),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("a/go.mod", `require example.com`),
+			ReadDiagnostics("a/go.mod", &d),
 		)
 		env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
 		if got := env.BufferText("a/go.mod"); got != want {
@@ -451,11 +435,9 @@
 	}.Run(t, repro, func(t *testing.T, env *Env) {
 		env.OpenFile("a/main.go")
 		var d protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				env.DiagnosticAtRegexp("a/main.go", `"github.com/esimov/caire"`),
-				ReadDiagnostics("a/main.go", &d),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("a/main.go", `"github.com/esimov/caire"`),
+			ReadDiagnostics("a/main.go", &d),
 		)
 		env.ApplyQuickFixes("a/main.go", d.Diagnostics)
 		want := `module mod.com
@@ -497,11 +479,9 @@
 		{"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
 		{"nested", WithOptions(ProxyFiles(proxy))},
 	}.Run(t, mod, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexp("a/go.mod", "require"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexp("a/go.mod", "require"),
 		)
 		env.RunGoCommandInDir("a", "mod", "tidy")
 		env.AfterChange(
@@ -1000,11 +980,9 @@
 		).Run(t, mod, func(t *testing.T, env *Env) {
 			env.OpenFile("go.mod")
 			d := &protocol.PublishDiagnosticsParams{}
-			env.Await(
-				OnceMet(
-					env.DiagnosticAtRegexp("go.mod", "require hasdep.com v1.2.3"),
-					ReadDiagnostics("go.mod", d),
-				),
+			env.AfterChange(
+				env.DiagnosticAtRegexp("go.mod", "require hasdep.com v1.2.3"),
+				ReadDiagnostics("go.mod", d),
 			)
 			const want = `module mod.com
 
@@ -1044,11 +1022,9 @@
 			d := &protocol.PublishDiagnosticsParams{}
 			env.OpenFile("go.mod")
 			pos := env.RegexpSearch("go.mod", "require hasdep.com v1.2.3")
-			env.Await(
-				OnceMet(
-					DiagnosticAt("go.mod", pos.Line, pos.Column),
-					ReadDiagnostics("go.mod", d),
-				),
+			env.AfterChange(
+				DiagnosticAt("go.mod", pos.Line, pos.Column),
+				ReadDiagnostics("go.mod", d),
 			)
 			const want = `module mod.com
 
@@ -1099,14 +1075,12 @@
 	).Run(t, mod, func(t *testing.T, env *Env) {
 		env.OpenFile("go.mod")
 		params := &protocol.PublishDiagnosticsParams{}
-		env.Await(
-			OnceMet(
-				Diagnostics(
-					env.AtRegexp("go.mod", `example.com`),
-					WithMessageContaining("go.sum is out of sync"),
-				),
-				ReadDiagnostics("go.mod", params),
+		env.AfterChange(
+			Diagnostics(
+				env.AtRegexp("go.mod", `example.com`),
+				WithMessageContaining("go.sum is out of sync"),
 			),
+			ReadDiagnostics("go.mod", params),
 		)
 		env.ApplyQuickFixes("go.mod", params.Diagnostics)
 		const want = `example.com v1.2.3 h1:Yryq11hF02fEf2JlOS2eph+ICE2/ceevGV3C9dl5V/c=
@@ -1191,11 +1165,9 @@
 package main
 `
 	Run(t, files, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexpWithMessage("go.mod", `go foo`, "invalid go version"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexpWithMessage("go.mod", `go foo`, "invalid go version"),
 		)
 		env.WriteWorkspaceFile("go.mod", "module mod.com \n\ngo 1.12\n")
 		env.AfterChange(NoDiagnostics("go.mod"))
diff --git a/gopls/internal/regtest/template/template_test.go b/gopls/internal/regtest/template/template_test.go
index 7ccf08d..140ba3c 100644
--- a/gopls/internal/regtest/template/template_test.go
+++ b/gopls/internal/regtest/template/template_test.go
@@ -71,12 +71,10 @@
 	).Run(t, files, func(t *testing.T, env *Env) {
 		// TODO: can we move this diagnostic onto {{}}?
 		var diags protocol.PublishDiagnosticsParams
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexp("hello.tmpl", "()Hello {{}}"),
-				ReadDiagnostics("hello.tmpl", &diags),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexp("hello.tmpl", "()Hello {{}}"),
+			ReadDiagnostics("hello.tmpl", &diags),
 		)
 		d := diags.Diagnostics // issue 50786: check for Source
 		if len(d) != 1 {
@@ -120,12 +118,10 @@
 			"templateExtensions": []string{"tmpl"},
 		},
 	).Run(t, files, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexp("a/a.tmpl", "()A"),
-				NoDiagnostics("b/b.tmpl"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexp("a/a.tmpl", "()A"),
+			NoDiagnostics("b/b.tmpl"),
 		)
 	})
 }
diff --git a/gopls/internal/regtest/watch/watch_test.go b/gopls/internal/regtest/watch/watch_test.go
index 70376a9..d2a203e 100644
--- a/gopls/internal/regtest/watch/watch_test.go
+++ b/gopls/internal/regtest/watch/watch_test.go
@@ -37,11 +37,9 @@
 	// diagnostics are updated.
 	t.Run("unopened", func(t *testing.T) {
 		Run(t, pkg, func(t *testing.T, env *Env) {
-			env.Await(
-				OnceMet(
-					InitialWorkspaceLoad,
-					env.DiagnosticAtRegexp("a/a.go", "x"),
-				),
+			env.OnceMet(
+				InitialWorkspaceLoad,
+				env.DiagnosticAtRegexp("a/a.go", "x"),
 			)
 			env.WriteWorkspaceFile("a/a.go", `package a; func _() {};`)
 			env.AfterChange(
@@ -124,11 +122,9 @@
 }
 `
 	Run(t, pkg, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexp("a/a.go", "x"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexp("a/a.go", "x"),
 		)
 		env.WriteWorkspaceFiles(map[string]string{
 			"b/b.go": `package b; func B() {};`,
@@ -202,11 +198,9 @@
 }
 `
 	Run(t, missing, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexp("a/a.go", "\"mod.com/c\""),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexp("a/a.go", "\"mod.com/c\""),
 		)
 		env.WriteWorkspaceFile("c/c.go", `package c; func C() {};`)
 		env.AfterChange(
@@ -252,11 +246,9 @@
 }
 `
 	Run(t, pkg, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				env.DiagnosticAtRegexp("a/a.go", "hello"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			env.DiagnosticAtRegexp("a/a.go", "hello"),
 		)
 		env.WriteWorkspaceFile("a/a2.go", `package a; func hello() {};`)
 		env.AfterChange(
@@ -391,18 +383,15 @@
 		).Run(t, pkg, func(t *testing.T, env *Env) {
 			env.OpenFile("a/a.go")
 			env.OpenFile("a/a_unneeded.go")
-			env.Await(
-				OnceMet(
-					env.DoneWithOpen(),
-					LogMatching(protocol.Info, "a_unneeded.go", 1, false),
-				),
+			env.AfterChange(
+				LogMatching(protocol.Info, "a_unneeded.go", 1, false),
 			)
 
 			// Close and delete the open file, mimicking what an editor would do.
 			env.CloseBuffer("a/a_unneeded.go")
 			env.RemoveWorkspaceFile("a/a_unneeded.go")
 			env.RegexpReplace("a/a.go", "var _ int", "fmt.Println(\"\")")
-			env.Await(
+			env.AfterChange(
 				env.DiagnosticAtRegexp("a/a.go", "fmt"),
 			)
 			env.SaveBuffer("a/a.go")
@@ -422,11 +411,8 @@
 		).Run(t, pkg, func(t *testing.T, env *Env) {
 			env.OpenFile("a/a.go")
 			env.OpenFile("a/a_unneeded.go")
-			env.Await(
-				OnceMet(
-					env.DoneWithOpen(),
-					LogMatching(protocol.Info, "a_unneeded.go", 1, false),
-				),
+			env.AfterChange(
+				LogMatching(protocol.Info, "a_unneeded.go", 1, false),
 			)
 
 			// Delete and then close the file.
@@ -682,15 +668,9 @@
 }
 `,
 		})
-		env.Await(
-			OnceMet(
-				env.DoneWithChangeWatchedFiles(),
-				NoDiagnostics("a/a.go"),
-			),
-			OnceMet(
-				env.DoneWithChangeWatchedFiles(),
-				NoDiagnostics("a/a_test.go"),
-			),
+		env.AfterChange(
+			NoDiagnostics("a/a.go"),
+			NoDiagnostics("a/a_test.go"),
 		)
 		// Now, add a new file to the test variant and use its symbol in the
 		// original test file. Expect no diagnostics.
@@ -714,15 +694,9 @@
 func TestSomething(t *testing.T) {}
 `,
 		})
-		env.Await(
-			OnceMet(
-				env.DoneWithChangeWatchedFiles(),
-				NoDiagnostics("a/a_test.go"),
-			),
-			OnceMet(
-				env.DoneWithChangeWatchedFiles(),
-				NoDiagnostics("a/a2_test.go"),
-			),
+		env.AfterChange(
+			NoDiagnostics("a/a_test.go"),
+			NoDiagnostics("a/a2_test.go"),
 		)
 	})
 }
diff --git a/gopls/internal/regtest/workspace/directoryfilters_test.go b/gopls/internal/regtest/workspace/directoryfilters_test.go
index 69f91cd..bf22b80 100644
--- a/gopls/internal/regtest/workspace/directoryfilters_test.go
+++ b/gopls/internal/regtest/workspace/directoryfilters_test.go
@@ -53,11 +53,9 @@
 	WithOptions(
 		Settings{"directoryFilters": []string{"-exclude"}},
 	).Run(t, files, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				NoDiagnostics("exclude/x.go"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			NoDiagnostics("exclude/x.go"),
 		)
 	})
 }
@@ -85,12 +83,10 @@
 	WithOptions(
 		Settings{"directoryFilters": []string{"-exclude"}},
 	).Run(t, files, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				NoDiagnostics("exclude/exclude.go"), // filtered out
-				NoDiagnostics("include/include.go"), // successfully builds
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			NoDiagnostics("exclude/exclude.go"), // filtered out
+			NoDiagnostics("include/include.go"), // successfully builds
 		)
 	})
 }
diff --git a/gopls/internal/regtest/workspace/fromenv_test.go b/gopls/internal/regtest/workspace/fromenv_test.go
index 218e206..831fa77 100644
--- a/gopls/internal/regtest/workspace/fromenv_test.go
+++ b/gopls/internal/regtest/workspace/fromenv_test.go
@@ -52,12 +52,10 @@
 		EnvVars{"GOWORK": "$SANDBOX_WORKDIR/config/go.work"},
 	).Run(t, files, func(t *testing.T, env *Env) {
 		// When we have an explicit GOWORK set, we should get a file watch request.
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				FileWatchMatching(`other`),
-				FileWatchMatching(`config.go\.work`),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			FileWatchMatching(`other`),
+			FileWatchMatching(`config.go\.work`),
 		)
 		env.Await(FileWatchMatching(`config.go\.work`))
 		// Even though work/b is not open, we should get its diagnostics as it is
diff --git a/gopls/internal/regtest/workspace/metadata_test.go b/gopls/internal/regtest/workspace/metadata_test.go
index c014f11..de7dec9 100644
--- a/gopls/internal/regtest/workspace/metadata_test.go
+++ b/gopls/internal/regtest/workspace/metadata_test.go
@@ -71,12 +71,10 @@
 	).Run(t, src, func(t *testing.T, env *Env) {
 		env.OpenFile("foo.go")
 		env.OpenFile("bar.go")
-		env.Await(
-			OnceMet(
-				env.DoneWithOpen(),
-				env.DiagnosticAtRegexp("foo.go", "func (main)"),
-				env.DiagnosticAtRegexp("bar.go", "func (main)"),
-			),
+		env.OnceMet(
+			env.DoneWithOpen(),
+			env.DiagnosticAtRegexp("foo.go", "func (main)"),
+			env.DiagnosticAtRegexp("bar.go", "func (main)"),
 		)
 
 		// Ignore bar.go. This should resolve diagnostics.
diff --git a/gopls/internal/regtest/workspace/standalone_test.go b/gopls/internal/regtest/workspace/standalone_test.go
index dffbbea..53b269e 100644
--- a/gopls/internal/regtest/workspace/standalone_test.go
+++ b/gopls/internal/regtest/workspace/standalone_test.go
@@ -185,12 +185,9 @@
 		env.OpenFile("ignore.go")
 		env.OpenFile("standalone.go")
 
-		env.Await(
-			OnceMet(
-				env.DoneWithOpen(),
-				env.DiagnosticAtRegexp("ignore.go", "package (main)"),
-				NoDiagnostics("standalone.go"),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("ignore.go", "package (main)"),
+			NoDiagnostics("standalone.go"),
 		)
 
 		cfg := env.Editor.Config()
@@ -203,12 +200,9 @@
 		// diagnostice when configuration changes.
 		env.RegexpReplace("ignore.go", "arbitrary", "meaningless")
 
-		env.Await(
-			OnceMet(
-				env.DoneWithChange(),
-				NoDiagnostics("ignore.go"),
-				env.DiagnosticAtRegexp("standalone.go", "package (main)"),
-			),
+		env.AfterChange(
+			NoDiagnostics("ignore.go"),
+			env.DiagnosticAtRegexp("standalone.go", "package (main)"),
 		)
 	})
 }
diff --git a/gopls/internal/regtest/workspace/workspace_test.go b/gopls/internal/regtest/workspace/workspace_test.go
index 1708263..720ec97 100644
--- a/gopls/internal/regtest/workspace/workspace_test.go
+++ b/gopls/internal/regtest/workspace/workspace_test.go
@@ -177,11 +177,8 @@
 replace random.org => %s
 `, env.ReadWorkspaceFile("pkg/go.mod"), dir)
 		env.WriteWorkspaceFile("pkg/go.mod", goModWithReplace)
-		env.Await(
-			OnceMet(
-				env.DoneWithChangeWatchedFiles(),
-				LogMatching(protocol.Info, `packages\.Load #\d+\n`, 2, false),
-			),
+		env.AfterChange(
+			LogMatching(protocol.Info, `packages\.Load #\d+\n`, 2, false),
 		)
 	})
 }
@@ -505,11 +502,8 @@
 		ProxyFiles(workspaceModuleProxy),
 	).Run(t, multiModule, func(t *testing.T, env *Env) {
 		env.OpenFile("modb/go.mod")
-		env.Await(
-			OnceMet(
-				env.DoneWithOpen(),
-				DiagnosticAt("modb/go.mod", 0, 0),
-			),
+		env.AfterChange(
+			DiagnosticAt("modb/go.mod", 0, 0),
 		)
 		env.RegexpReplace("modb/go.mod", "modul", "module")
 		env.SaveBufferWithoutActions("modb/go.mod")
@@ -612,11 +606,8 @@
 
 		// As of golang/go#54069, writing go.work to the workspace triggers a
 		// workspace reload.
-		env.Await(
-			OnceMet(
-				env.DoneWithChangeWatchedFiles(),
-				env.DiagnosticAtRegexp("modb/b/b.go", "x"),
-			),
+		env.AfterChange(
+			env.DiagnosticAtRegexp("modb/b/b.go", "x"),
 		)
 
 		// Jumping to definition should now go to b.com in the workspace.
@@ -627,7 +618,7 @@
 		// Now, let's modify the go.work *overlay* (not on disk), and verify that
 		// this change is only picked up once it is saved.
 		env.OpenFile("go.work")
-		env.Await(env.DoneWithOpen())
+		env.AfterChange()
 		env.SetBufferContent("go.work", `go 1.17
 
 use (
@@ -910,16 +901,14 @@
 	WithOptions(
 		ProxyFiles(proxy),
 	).Run(t, multiModule, func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				// TODO(rfindley): assert on the full set of diagnostics here. We
-				// should ensure that we don't have a diagnostic at b.Hi in a.go.
-				env.DiagnosticAtRegexp("moda/a/a.go", "x"),
-				env.DiagnosticAtRegexp("modb/b/b.go", "x"),
-				env.DiagnosticAtRegexp("modb/v2/b/b.go", "x"),
-				env.DiagnosticAtRegexp("modc/main.go", "x"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			// TODO(rfindley): assert on the full set of diagnostics here. We
+			// should ensure that we don't have a diagnostic at b.Hi in a.go.
+			env.DiagnosticAtRegexp("moda/a/a.go", "x"),
+			env.DiagnosticAtRegexp("modb/b/b.go", "x"),
+			env.DiagnosticAtRegexp("modb/v2/b/b.go", "x"),
+			env.DiagnosticAtRegexp("modc/main.go", "x"),
 		)
 	})
 }
@@ -1203,11 +1192,9 @@
 	}
 
 	Run(t, "", func(t *testing.T, env *Env) {
-		env.Await(
-			OnceMet(
-				InitialWorkspaceLoad,
-				NoShownMessage("upgrade"),
-			),
+		env.OnceMet(
+			InitialWorkspaceLoad,
+			NoShownMessage("upgrade"),
 		)
 	})
 }