src/goStatus: assign id/name to each status bar item

Adopt the new `createStatusBarItem` API which allows
users to control visibility per each status bar item
the extension creates.

This change also addresses an issue that caused the missing
analysis tool error status overridden by the go version release
notification message, because now the extension creates
separate status bar items for these two different notifications.

Fixes golang/vscode-go#1571

Change-Id: I6f457bace0385731a0218ccffebfba66e2fbb74b
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/370354
Reviewed-by: Suzy Mueller <suzmue@golang.org>
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
diff --git a/src/goCheck.ts b/src/goCheck.ts
index c4d710b..021b52d 100644
--- a/src/goCheck.ts
+++ b/src/goCheck.ts
@@ -20,7 +20,9 @@
 import { getTestFlags, goTest, TestConfig } from './testUtils';
 import { ICheckResult } from './util';
 
-const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
+const STATUS_BAR_ITEM_NAME = 'Go Test';
+const statusBarItem = vscode.window.createStatusBarItem(STATUS_BAR_ITEM_NAME, vscode.StatusBarAlignment.Left);
+statusBarItem.name = STATUS_BAR_ITEM_NAME;
 statusBarItem.command = 'go.test.showOutput';
 const neverAgain = { title: "Don't Show Again" };
 
diff --git a/src/goEnvironmentStatus.ts b/src/goEnvironmentStatus.ts
index 87f7473..8b11e48 100644
--- a/src/goEnvironmentStatus.ts
+++ b/src/goEnvironmentStatus.ts
@@ -555,6 +555,7 @@
 	return results;
 }
 
+const STATUS_BAR_ITEM_NAME = 'Go Notification';
 const dismissedGoVersionUpdatesKey = 'dismissedGoVersionUpdates';
 
 export async function offerToInstallLatestGoVersion() {
@@ -585,7 +586,12 @@
 
 	// notify user that there is a newer version of Go available
 	if (options.length > 0) {
-		addGoStatus('Go Update Available', 'go.promptforgoinstall', 'A newer version of Go is available');
+		addGoStatus(
+			STATUS_BAR_ITEM_NAME,
+			'Go Update Available',
+			'go.promptforgoinstall',
+			'A newer version of Go is available'
+		);
 		vscode.commands.registerCommand('go.promptforgoinstall', () => {
 			const download = {
 				title: 'Download',
@@ -630,7 +636,7 @@
 					// TODO: should we removeGoStatus if user has closed the notification
 					// without any action? It's kind of a feature now - without selecting
 					// neverAgain, user can hide this statusbar item.
-					removeGoStatus();
+					removeGoStatus(STATUS_BAR_ITEM_NAME);
 					selection?.command();
 				});
 		});
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index 5fc4aa5..1b02cc5 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -44,6 +44,8 @@
 import vscode = require('vscode');
 import { isInPreviewMode, RestartReason } from './goLanguageServer';
 
+const STATUS_BAR_ITEM_NAME = 'Go Tools';
+
 // declinedUpdates tracks the tools that the user has declined to update.
 const declinedUpdates: Tool[] = [];
 
@@ -395,7 +397,7 @@
 			break;
 		case 'Install All':
 			await installTools(missing, goVersion);
-			removeGoStatus();
+			removeGoStatus(STATUS_BAR_ITEM_NAME);
 			break;
 		default:
 			// The user has declined to install this tool.
@@ -555,12 +557,17 @@
 	let missing = await getMissingTools(goVersion);
 	missing = missing.filter((x) => x.isImportant);
 	if (missing.length > 0) {
-		addGoStatus('Analysis Tools Missing', 'go.promptforinstall', 'Not all Go tools are available on the GOPATH');
+		addGoStatus(
+			STATUS_BAR_ITEM_NAME,
+			'Analysis Tools Missing',
+			'go.promptforinstall',
+			'Not all Go tools are available on the GOPATH'
+		);
 		vscode.commands.registerCommand('go.promptforinstall', () => {
 			const installItem = {
 				title: 'Install',
 				async command() {
-					removeGoStatus();
+					removeGoStatus(STATUS_BAR_ITEM_NAME);
 					await installTools(missing, goVersion);
 				}
 			};
@@ -583,7 +590,7 @@
 					if (selection) {
 						selection.command();
 					} else {
-						removeGoStatus();
+						removeGoStatus(STATUS_BAR_ITEM_NAME);
 					}
 				});
 		});
diff --git a/src/goMain.ts b/src/goMain.ts
index 8bcb57e..b2cd019 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -100,14 +100,7 @@
 	resolvePath,
 	runGoVersionM
 } from './util';
-import {
-	clearCacheForTools,
-	fileExists,
-	getCurrentGoRoot,
-	dirExists,
-	setCurrentGoRoot,
-	envPath
-} from './utils/pathUtils';
+import { clearCacheForTools, fileExists, getCurrentGoRoot, dirExists, envPath } from './utils/pathUtils';
 import { WelcomePanel } from './welcome';
 import semver = require('semver');
 import vscode = require('vscode');
diff --git a/src/goStatus.ts b/src/goStatus.ts
index 2968297..89f98d5 100644
--- a/src/goStatus.ts
+++ b/src/goStatus.ts
@@ -24,7 +24,12 @@
 
 export const outputChannel = vscode.window.createOutputChannel('Go');
 
-export const diagnosticsStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
+const STATUS_BAR_ITEM_NAME = 'Go Diagnostics';
+export const diagnosticsStatusBarItem = vscode.window.createStatusBarItem(
+	STATUS_BAR_ITEM_NAME,
+	vscode.StatusBarAlignment.Left
+);
+diagnosticsStatusBarItem.name = STATUS_BAR_ITEM_NAME;
 
 // statusbar item for switching the Go environment
 export let goEnvStatusbarItem: vscode.StatusBarItem;
@@ -106,7 +111,13 @@
  */
 export async function initGoStatusBar() {
 	if (!goEnvStatusbarItem) {
-		goEnvStatusbarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 50);
+		const STATUS_BAR_ITEM_NAME = 'Go';
+		goEnvStatusbarItem = vscode.window.createStatusBarItem(
+			STATUS_BAR_ITEM_NAME,
+			vscode.StatusBarAlignment.Left,
+			50
+		);
+		goEnvStatusbarItem.name = STATUS_BAR_ITEM_NAME;
 	}
 	// set Go version and command
 	const version = await getGoVersion();
@@ -158,7 +169,13 @@
 	if (terminalCreationListener) {
 		terminalCreationListener.dispose();
 	}
-	removeGoStatus();
+	for (const statusBarEntry of statusBarEntries) {
+		if (statusBarEntry) {
+			const [name, entry] = statusBarEntry;
+			statusBarEntries.delete(name);
+			entry.dispose();
+		}
+	}
 }
 
 /**
@@ -171,18 +188,23 @@
 }
 
 // status bar item to show warning messages such as missing analysis tools.
-let statusBarEntry: vscode.StatusBarItem;
+const statusBarEntries = new Map<string, vscode.StatusBarItem>();
 
-export function removeGoStatus() {
+export function removeGoStatus(name: string) {
+	const statusBarEntry = statusBarEntries.get(name);
 	if (statusBarEntry) {
 		statusBarEntry.dispose();
-		statusBarEntry = undefined;
+		statusBarEntries.delete(name);
 	}
 }
 
-export function addGoStatus(message: string, command: string, tooltip?: string) {
+export function addGoStatus(name: string, message: string, command: string, tooltip?: string) {
+	let statusBarEntry = statusBarEntries.get(name);
 	if (!statusBarEntry) {
-		statusBarEntry = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, Number.MIN_VALUE);
+		statusBarEntry = vscode.window.createStatusBarItem(name, vscode.StatusBarAlignment.Right, Number.MIN_VALUE);
+		statusBarEntries.set(name, statusBarEntry);
+
+		statusBarEntry.name = name;
 	}
 	statusBarEntry.text = `$(alert) ${message}`;
 	statusBarEntry.command = command;
diff --git a/src/testUtils.ts b/src/testUtils.ts
index 3dc4e45..d340168 100644
--- a/src/testUtils.ts
+++ b/src/testUtils.ts
@@ -23,7 +23,9 @@
 import { killProcessTree } from './utils/processUtils';
 
 const testOutputChannel = vscode.window.createOutputChannel('Go Tests');
-const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
+const STATUS_BAR_ITEM_NAME = 'Go Test Cancel';
+const statusBarItem = vscode.window.createStatusBarItem(STATUS_BAR_ITEM_NAME, vscode.StatusBarAlignment.Left);
+statusBarItem.name = STATUS_BAR_ITEM_NAME;
 statusBarItem.command = 'go.test.cancel';
 statusBarItem.text = '$(x) Cancel Running Tests';