src/goStatus.ts: refactor status bar code into goStatus.ts

Refactor the status bar environment and entry items into the same
goStatus.ts file.

Change-Id: I892d3d32d828ff5743e5e6ce35d722c88530199c
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/258520
Trust: Suzy Mueller <suzmue@golang.org>
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Suzy Mueller <suzmue@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/src/goEnvironmentStatus.ts b/src/goEnvironmentStatus.ts
index 07d596e..126fce7 100644
--- a/src/goEnvironmentStatus.ts
+++ b/src/goEnvironmentStatus.ts
@@ -14,9 +14,8 @@
 import vscode = require('vscode');
 import WebRequest = require('web-request');
 import { toolInstallationEnvironment } from './goEnv';
-import { buildLanguageServerConfig } from './goLanguageServer';
 import { logVerbose } from './goLogging';
-import { hideGoStatus, languageServerIcon, outputChannel, showGoStatus } from './goStatus';
+import { addGoStatus, goEnvStatusbarItem, outputChannel, removeGoStatus } from './goStatus';
 import { getFromGlobalState, getFromWorkspaceState, updateGlobalState, updateWorkspaceState } from './stateUtils';
 import { getBinPath, getGoConfig, getGoVersion, getTempFilePath, GoVersion, rmdirRecursive } from './util';
 import { correctBinname, getBinPathFromEnvVar, getCurrentGoRoot, pathExists } from './utils/pathUtils';
@@ -36,80 +35,7 @@
 	}
 }
 
-// statusbar item for switching the Go environment
-let goEnvStatusbarItem: vscode.StatusBarItem;
-let terminalCreationListener: vscode.Disposable;
-
-/**
- * Initialize the status bar item with current Go binary
- */
-export async function initGoStatusBar() {
-	if (!goEnvStatusbarItem) {
-		goEnvStatusbarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 50);
-	}
-	// set Go version and command
-	const version = await getGoVersion();
-	const goOption = new GoEnvironmentOption(version.binaryPath, formatGoVersion(version));
-
-	hideGoStatusBar();
-	goEnvStatusbarItem.text = goOption.label;
-	goEnvStatusbarItem.command = 'go.environment.status';
-
-	// Add an icon to indicate that the 'gopls' server is running.
-	// Assume if it is configured it is already running, since the
-	// icon will be updated on an attempt to start.
-	const cfg = buildLanguageServerConfig();
-	updateLanguageServerIconGoStatusBar(true, cfg.serverName);
-
-	showGoStatusBar();
-}
-
-export async function updateLanguageServerIconGoStatusBar(started: boolean, server: string) {
-	if (!goEnvStatusbarItem) {
-		return;
-	}
-
-	const text = goEnvStatusbarItem.text;
-	if (started && server === 'gopls') {
-		if (!text.endsWith(languageServerIcon)) {
-			goEnvStatusbarItem.text = text + languageServerIcon;
-		}
-	} else {
-		if (text.endsWith(languageServerIcon)) {
-			goEnvStatusbarItem.text = text.substring(0, text.length - languageServerIcon.length);
-		}
-	}
-}
-
-/**
- * disable the Go environment status bar item
- */
-export function disposeGoStatusBar() {
-	if (!!goEnvStatusbarItem) {
-		goEnvStatusbarItem.dispose();
-	}
-	if (!!terminalCreationListener) {
-		terminalCreationListener.dispose();
-	}
-}
-
-/**
- * Show the Go Environment statusbar item on the statusbar
- */
-export function showGoStatusBar() {
-	if (!!goEnvStatusbarItem) {
-		goEnvStatusbarItem.show();
-	}
-}
-
-/**
- * Hide the Go Environment statusbar item from the statusbar
- */
-export function hideGoStatusBar() {
-	if (!!goEnvStatusbarItem) {
-		goEnvStatusbarItem.hide();
-	}
-}
+export let terminalCreationListener: vscode.Disposable;
 
 let environmentVariableCollection: vscode.EnvironmentVariableCollection;
 export function setEnvironmentVariableCollection(env: vscode.EnvironmentVariableCollection) {
@@ -571,7 +497,7 @@
 
 	// notify user that there is a newer version of Go available
 	if (options.length > 0) {
-		showGoStatus('Go Update Available', 'go.promptforgoinstall', 'A newer version of Go is available');
+		addGoStatus('Go Update Available', 'go.promptforgoinstall', 'A newer version of Go is available');
 		vscode.commands.registerCommand('go.promptforgoinstall', () => {
 			const download = {
 				title: 'Download',
@@ -612,7 +538,7 @@
 					neverAgain
 				)
 				.then((selection) => {
-					hideGoStatus();
+					removeGoStatus();
 					selection.command();
 				});
 		});
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index d80fe21..ff5cfe8 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -12,11 +12,11 @@
 import util = require('util');
 import vscode = require('vscode');
 import { toolExecutionEnvironment, toolInstallationEnvironment } from './goEnv';
-import { addGoRuntimeBaseToPATH, clearGoRuntimeBaseFromPATH, initGoStatusBar } from './goEnvironmentStatus';
+import { addGoRuntimeBaseToPATH, clearGoRuntimeBaseFromPATH } from './goEnvironmentStatus';
 import { getLanguageServerToolPath } from './goLanguageServer';
 import { logVerbose } from './goLogging';
 import { restartLanguageServer } from './goMain';
-import { hideGoStatus, outputChannel, showGoStatus } from './goStatus';
+import { addGoStatus, initGoEnvStatusBar, outputChannel, removeGoStatus } from './goStatus';
 import {
 	containsTool,
 	disableModulesForWildcard,
@@ -28,7 +28,6 @@
 	Tool,
 	ToolAtVersion,
 } from './goTools';
-import { getFromWorkspaceState } from './stateUtils';
 import {
 	getBinPath,
 	getBinPathWithExplanation,
@@ -301,7 +300,7 @@
 			break;
 		case 'Install All':
 			await installTools(missing, goVersion);
-			hideGoStatus();
+			removeGoStatus();
 			break;
 		default:
 			// The user has declined to install this tool.
@@ -396,7 +395,7 @@
 					// clear pre-existing terminal PATH mutation logic set up by this extension.
 					clearGoRuntimeBaseFromPATH();
 				}
-				initGoStatusBar();
+				initGoEnvStatusBar();
 				// TODO: restart language server or synchronize with language server update.
 
 				return resolve();
@@ -416,12 +415,12 @@
 	let missing = await getMissingTools(goVersion);
 	missing = missing.filter((x) => x.isImportant);
 	if (missing.length > 0) {
-		showGoStatus('Analysis Tools Missing', 'go.promptforinstall', 'Not all Go tools are available on the GOPATH');
+		addGoStatus('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() {
-					hideGoStatus();
+					removeGoStatus();
 					await installTools(missing, goVersion);
 				}
 			};
@@ -443,7 +442,7 @@
 					if (selection) {
 						selection.command();
 					} else {
-						hideGoStatus();
+						removeGoStatus();
 					}
 				});
 		});
diff --git a/src/goLanguageServer.ts b/src/goLanguageServer.ts
index 80c0797..0fac38a 100644
--- a/src/goLanguageServer.ts
+++ b/src/goLanguageServer.ts
@@ -20,7 +20,6 @@
 	ErrorAction,
 	ExecuteCommandParams,
 	ExecuteCommandRequest,
-	ExecuteCommandSignature,
 	HandleDiagnosticsSignature,
 	InitializeError,
 	LanguageClient,
@@ -35,7 +34,6 @@
 import { GoCodeActionProvider } from './goCodeAction';
 import { GoDefinitionProvider } from './goDeclaration';
 import { toolExecutionEnvironment } from './goEnv';
-import { updateLanguageServerIconGoStatusBar } from './goEnvironmentStatus';
 import { GoHoverProvider } from './goExtraInfo';
 import { GoDocumentFormattingEditProvider } from './goFormat';
 import { GoImplementationProvider } from './goImplementations';
@@ -47,6 +45,7 @@
 import { GoReferenceProvider } from './goReferences';
 import { GoRenameProvider } from './goRename';
 import { GoSignatureHelpProvider } from './goSignature';
+import { updateLanguageServerIconGoStatusBar } from './goStatus';
 import { GoCompletionItemProvider } from './goSuggest';
 import { GoWorkspaceSymbolProvider } from './goSymbol';
 import { getTool, Tool } from './goTools';
diff --git a/src/goMain.ts b/src/goMain.ts
index 1e707b2..dea0b8a 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -19,7 +19,7 @@
 import { GoDebugConfigurationProvider } from './goDebugConfiguration';
 import { extractFunction, extractVariable } from './goDoctor';
 import { toolExecutionEnvironment } from './goEnv';
-import { chooseGoEnvironment, disposeGoStatusBar, offerToInstallLatestGoVersion, setEnvironmentVariableCollection } from './goEnvironmentStatus';
+import { chooseGoEnvironment, offerToInstallLatestGoVersion, setEnvironmentVariableCollection } from './goEnvironmentStatus';
 import { runFillStruct } from './goFillStruct';
 import * as goGenerateTests from './goGenerateTests';
 import { goGetPackage } from './goGetPackage';
@@ -42,7 +42,7 @@
 import { playgroundCommand } from './goPlayground';
 import { GoReferencesCodeLensProvider } from './goReferencesCodelens';
 import { GoRunTestCodeLensProvider } from './goRunTestCodelens';
-import { expandGoStatusBar, outputChannel, showHideStatus } from './goStatus';
+import { disposeGoStatusBar, expandGoStatusBar, outputChannel, showHideStatus } from './goStatus';
 import { subTestAtCursor, testAtCursor, testCurrentFile, testCurrentPackage, testPrevious, testWorkspace } from './goTest';
 import { getConfiguredTools } from './goTools';
 import { vetCode } from './goVet';
diff --git a/src/goMode.ts b/src/goMode.ts
index 06b130e..d8d91b9 100644
--- a/src/goMode.ts
+++ b/src/goMode.ts
@@ -8,3 +8,14 @@
 import vscode = require('vscode');
 
 export const GO_MODE: vscode.DocumentFilter = { language: 'go', scheme: 'file' };
+export const GO_MOD_MODE: vscode.DocumentFilter = { language: 'go.mod', scheme: 'file' };
+export const GO_SUM_MODE: vscode.DocumentFilter = { language: 'go.sum', scheme: 'file' };
+
+export function isGoFile(document: vscode.TextDocument): boolean {
+	if (vscode.languages.match(GO_MODE, document)
+	|| vscode.languages.match(GO_MOD_MODE, document)
+	|| vscode.languages.match(GO_SUM_MODE, document)) {
+		return true;
+	}
+	return false;
+}
diff --git a/src/goStatus.ts b/src/goStatus.ts
index bac8c3b..0009f58 100644
--- a/src/goStatus.ts
+++ b/src/goStatus.ts
@@ -8,38 +8,42 @@
 
 import path = require('path');
 import vscode = require('vscode');
+import { formatGoVersion, GoEnvironmentOption, terminalCreationListener } from './goEnvironmentStatus';
 import { buildLanguageServerConfig, getLocalGoplsVersion, serverOutputChannel } from './goLanguageServer';
-import { GO_MODE } from './goMode';
+import { isGoFile } from './goMode';
 import { getModFolderPath, isModSupported } from './goModules';
+import { getGoVersion } from './util';
 
 export let outputChannel = vscode.window.createOutputChannel('Go');
 
 export let diagnosticsStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
 
+// statusbar item for switching the Go environment
+export let goEnvStatusbarItem: vscode.StatusBarItem;
+
 let statusBarEntry: vscode.StatusBarItem;
 let modulePath: string;
 export const languageServerIcon = '$(zap)';
 
 export function showHideStatus(editor: vscode.TextEditor) {
-	if (statusBarEntry) {
-		if (!editor) {
-			statusBarEntry.hide();
-		} else if (vscode.languages.match(GO_MODE, editor.document)) {
-			statusBarEntry.show();
-		} else {
-			statusBarEntry.hide();
+	// Update the status bar entry
+	if (!editor) {
+		hideGoStatusBar();
+	} else {
+		showGoStatusBar();
+		// Only update the module path if we are in a Go file.
+		// This allows the user to open output windows without losing
+		// the go.mod information in the status bar.
+		if (isGoFile(editor.document)) {
+			isModSupported(editor.document.uri).then((isMod) => {
+				if (isMod) {
+					getModFolderPath(editor.document.uri).then((p) => modulePath = p);
+				} else {
+					modulePath = '';
+				}
+			});
 		}
 	}
-
-	if (editor) {
-		isModSupported(editor.document.uri).then((isMod) => {
-			if (isMod) {
-				getModFolderPath(editor.document.uri).then((p) => modulePath = p);
-			} else {
-				modulePath = '';
-			}
-		});
-	}
 }
 
 export async function expandGoStatusBar() {
@@ -86,16 +90,93 @@
 
 }
 
-export function hideGoStatus() {
+/**
+ * Initialize the status bar item with current Go binary
+ */
+export async function initGoEnvStatusBar() {
+	if (!goEnvStatusbarItem) {
+		goEnvStatusbarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 50);
+	}
+	// set Go version and command
+	const version = await getGoVersion();
+	const goOption = new GoEnvironmentOption(version.binaryPath, formatGoVersion(version));
+
+	goEnvStatusbarItem.text = goOption.label;
+	goEnvStatusbarItem.command = 'go.environment.status';
+
+	// Add an icon to indicate that the 'gopls' server is running.
+	// Assume if it is configured it is already running, since the
+	// icon will be updated on an attempt to start.
+	const cfg = buildLanguageServerConfig();
+	updateLanguageServerIconGoStatusBar(true, cfg.serverName);
+
+	showHideStatus(vscode.window.activeTextEditor);
+}
+
+export async function updateLanguageServerIconGoStatusBar(started: boolean, server: string) {
+	if (!goEnvStatusbarItem) {
+		return;
+	}
+
+	const text = goEnvStatusbarItem.text;
+	if (started && server === 'gopls') {
+		if (!text.endsWith(languageServerIcon)) {
+			goEnvStatusbarItem.text = text + languageServerIcon;
+		}
+	} else {
+		if (text.endsWith(languageServerIcon)) {
+			goEnvStatusbarItem.text = text.substring(0, text.length - languageServerIcon.length);
+		}
+	}
+}
+
+/**
+ * disable the Go status bar items
+ */
+export function disposeGoStatusBar() {
+	if (!!goEnvStatusbarItem) {
+		goEnvStatusbarItem.dispose();
+	}
+	if (!!terminalCreationListener) {
+		terminalCreationListener.dispose();
+	}
+	removeGoStatus();
+}
+
+/**
+ * Show the Go statusbar items on the statusbar
+ */
+export function showGoStatusBar() {
+	if (!!goEnvStatusbarItem) {
+		goEnvStatusbarItem.show();
+	}
+	if (!!statusBarEntry) {
+		statusBarEntry.show();
+	}
+}
+
+/**
+ * Hide the Go statusbar items on the statusbar
+ */
+export function hideGoStatusBar() {
+	if (!!goEnvStatusbarItem) {
+		goEnvStatusbarItem.hide();
+	}
+	if (!!statusBarEntry) {
+		statusBarEntry.hide();
+	}
+}
+
+export function removeGoStatus() {
 	if (statusBarEntry) {
 		statusBarEntry.dispose();
 	}
 }
 
-export function showGoStatus(message: string, command: string, tooltip?: string) {
+export function addGoStatus(message: string, command: string, tooltip?: string) {
 	statusBarEntry = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, Number.MIN_VALUE);
 	statusBarEntry.text = `$(alert) ${message}`;
 	statusBarEntry.command = command;
 	statusBarEntry.tooltip = tooltip;
-	statusBarEntry.show();
+	showHideStatus(vscode.window.activeTextEditor);
 }
diff --git a/test/integration/statusbar.test.ts b/test/integration/statusbar.test.ts
index 124cf91..153f36b 100644
--- a/test/integration/statusbar.test.ts
+++ b/test/integration/statusbar.test.ts
@@ -15,7 +15,6 @@
 import * as vscode from 'vscode';
 
 import {
-	disposeGoStatusBar,
 	formatGoVersion,
 	getGoEnvironmentStatusbarItem,
 	getSelectedGo,
@@ -23,6 +22,7 @@
 	setSelectedGo,
 } from '../../src/goEnvironmentStatus';
 import { updateGoVarsFromConfig } from '../../src/goInstallTools';
+import { disposeGoStatusBar } from '../../src/goStatus';
 import { getWorkspaceState, setWorkspaceState } from '../../src/stateUtils';
 import ourutil = require('../../src/util');
 import { getCurrentGoRoot } from '../../src/utils/pathUtils';