[release] src/goLanguageServer: suggest updating gopls before filing an issue

We're getting a lot of crash issue reports with people using outdated
gopls versions. We can just suggest an update to them instead of filing
an issue.

Also, update the hardcoded latest gopls version and clean up the
installing message which used to print "gopls@v0.5.3@0.5.3".

Some formatting changes seem to have snuck in--I have format on save set
for TypeScript with the TSLint extension. Should I change something?

Change-Id: I3aca9e47f42e1e9951b1f6ad99944e36afac766f
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/272209
Trust: Rebecca Stambler <rstambler@golang.org>
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
(cherry picked from commit dd08b76e6bf97353b066b866ec5a3578217f7265)
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/272966
Trust: Robert Findley <rfindley@google.com>
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index 3870634..231c00b 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -226,8 +226,6 @@
 	}
 	args.push(importPath);
 
-	const toolImportPath = tool.version ? importPath + '@' + tool.version : importPath;
-
 	let output: string;
 	let result: string = '';
 	try {
@@ -253,10 +251,10 @@
 			await execFile(goBinary, ['build', '-o', outputFile, importPath], opts);
 		}
 		const toolInstallPath = getBinPath(tool.name);
-		outputChannel.appendLine(`Installing ${toolImportPath} (${toolInstallPath}) SUCCEEDED`);
+		outputChannel.appendLine(`Installing ${importPath} (${toolInstallPath}) SUCCEEDED`);
 	} catch (e) {
-		outputChannel.appendLine(`Installing ${toolImportPath} FAILED`);
-		result = `failed to install ${tool.name}(${toolImportPath}): ${e} ${output} `;
+		outputChannel.appendLine(`Installing ${importPath} FAILED`);
+		result = `failed to install ${tool.name}(${importPath}): ${e} ${output} `;
 	}
 
 	// Delete the temporary installation directory.
@@ -316,7 +314,7 @@
 	}
 }
 
-export async function promptForUpdatingTool(toolName: string, newVersion?: SemVer) {
+export async function promptForUpdatingTool(toolName: string, newVersion?: SemVer, crashed?: boolean) {
 	const tool = getTool(toolName);
 	const toolVersion = { ...tool, version: newVersion }; // ToolWithVersion
 
@@ -324,21 +322,28 @@
 	if (containsTool(declinedUpdates, tool)) {
 		return;
 	}
-	const goVersion = await getGoVersion();
-	let updateMsg = `Your version of ${tool.name} appears to be out of date. Please update for an improved experience.`;
+
+	// Adjust the prompt if it occurred because the tool crashed.
+	let updateMsg: string;
+	if (crashed === true) {
+		updateMsg = `${tool.name} has crashed, but you are using an outdated version. Please update to the latest version of ${tool.name}.`;
+	} else if (newVersion) {
+		updateMsg = `A new version of ${tool.name} (v${newVersion}) is available. Please update for an improved experience.`;
+	} else {
+		updateMsg = `Your version of ${tool.name} appears to be out of date. Please update for an improved experience.`;
+	}
+
 	let choices: string[] = ['Update'];
 	if (toolName === `gopls`) {
 		choices.push('Release Notes');
 	}
-	if (newVersion) {
-		updateMsg = `A new version of ${tool.name} (v${newVersion}) is available. Please update for an improved experience.`;
-	}
 
 	while (choices.length > 0) {
 		const selected = await vscode.window.showInformationMessage(updateMsg, ...choices);
 		switch (selected) {
 			case 'Update':
 				choices = [];
+				const goVersion = await getGoVersion();
 				await installTools([toolVersion], goVersion);
 				break;
 			case 'Release Notes':
diff --git a/src/goLanguageServer.ts b/src/goLanguageServer.ts
index e23d2df..763097c 100644
--- a/src/goLanguageServer.ts
+++ b/src/goLanguageServer.ts
@@ -215,19 +215,19 @@
 // used in building a new LanguageClient instance. Options specified
 // in LanguageServerConfig
 function buildLanguageClientOption(cfg: LanguageServerConfig): BuildLanguageClientOption {
-		// Reuse the same output channel for each instance of the server.
-		if (cfg.enabled) {
-			if (!serverOutputChannel) {
-				serverOutputChannel = vscode.window.createOutputChannel(cfg.serverName + ' (server)');
-			}
-			if (!serverTraceChannel) {
-				serverTraceChannel = vscode.window.createOutputChannel(cfg.serverName);
-			}
+	// Reuse the same output channel for each instance of the server.
+	if (cfg.enabled) {
+		if (!serverOutputChannel) {
+			serverOutputChannel = vscode.window.createOutputChannel(cfg.serverName + ' (server)');
 		}
-		return Object.assign({
-			outputChannel: serverOutputChannel,
-			traceOutputChannel: serverTraceChannel
-		}, cfg);
+		if (!serverTraceChannel) {
+			serverTraceChannel = vscode.window.createOutputChannel(cfg.serverName);
+		}
+	}
+	return Object.assign({
+		outputChannel: serverOutputChannel,
+		traceOutputChannel: serverTraceChannel
+	}, cfg);
 }
 
 // buildLanguageClient returns a language client built using the given language server config.
@@ -1128,6 +1128,17 @@
 		return;
 	}
 
+	// The user may have an outdated version of gopls, in which case we should
+	// just prompt them to update, not file an issue.
+	const tool = getTool('gopls');
+	if (tool) {
+		const versionToUpdate = await shouldUpdateLanguageServer(tool, latestConfig);
+		if (versionToUpdate) {
+			promptForUpdatingTool(tool.name, versionToUpdate, true);
+			return;
+		}
+	}
+
 	// Show the user the output channel content to alert them to the issue.
 	serverOutputChannel.show();
 
@@ -1165,8 +1176,8 @@
 					errKind = 'initialization';
 					break;
 			}
+			// Get the user's version in case the update prompt above failed.
 			const usersGoplsVersion = await getLocalGoplsVersion(latestConfig);
-			// TODO(hakim): If gopls version is too old, ask users to update it.
 			const settings = latestConfig.flags.join(' ');
 			const title = `gopls: automated issue report (${errKind})`;
 			const sanitizedLog = collectGoplsLog();
@@ -1258,7 +1269,7 @@
 			}
 			found = doc;
 			// .log, as some decoration is better than none
-			vscode.workspace.openTextDocument({language: 'log', content: contents});
+			vscode.workspace.openTextDocument({ language: 'log', content: contents });
 		}
 	}
 	if (found === undefined) {