gopls/internal/lsp: remove Server.processModifications

Now that we no longer support a process delay, there is no need for this
function. Also, clean up the logic to await the completion of change
processing.

Updates golang/go#55332

Change-Id: I27936e112ee872eb1a46b350bf6f8f867a83bf19
Reviewed-on: https://go-review.googlesource.com/c/tools/+/462595
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/gopls/internal/lsp/text_synchronization.go b/gopls/internal/lsp/text_synchronization.go
index 3028dc9..b7be1e1 100644
--- a/gopls/internal/lsp/text_synchronization.go
+++ b/gopls/internal/lsp/text_synchronization.go
@@ -10,6 +10,7 @@
 	"errors"
 	"fmt"
 	"path/filepath"
+	"sync"
 
 	"golang.org/x/tools/gopls/internal/lsp/protocol"
 	"golang.org/x/tools/gopls/internal/lsp/source"
@@ -208,32 +209,35 @@
 }
 
 func (s *Server) didModifyFiles(ctx context.Context, modifications []source.FileModification, cause ModificationSource) error {
-	diagnoseDone := make(chan struct{})
+	// wg guards two conditions:
+	//  1. didModifyFiles is complete
+	//  2. the goroutine diagnosing changes on behalf of didModifyFiles is
+	//     complete, if it was started
+	//
+	// Both conditions must be satisfied for the purpose of testing: we don't
+	// want to observe the completion of change processing until we have received
+	// all diagnostics as well as all server->client notifications done on behalf
+	// of this function.
+	var wg sync.WaitGroup
+	wg.Add(1)
+	defer wg.Done()
+
 	if s.session.Options().VerboseWorkDoneProgress {
 		work := s.progress.Start(ctx, DiagnosticWorkTitle(cause), "Calculating file diagnostics...", nil, nil)
-		defer func() {
-			go func() {
-				<-diagnoseDone
-				work.End(ctx, "Done.")
-			}()
+		go func() {
+			wg.Wait()
+			work.End(ctx, "Done.")
 		}()
 	}
 
 	onDisk := cause == FromDidChangeWatchedFiles
-	return s.processModifications(ctx, modifications, onDisk, diagnoseDone)
-}
 
-// processModifications update server state to reflect file changes, and
-// triggers diagnostics to run asynchronously. The diagnoseDone channel will be
-// closed once diagnostics complete.
-func (s *Server) processModifications(ctx context.Context, modifications []source.FileModification, onDisk bool, diagnoseDone chan struct{}) error {
 	s.stateMu.Lock()
 	if s.state >= serverShutDown {
 		// This state check does not prevent races below, and exists only to
 		// produce a better error message. The actual race to the cache should be
 		// guarded by Session.viewMu.
 		s.stateMu.Unlock()
-		close(diagnoseDone)
 		return errors.New("server is shut down")
 	}
 	s.stateMu.Unlock()
@@ -251,7 +255,6 @@
 
 	snapshots, release, err := s.session.DidModifyFiles(ctx, modifications)
 	if err != nil {
-		close(diagnoseDone)
 		return err
 	}
 
@@ -266,10 +269,11 @@
 		}
 	}
 
+	wg.Add(1)
 	go func() {
 		s.diagnoseSnapshots(snapshots, onDisk)
 		release()
-		close(diagnoseDone)
+		wg.Done()
 	}()
 
 	// After any file modifications, we need to update our watched files,