src/language/goLanguageServer: remove redundant error popups from custom error handler

From vscode-languageclient v8.0.x (LSP 3.17), the language client reports the start
errors specially and surfaces them as user visible popups regardless revealOutputChannelOn
setting. Thus, our error popups are no longer necessary. Remove this.

When an error occurs during initialization, the connection to the server shuts
down which triggers the close handler. Previously, we suggested gopls issue
report from both initializationFailedHandler and errorHandler.closed handler.
That now results in two gopls issue report suggestions. Instead, stash the
initialization failure error, and handle the suggestion prompt from one place.

Note - in case of initializtion error, there is no point of retrying 5 times.

We also explicitly set the error & connection close handlers messages to empty
when requesting for continue/restart action, which will suppresses the default
error message popups.

While we are here, we improve the go status bar's language server state report
by updating it when the language server connection close is obeserved.

Updates microsoft/vscode-languageserver-node#1011
Fixes golang/vscode-go#2300

Change-Id: I8b20cf11ebb61ab474950440fc46ff23f7b0b826
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/414457
Reviewed-by: Jamal Carvalho <jamal@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/src/commands/startLanguageServer.ts b/src/commands/startLanguageServer.ts
index 703c5ee..e2c6f13 100644
--- a/src/commands/startLanguageServer.ts
+++ b/src/commands/startLanguageServer.ts
@@ -39,6 +39,7 @@
 		}
 
 		const unlock = await languageServerStartMutex.lock();
+		goCtx.latestConfig = cfg;
 		try {
 			if (reason === RestartReason.MANUAL) {
 				await suggestGoplsIssueReport(
@@ -52,6 +53,7 @@
 			if (goCtx.languageClient) {
 				await stopLanguageClient(goCtx);
 			}
+			updateStatus(goCtx, goConfig, false);
 
 			// Before starting the language server, make sure to deregister any
 			// currently registered language providers.
@@ -100,7 +102,6 @@
 			console.log(msg);
 			goCtx.serverOutputChannel?.append(msg);
 		} finally {
-			goCtx.latestConfig = cfg;
 			unlock();
 		}
 	};
diff --git a/src/language/goLanguageServer.ts b/src/language/goLanguageServer.ts
index 8561b25..d7c10f1 100644
--- a/src/language/goLanguageServer.ts
+++ b/src/language/goLanguageServer.ts
@@ -56,6 +56,7 @@
 import { daysBetween, getStateConfig, maybePromptForGoplsSurvey, timeDay, timeMinute } from '../goSurvey';
 import { maybePromptForDeveloperSurvey } from '../goDeveloperSurvey';
 import { CommandFactory } from '../commands';
+import { updateLanguageServerIconGoStatusBar } from '../goStatus';
 
 export interface LanguageServerConfig {
 	serverName: string;
@@ -360,6 +361,11 @@
 		{ language: 'gotmpl', scheme: 'file' }
 	];
 
+	// when initialization is failed after the connection is established,
+	// we want to handle the connection close error case specially. Capture the error
+	// in initializationFailedHandler and handle it in the connectionCloseHandler.
+	let initializationError: WebRequest.ResponseError<InitializeError> | undefined = undefined;
+
 	const c = new LanguageClient(
 		'go', // id
 		cfg.serverName, // name e.g. gopls
@@ -381,41 +387,56 @@
 			traceOutputChannel: cfg.traceOutputChannel,
 			revealOutputChannelOn: RevealOutputChannelOn.Never,
 			initializationFailedHandler: (error: WebRequest.ResponseError<InitializeError>): boolean => {
-				vscode.window.showErrorMessage(
-					`The language server is not able to serve any features. Initialization failed: ${error}. `
-				);
-				suggestGoplsIssueReport(
-					goCtx,
-					'The gopls server failed to initialize',
-					errorKind.initializationFailure,
-					error
-				);
+				initializationError = error;
 				return false;
 			},
 			errorHandler: {
 				error: (error: Error, message: Message, count: number) => {
 					// Allow 5 crashes before shutdown.
 					if (count < 5) {
-						return { action: ErrorAction.Continue };
+						return {
+							message: '', // suppresses error popups
+							action: ErrorAction.Continue
+						};
 					}
-					vscode.window.showErrorMessage(
-						`Error communicating with the language server: ${error}: ${message}.`
-					);
-					return { action: ErrorAction.Shutdown };
+					return {
+						action: ErrorAction.Shutdown
+					};
 				},
 				closed: () => {
+					if (initializationError !== undefined) {
+						suggestGoplsIssueReport(
+							goCtx,
+							'The gopls server failed to initialize.',
+							errorKind.initializationFailure,
+							initializationError
+						);
+						initializationError = undefined;
+						// In case of initialization failure, do not try to restart.
+						return {
+							message: 'The gopls server failed to initialize.',
+							action: CloseAction.DoNotRestart
+						};
+					}
+
 					// Allow 5 crashes before shutdown.
 					const { crashCount = 0 } = goCtx;
 					goCtx.crashCount = crashCount + 1;
 					if (goCtx.crashCount < 5) {
-						return { action: CloseAction.Restart };
+						return {
+							message: '', // suppresses error popups
+							action: CloseAction.Restart
+						};
 					}
 					suggestGoplsIssueReport(
 						goCtx,
 						'The connection to gopls has been closed. The gopls server may have crashed.',
 						errorKind.crash
 					);
-					return { action: CloseAction.DoNotRestart };
+					updateLanguageServerIconGoStatusBar(false, true);
+					return {
+						action: CloseAction.DoNotRestart
+					};
 				}
 			},
 			middleware: {