goLanguageServer: improve gopls error report suggestion

Our current error reporting uses `gopls bug`. Modify the issue reporting
mechanism to request a stack trace and make the issue template clearer.

Updates golang/vscode-go#276

Change-Id: I0720422d1d20740d0bdbe02800fa5134fc4e488f
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/240506
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
(cherry picked from commit 0c6bb9ea9bfe71bdd3364cb80c6f43167680094a)
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/241161
diff --git a/src/goLanguageServer.ts b/src/goLanguageServer.ts
index ae0aee7..bc2c66d 100644
--- a/src/goLanguageServer.ts
+++ b/src/goLanguageServer.ts
@@ -145,10 +145,9 @@
 	// language server.
 	if (!restartCommand) {
 		restartCommand = vscode.commands.registerCommand('go.languageserver.restart', async () => {
-			// TODO(rstambler): Enable this behavior when gopls reaches v1.0.
-			if (false) {
-				await suggestGoplsIssueReport(`Looks like you're about to manually restart the language server.`);
-			}
+			await suggestGoplsIssueReport(
+				`Looks like you're about to manually restart the language server.`,
+				errorKind.manualRestart);
 			restartLanguageServer();
 		});
 		ctx.subscriptions.push(restartCommand);
@@ -197,8 +196,7 @@
 				vscode.window.showErrorMessage(
 					`The language server is not able to serve any features. Initialization failed: ${error}. `
 				);
-				serverOutputChannel.show();
-				suggestGoplsIssueReport(`The gopls server failed to initialize.`);
+				suggestGoplsIssueReport(`The gopls server failed to initialize.`, errorKind.initializationFailure);
 				return false;
 			},
 			errorHandler: {
@@ -218,8 +216,9 @@
 					if (crashCount < 5) {
 						return CloseAction.Restart;
 					}
-					serverOutputChannel.show();
-					suggestGoplsIssueReport(`The connection to gopls has been closed. The gopls server may have crashed.`);
+					suggestGoplsIssueReport(
+						`The connection to gopls has been closed. The gopls server may have crashed.`,
+						errorKind.crash);
 					return CloseAction.DoNotRestart;
 				},
 			},
@@ -814,8 +813,23 @@
 	updateGlobalState(goplsSurveyConfig, JSON.stringify(cfg));
 }
 
+// errorKind refers to the different possible kinds of gopls errors.
+enum errorKind {
+	initializationFailure,
+	crash,
+	manualRestart,
+}
+
 // suggestGoplsIssueReport prompts users to file an issue with gopls.
-async function suggestGoplsIssueReport(msg: string) {
+async function suggestGoplsIssueReport(msg: string, reason: errorKind) {
+	// Don't prompt users who manually restart to file issues until gopls/v1.0.
+	if (reason === errorKind.manualRestart) {
+		return;
+	}
+
+	// Show the user the output channel content to alert them to the issue.
+	serverOutputChannel.show();
+
 	if (latestConfig.serverName !== 'gopls') {
 		return;
 	}
@@ -839,15 +853,38 @@
 	const selected = await vscode.window.showInformationMessage(`${msg} Would you like to report a gopls issue ? `, 'Yes', 'Next time', 'Never');
 	switch (selected) {
 		case 'Yes':
-			// Run the `gopls bug` command directly for now. When
-			// https://github.com/golang/go/issues/38942 is
-			// resolved, we'll be able to do this through the
-			// language client.
+			// Prefill an issue title and report.
+			let errKind: string;
+			switch (reason) {
+				case errorKind.crash:
+					errKind = 'crash';
+					break;
+				case errorKind.initializationFailure:
+					errKind = 'initialization';
+					break;
+			}
+			const title = `gopls: automated issue report (${errKind})`;
+			const body = `ATTENTION: PLEASE PROVIDE THE DETAILS REQUESTED BELOW.
 
-			// Wait for the command to finish before restarting the
-			// server, but don't bother handling errors.
-			const execFile = util.promisify(cp.execFile);
-			await execFile(latestConfig.path, ['bug'], { env: toolExecutionEnvironment() });
+Describe what you observed.
+
+<ANSWER HERE>
+
+Please attach the stack trace from the crash.
+A window with the error message should have popped up in the lower half of your screen.
+Please copy the stack trace from that window and paste it in this issue.
+
+<PASTE STACK TRACE HERE>
+
+OPTIONAL: If you would like to share more information, you can attach your complete gopls logs.
+
+NOTE: THESE MAY CONTAIN SENSITIVE INFORMATION ABOUT YOUR CODEBASE.
+DO NOT SHARE LOGS IF YOU ARE WORKING IN A PRIVATE REPOSITORY.
+
+<OPTIONAL: ATTACH LOGS HERE>
+`;
+			const url = `https://github.com/golang/vscode-go/issues/new?title=${title}&labels=upstream-tools&body=${body}`;
+			await vscode.env.openExternal(vscode.Uri.parse(url));
 			break;
 		case 'Next time':
 			break;