sync: merge microsoft/vscode-go@46dfb5a into master

Removed isForNightly from util.ts, and set the acceptGoplsPrerelease
var in goLanguageServer.ts directly. The variable was newly
added by microsoft/vscode@28e2d9.

Change-Id: Ic4bfe925cd3285632cefae7365d2835388bb081c
diff --git a/.prettierrc.json b/.prettierrc.json
index 410bca4..18704c7 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -2,5 +2,6 @@
 	"printWidth": 120,
 	"singleQuote": true,
 	"arrowParens": "always",
-	"quoteProps": "consistent"
+	"quoteProps": "consistent",
+	"trailingComma": "none"
 }
\ No newline at end of file
diff --git a/README.md b/README.md
index d5f4900..9cbff90 100644
--- a/README.md
+++ b/README.md
@@ -227,9 +227,11 @@
 
 ### _Optional_: Debugging
 
-To use the debugger, you must currently manually install `delve`.  See the [Installation Instructions](https://github.com/derekparker/delve/tree/master/Documentation/installation) for full details.  On MacOS it requires creating a self-signed cert to sign the `dlv` binary.
+To use the debugger, you must currently manually [install delve](https://github.com/derekparker/delve/tree/master/Documentation/installation). For more read [Debugging Go Code Using VS Code](https://github.com/Microsoft/vscode-go/wiki/Debugging-Go-code-using-VS-Code).
 
-For more read [Debugging Go Code Using VS Code](https://github.com/Microsoft/vscode-go/wiki/Debugging-Go-code-using-VS-Code).
+#### Debugging in WSL
+
+If using WSL on Windows, you will need the WSL 2 Linux kernel.  See [WSL 2 Installation](https://docs.microsoft.com/en-us/windows/wsl/wsl2-install) and note the Window 10 build version requirements. 
 
 #### Remote Debugging
 
diff --git a/docs/Building,-Debugging-and-Sideloading-the-extension-in-Visual-Studio-Code.md b/docs/Building,-Debugging-and-Sideloading-the-extension-in-Visual-Studio-Code.md
index 3bdb1f9..d0067d1 100644
--- a/docs/Building,-Debugging-and-Sideloading-the-extension-in-Visual-Studio-Code.md
+++ b/docs/Building,-Debugging-and-Sideloading-the-extension-in-Visual-Studio-Code.md
@@ -39,4 +39,4 @@
 
 ## Use the beta version of this extension
 
-If you want to help with testing the next update to this extension or you want to use the latest features that arent released yet, its easy to do so. Please see [Use the beta version of the Go extension](https://github.com/Microsoft/vscode-go/wiki/Use-the-beta-version-of-the-latest-Go-extension)
\ No newline at end of file
+If you want to help with testing the next update to this extension or you want to use the latest features that arent released yet, its easy to do so. Please see [Use the beta version of the Go extension](Use-the-beta-version-of-the-latest-Go-extension.md)
\ No newline at end of file
diff --git a/docs/Debugging-Go-code-using-VS-Code.md b/docs/Debugging-Go-code-using-VS-Code.md
index 9dec596..e36c61f 100644
--- a/docs/Debugging-Go-code-using-VS-Code.md
+++ b/docs/Debugging-Go-code-using-VS-Code.md
@@ -2,13 +2,13 @@
 
 There are 2 ways to install delve
 - Run the command `Go: Install/Update Tools`, select `dlv`, press `Ok` to install/update delve
-- Or install it manually install delve as per the [Installation Instructions](https://github.com/derekparker/delve/tree/master/Documentation/installation).
+- Or install it manually install delve as per the [Installation Instructions](https://github.com/go-delve/delve/tree/master/Documentation/installation).
 
 ## Set up configurations in your settings
 
 The below settings are used by the debugger. You may not need to add/change any of them to have debugging working in simple cases, but do give them a read sometime
-- `go.gopath`. See [GOPATH in VS Code](https://github.com/Microsoft/vscode-go/wiki/GOPATH-in-the-VS-Code-Go-extension)
-- `go.inferGopath`. See [GOPATH in VS Code](https://github.com/Microsoft/vscode-go/wiki/GOPATH-in-the-VS-Code-Go-extension)
+- `go.gopath`. See [GOPATH in VS Code](GOPATH-in-the-VS-Code-Go-extension.md)
+- `go.inferGopath`. See [GOPATH in VS Code](GOPATH-in-the-VS-Code-Go-extension.md)
 - `go.delveConfig`
      - `apiVersion`: Controls the version of delve apis to be used when launching the delve headless server. Default is 2.
      - `dlvLoadConfig`: Not applicable when `apiVersion` is 1. The configuration passed to delve. Controls [various features of delve](https://github.com/Microsoft/vscode-go/blob/0.6.85/package.json#L431-L468) that affects the variables shown in the debug pane.
@@ -205,7 +205,7 @@
 
 ### Debug the debugger using source code
 
-If you want to dig deeper and debug the debugger using source code of this extension, see [building-and-debugging-the-extension](https://github.com/Microsoft/vscode-go/wiki/Building,-Debugging-and-Sideloading-the-extension-in-Visual-Studio-Code#building-and-debugging-the-extension)
+If you want to dig deeper and debug the debugger using source code of this extension, see [building-and-debugging-the-extension](Building,-Debugging-and-Sideloading-the-extension-in-Visual-Studio-Code#building-and-debugging-the-extension.md)
 
 ### Common issues
 
@@ -234,6 +234,11 @@
 
 **_Solution_**: Ensure that the `program` attribute points to the folder that contains the test files you want to run.
 
+#### delve/launch hangs with no messages when using WSL
+Try running ```delve debug ./main``` at the WSL command line and see if you get a prompt
+
+**_Solution_**: Ensure you are running the WSL 2 Kernel, which (as of 4/15/2020) requires an early release of the Windows 10 OS.  This is available to anyone via the Windows Insider program.  See [WSL 2 Installation](https://docs.microsoft.com/en-us/windows/wsl/wsl2-install)
+
 #### could not launch process: could not fork/exec
 
 ##### OSX 
@@ -258,4 +263,4 @@
 
 #### Try using dlv from the terminal/command-line
 
-Add `"trace": "log"` to your debug configuration and debug in VS Code. This will send logs to the debug console where you can see the actual call being made to dlv. You can copy that and run it in your terminal
\ No newline at end of file
+Add `"trace": "log"` to your debug configuration and debug in VS Code. This will send logs to the debug console where you can see the actual call being made to dlv. You can copy that and run it in your terminal
diff --git a/docs/Go-modules-support-in-Visual-Studio-Code.md b/docs/Go-modules-support-in-Visual-Studio-Code.md
index 95e3de6..652fdbf 100644
--- a/docs/Go-modules-support-in-Visual-Studio-Code.md
+++ b/docs/Go-modules-support-in-Visual-Studio-Code.md
@@ -1,4 +1,4 @@
-VS Code uses a host of [Go tools](https://github.com/Microsoft/vscode-go/wiki/Go-tools-that-the-Go-extension-depends-on) to provide features like code navigation, code completion, build, lint etc. 
+VS Code uses a host of [Go tools](Go-tools-that-the-Go-extension-depends-on.md) to provide features like code navigation, code completion, build, lint etc. 
 
 > ⚠️ These tools **do not** provide a good support for [Go modules](https://blog.golang.org/modules2019) yet. 
 
@@ -21,7 +21,7 @@
 To troubleshoot the language server, please see [Troubleshooting gopls](https://github.com/golang/go/wiki/gopls#troubleshooting)
 
 
-If you don't want to use the language server for any reason, then please know that not all the [Go tools](https://github.com/Microsoft/vscode-go/wiki/Go-tools-that-the-Go-extension-depends-on) that this extension depends on supports Go modules. https://github.com/golang/go/issues/24661 is the issue used by the Go tools team to track the update of Go modules support in various Go tools.
+If you don't want to use the language server for any reason, then please know that not all the [Go tools](Go-tools-that-the-Go-extension-depends-on.md) that this extension depends on supports Go modules. https://github.com/golang/go/issues/24661 is the issue used by the Go tools team to track the update of Go modules support in various Go tools.
 
 ## FAQ
 
diff --git a/docs/Go-with-VS-Code-FAQ-and-Troubleshooting.md b/docs/Go-with-VS-Code-FAQ-and-Troubleshooting.md
index 7a785c2..00caf78 100644
--- a/docs/Go-with-VS-Code-FAQ-and-Troubleshooting.md
+++ b/docs/Go-with-VS-Code-FAQ-and-Troubleshooting.md
@@ -2,7 +2,7 @@
 
 **Q: I installed the plugin, but none of the features are working. Why?**
 
-**A:** Make sure to install all the dependent Go tools. Run `Go: Install/Update Tools`. If you want to install only selected tools, then go through the [Go tools that this plugin depends on](https://github.com/Microsoft/vscode-go/wiki/Go-tools-that-the-Go-extension-depends-on) and install the ones you need manually
+**A:** Make sure to install all the dependent Go tools. Run `Go: Install/Update Tools`. If you want to install only selected tools, then go through the [Go tools that this plugin depends on](Go-tools-that-the-Go-extension-depends-on) and install the ones you need manually
 
 If you see an error of the form `command <command-name-here> not found`, it means that the extension has failed to activate and register its commands. Please try to uninstall and re-install the extension.
 
@@ -43,15 +43,15 @@
 
 **Q: How does the plugin determine the GOPATH to use?**
 
-**A:** See [GOPATH in the VS Code Go extension](https://github.com/Microsoft/vscode-go/wiki/GOPATH-in-the-VS-Code-Go-extension)
+**A:** See [GOPATH in the VS Code Go extension](GOPATH-in-the-VS-Code-Go-extension.md)
 
 **Q: Does VS Code support Go modules?**
 
-**A:** See [Go modules support in VS Code](https://github.com/Microsoft/vscode-go/wiki/Go-modules-support-in-Visual-Studio-Code)
+**A:** See [Go modules support in VS Code](Go-modules-support-in-Visual-Studio-Code.md)
 
 **Q: Why is code navigation and code completion slow when using Go modules?**
 
-Please see [Go modules support in VS Code](https://github.com/Microsoft/vscode-go/wiki/Go-modules-support-in-Visual-Studio-Code)
+Please see [Go modules support in VS Code](Go-modules-support-in-Visual-Studio-Code.md)
 
 **Q: Can I use language server when using Go modules?**
 
@@ -95,4 +95,4 @@
 
 **Q: How do I get the features/bug fixes that are implemented but not released yet? How do I get the beta version of the Go extension?**
 
-**A:** See [Install the beta version](https://github.com/Microsoft/vscode-go/wiki/Use-the-beta-version-of-the-latest-Go-extension)
\ No newline at end of file
+**A:** See [Install the beta version](Use-the-beta-version-of-the-latest-Go-extension.md)
\ No newline at end of file
diff --git a/docs/Home.md b/docs/Home.md
deleted file mode 100644
index a908f4b..0000000
--- a/docs/Home.md
+++ /dev/null
@@ -1,11 +0,0 @@
-- How to contribute? [Build, Debug and/or SideLoad the Go extension](https://github.com/Microsoft/vscode-go/wiki/Building,-Debugging-and-Sideloading-the-extension-in-Visual-Studio-Code)
-
-- [Go tools that the Go extension depends on](https://github.com/Microsoft/vscode-go/wiki/Go-tools-that-the-Go-extension-depends-on)
-- [GOPATH in the VS Code Go extension](https://github.com/Microsoft/vscode-go/wiki/GOPATH-in-the-VS-Code-Go-extension)
-- [Settings & Commands in Visual Studio Code Go extension](https://github.com/Microsoft/vscode-go/wiki/Settings-for-Visual-Studio-Code-Go-extension) 
-- [Debugging Go Code Using VS Code](https://github.com/Microsoft/vscode-go/wiki/Debugging-Go-code-using-VS-Code)
-- [Release Notes](https://github.com/Microsoft/vscode-go/wiki/Release-Notes)
-
-
-See the [FAQ](https://github.com/Microsoft/vscode-go/wiki/Go-with-VS-Code-FAQ-and-Troubleshooting).
-Read a [demo script](demo-script).
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..9ec8d70
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,10 @@
+- How to contribute? [Build, Debug and/or SideLoad the Go extension](Building,-Debugging-and-Sideloading-the-extension-in-Visual-Studio-Code.md)
+
+- [Go tools that the Go extension depends on](Go-tools-that-the-Go-extension-depends-on.md)
+- [GOPATH in the VS Code Go extension](GOPATH-in-the-VS-Code-Go-extension.md)
+- [Settings & Commands in Visual Studio Code Go extension](Settings-for-Visual-Studio-Code-Go-extension.md) 
+- [Debugging Go Code Using VS Code](Debugging-Go-code-using-VS-Code.md)
+- [Release Notes](https://github.com/Microsoft/vscode-go/blob/master/CHANGELOG.md)
+
+
+See the [FAQ](Go-with-VS-Code-FAQ-and-Troubleshooting.md).
\ No newline at end of file
diff --git a/docs/Release-Notes.md b/docs/Release-Notes.md
deleted file mode 100644
index 51dedd7..0000000
--- a/docs/Release-Notes.md
+++ /dev/null
@@ -1 +0,0 @@
-The Release Notes for the Go extension to VS Code is captured in the [Changelog](https://github.com/Microsoft/vscode-go/blob/master/CHANGELOG.md)
\ No newline at end of file
diff --git a/package.json b/package.json
index fb6541d..2ec6eda 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,7 @@
     "@types/node": "^13.11.1",
     "@types/semver": "^7.1.0",
     "@types/sinon": "^9.0.0",
-    "@types/vscode": "^1.44.0",
+    "@types/vscode": "^1.41.0",
     "fs-extra": "^9.0.0",
     "glob": "^7.1.6",
     "mocha": "^7.1.1",
diff --git a/src/debugAdapter/Readme.md b/src/debugAdapter/Readme.md
index d80f71c..47b1c6e 100644
--- a/src/debugAdapter/Readme.md
+++ b/src/debugAdapter/Readme.md
@@ -8,12 +8,26 @@
 
 Clone this [repo](https://github.com/Microsoft/vscode-go) and then run `npm install`
 
-```
+```shell
 git clone https://github.com/Microsoft/vscode-go
 cd vscode-go
 npm install
 ```
 
+#### Debug Adapter compilation:
+You might want to compile the debug adapter to verify your changes. Additionally, debug symbols must be updated whenever you want to set breakpoints accurately. For the vscode-go project, there is a build task available which will start the Typescript compiler in watch mode, detecting errors on code changes and updating debug symbols automatically.
+
+The project on the debugAdapter folder level doesn´t have this task included, but the `tsc` compiler can be started manually via the following steps:
+
+1. Install `tsc`, if you haven't done so yet:
+```shell
+npm install -g typescript
+```
+2. In the debugAdapter directory, start `tsc` in watch mode, using this extension's Typescript configuration rules:
+```shell
+tsc -w -p ../../
+```
+
 ## Debugging the Go Debug Adapter
 
 This is the option you would take if you want to understand or change the way the Go debug adapter interacts with delve.
diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts
index cd90b29..d143d3c 100644
--- a/src/debugAdapter/goDebug.ts
+++ b/src/debugAdapter/goDebug.ts
@@ -24,7 +24,7 @@
 	StackFrame,
 	StoppedEvent,
 	TerminatedEvent,
-	Thread,
+	Thread
 } from 'vscode-debugadapter';
 import { DebugProtocol } from 'vscode-debugprotocol';
 import {
@@ -1399,16 +1399,9 @@
 			}
 
 			if (i) {
-				localPath =
-					llist
-						.reverse()
-						.slice(0, -i)
-						.join(this.localPathSeparator) + this.localPathSeparator;
+				localPath = llist.reverse().slice(0, -i).join(this.localPathSeparator) + this.localPathSeparator;
 				args.remotePath =
-					rlist
-						.reverse()
-						.slice(0, -i)
-						.join(this.remotePathSeparator) + this.remotePathSeparator;
+					rlist.reverse().slice(0, -i).join(this.remotePathSeparator) + this.remotePathSeparator;
 			} else if (
 				args.remotePath.length > 1 &&
 				(args.remotePath.endsWith('\\') || args.remotePath.endsWith('/'))
@@ -1720,7 +1713,7 @@
 			// TODO(polina): validate the assumption in this code that the first goroutine
 			// is the current one. So far it appears to me that this is always the main goroutine
 			// with id 1.
-			this.delve.call<DebugGoroutine[] | ListGoroutinesOut>('ListGoroutines', [{count: 1}], (err, out) => {
+			this.delve.call<DebugGoroutine[] | ListGoroutinesOut>('ListGoroutines', [{ count: 1 }], (err, out) => {
 				if (err) {
 					this.logDelveError(err, 'Failed to get threads');
 				}
diff --git a/src/goBaseCodelens.ts b/src/goBaseCodelens.ts
index 6f4f442..1282fd6 100644
--- a/src/goBaseCodelens.ts
+++ b/src/goBaseCodelens.ts
@@ -1,29 +1,29 @@
-/*---------------------------------------------------------

- * Copyright (C) Microsoft Corporation. All rights reserved.

- * Licensed under the MIT License. See License.txt in the project root for license information.

- *--------------------------------------------------------*/

-

-import vscode = require('vscode');

-

-export abstract class GoBaseCodeLensProvider implements vscode.CodeLensProvider {

-	protected enabled: boolean = true;

-	private onDidChangeCodeLensesEmitter = new vscode.EventEmitter<void>();

-

-	public get onDidChangeCodeLenses(): vscode.Event<void> {

-		return this.onDidChangeCodeLensesEmitter.event;

-	}

-

-	public setEnabled(enabled: false): void {

-		if (this.enabled !== enabled) {

-			this.enabled = enabled;

-			this.onDidChangeCodeLensesEmitter.fire();

-		}

-	}

-

-	public provideCodeLenses(

-		document: vscode.TextDocument,

-		token: vscode.CancellationToken

-	): vscode.ProviderResult<vscode.CodeLens[]> {

-		return [];

-	}

-}

+/*---------------------------------------------------------
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------*/
+
+import vscode = require('vscode');
+
+export abstract class GoBaseCodeLensProvider implements vscode.CodeLensProvider {
+	protected enabled: boolean = true;
+	private onDidChangeCodeLensesEmitter = new vscode.EventEmitter<void>();
+
+	public get onDidChangeCodeLenses(): vscode.Event<void> {
+		return this.onDidChangeCodeLensesEmitter.event;
+	}
+
+	public setEnabled(enabled: false): void {
+		if (this.enabled !== enabled) {
+			this.enabled = enabled;
+			this.onDidChangeCodeLensesEmitter.fire();
+		}
+	}
+
+	public provideCodeLenses(
+		document: vscode.TextDocument,
+		token: vscode.CancellationToken
+	): vscode.ProviderResult<vscode.CodeLens[]> {
+		return [];
+	}
+}
diff --git a/src/goBuild.ts b/src/goBuild.ts
index db5c387..836d53b 100644
--- a/src/goBuild.ts
+++ b/src/goBuild.ts
@@ -1,177 +1,177 @@
-/*---------------------------------------------------------

- * Copyright (C) Microsoft Corporation. All rights reserved.

- * Licensed under the MIT License. See License.txt in the project root for license information.

- *--------------------------------------------------------*/

-

-import path = require('path');

-import vscode = require('vscode');

-import { buildDiagnosticCollection } from './goMain';

-import { isModSupported } from './goModules';

-import { getNonVendorPackages } from './goPackages';

-import { getCurrentGoWorkspaceFromGOPATH } from './goPath';

-import { diagnosticsStatusBarItem, outputChannel } from './goStatus';

-import { getTestFlags } from './testUtils';

-import {

-	getCurrentGoPath,

-	getGoConfig,

-	getModuleCache,

-	getTempFilePath,

-	getToolsEnvVars,

-	getWorkspaceFolderPath,

-	handleDiagnosticErrors,

-	ICheckResult,

-	runTool

-} from './util';

-/**

- * Builds current package or workspace.

- */

-export function buildCode(buildWorkspace?: boolean) {

-	const editor = vscode.window.activeTextEditor;

-	if (!buildWorkspace) {

-		if (!editor) {

-			vscode.window.showInformationMessage('No editor is active, cannot find current package to build');

-			return;

-		}

-		if (editor.document.languageId !== 'go') {

-			vscode.window.showInformationMessage(

-				'File in the active editor is not a Go file, cannot find current package to build'

-			);

-			return;

-		}

-	}

-

-	const documentUri = editor ? editor.document.uri : null;

-	const goConfig = getGoConfig(documentUri);

-

-	outputChannel.clear(); // Ensures stale output from build on save is cleared

-	diagnosticsStatusBarItem.show();

-	diagnosticsStatusBarItem.text = 'Building...';

-

-	isModSupported(documentUri).then((isMod) => {

-		goBuild(documentUri, isMod, goConfig, buildWorkspace)

-			.then((errors) => {

-				handleDiagnosticErrors(editor ? editor.document : null, errors, buildDiagnosticCollection);

-				diagnosticsStatusBarItem.hide();

-			})

-			.catch((err) => {

-				vscode.window.showInformationMessage('Error: ' + err);

-				diagnosticsStatusBarItem.text = 'Build Failed';

-			});

-	});

-}

-

-/**

- * Runs go build -i or go test -i and presents the output in the 'Go' channel and in the diagnostic collections.

- *

- * @param fileUri Document uri.

- * @param isMod Boolean denoting if modules are being used.

- * @param goConfig Configuration for the Go extension.

- * @param buildWorkspace If true builds code in all workspace.

- */

-export async function goBuild(

-	fileUri: vscode.Uri,

-	isMod: boolean,

-	goConfig: vscode.WorkspaceConfiguration,

-	buildWorkspace?: boolean

-): Promise<ICheckResult[]> {

-	epoch++;

-	const closureEpoch = epoch;

-	if (tokenSource) {

-		if (running) {

-			tokenSource.cancel();

-		}

-		tokenSource.dispose();

-	}

-	tokenSource = new vscode.CancellationTokenSource();

-	const updateRunning = () => {

-		if (closureEpoch === epoch) {

-			running = false;

-		}

-	};

-

-	const currentWorkspace = getWorkspaceFolderPath(fileUri);

-	const cwd = buildWorkspace && currentWorkspace ? currentWorkspace : path.dirname(fileUri.fsPath);

-	if (!path.isAbsolute(cwd)) {

-		return Promise.resolve([]);

-	}

-

-	// Skip building if cwd is in the module cache

-	if (isMod && cwd.startsWith(getModuleCache())) {

-		return [];

-	}

-

-	const buildEnv = Object.assign({}, getToolsEnvVars());

-	const tmpPath = getTempFilePath('go-code-check');

-	const isTestFile = fileUri && fileUri.fsPath.endsWith('_test.go');

-	const buildFlags: string[] = isTestFile

-		? getTestFlags(goConfig)

-		: Array.isArray(goConfig['buildFlags'])

-		? [...goConfig['buildFlags']]

-		: [];

-	const buildArgs: string[] = isTestFile ? ['test', '-c'] : ['build'];

-

-	if (goConfig['installDependenciesWhenBuilding'] === true && !isMod) {

-		buildArgs.push('-i');

-		// Remove the -i flag from user as we add it anyway

-		if (buildFlags.indexOf('-i') > -1) {

-			buildFlags.splice(buildFlags.indexOf('-i'), 1);

-		}

-	}

-	buildArgs.push(...buildFlags);

-	if (goConfig['buildTags'] && buildFlags.indexOf('-tags') === -1) {

-		buildArgs.push('-tags');

-		buildArgs.push(goConfig['buildTags']);

-	}

-

-	if (buildWorkspace && currentWorkspace && !isTestFile) {

-		outputChannel.appendLine(`Starting building the current workspace at ${currentWorkspace}`);

-		return getNonVendorPackages(currentWorkspace).then((pkgs) => {

-			running = true;

-			return runTool(

-				buildArgs.concat(Array.from(pkgs.keys())),

-				currentWorkspace,

-				'error',

-				true,

-				null,

-				buildEnv,

-				true,

-				tokenSource.token

-			).then((v) => {

-				updateRunning();

-				return v;

-			});

-		});

-	}

-

-	outputChannel.appendLine(`Starting building the current package at ${cwd}`);

-

-	// Find the right importPath instead of directly using `.`. Fixes https://github.com/Microsoft/vscode-go/issues/846

-	const currentGoWorkspace = getCurrentGoWorkspaceFromGOPATH(getCurrentGoPath(), cwd);

-	let importPath = '.';

-	if (currentGoWorkspace && !isMod) {

-		importPath = cwd.substr(currentGoWorkspace.length + 1);

-	} else {

-		outputChannel.appendLine(

-			`Not able to determine import path of current package by using cwd: ${cwd} and Go workspace: ${currentGoWorkspace}`

-		);

-	}

-

-	running = true;

-	return runTool(

-		buildArgs.concat('-o', tmpPath, importPath),

-		cwd,

-		'error',

-		true,

-		null,

-		buildEnv,

-		true,

-		tokenSource.token

-	).then((v) => {

-		updateRunning();

-		return v;

-	});

-}

-

-let epoch = 0;

-let tokenSource: vscode.CancellationTokenSource;

-let running = false;

+/*---------------------------------------------------------
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------*/
+
+import path = require('path');
+import vscode = require('vscode');
+import { buildDiagnosticCollection } from './goMain';
+import { isModSupported } from './goModules';
+import { getNonVendorPackages } from './goPackages';
+import { getCurrentGoWorkspaceFromGOPATH } from './goPath';
+import { diagnosticsStatusBarItem, outputChannel } from './goStatus';
+import { getTestFlags } from './testUtils';
+import {
+	getCurrentGoPath,
+	getGoConfig,
+	getModuleCache,
+	getTempFilePath,
+	getToolsEnvVars,
+	getWorkspaceFolderPath,
+	handleDiagnosticErrors,
+	ICheckResult,
+	runTool
+} from './util';
+/**
+ * Builds current package or workspace.
+ */
+export function buildCode(buildWorkspace?: boolean) {
+	const editor = vscode.window.activeTextEditor;
+	if (!buildWorkspace) {
+		if (!editor) {
+			vscode.window.showInformationMessage('No editor is active, cannot find current package to build');
+			return;
+		}
+		if (editor.document.languageId !== 'go') {
+			vscode.window.showInformationMessage(
+				'File in the active editor is not a Go file, cannot find current package to build'
+			);
+			return;
+		}
+	}
+
+	const documentUri = editor ? editor.document.uri : null;
+	const goConfig = getGoConfig(documentUri);
+
+	outputChannel.clear(); // Ensures stale output from build on save is cleared
+	diagnosticsStatusBarItem.show();
+	diagnosticsStatusBarItem.text = 'Building...';
+
+	isModSupported(documentUri).then((isMod) => {
+		goBuild(documentUri, isMod, goConfig, buildWorkspace)
+			.then((errors) => {
+				handleDiagnosticErrors(editor ? editor.document : null, errors, buildDiagnosticCollection);
+				diagnosticsStatusBarItem.hide();
+			})
+			.catch((err) => {
+				vscode.window.showInformationMessage('Error: ' + err);
+				diagnosticsStatusBarItem.text = 'Build Failed';
+			});
+	});
+}
+
+/**
+ * Runs go build -i or go test -i and presents the output in the 'Go' channel and in the diagnostic collections.
+ *
+ * @param fileUri Document uri.
+ * @param isMod Boolean denoting if modules are being used.
+ * @param goConfig Configuration for the Go extension.
+ * @param buildWorkspace If true builds code in all workspace.
+ */
+export async function goBuild(
+	fileUri: vscode.Uri,
+	isMod: boolean,
+	goConfig: vscode.WorkspaceConfiguration,
+	buildWorkspace?: boolean
+): Promise<ICheckResult[]> {
+	epoch++;
+	const closureEpoch = epoch;
+	if (tokenSource) {
+		if (running) {
+			tokenSource.cancel();
+		}
+		tokenSource.dispose();
+	}
+	tokenSource = new vscode.CancellationTokenSource();
+	const updateRunning = () => {
+		if (closureEpoch === epoch) {
+			running = false;
+		}
+	};
+
+	const currentWorkspace = getWorkspaceFolderPath(fileUri);
+	const cwd = buildWorkspace && currentWorkspace ? currentWorkspace : path.dirname(fileUri.fsPath);
+	if (!path.isAbsolute(cwd)) {
+		return Promise.resolve([]);
+	}
+
+	// Skip building if cwd is in the module cache
+	if (isMod && cwd.startsWith(getModuleCache())) {
+		return [];
+	}
+
+	const buildEnv = Object.assign({}, getToolsEnvVars());
+	const tmpPath = getTempFilePath('go-code-check');
+	const isTestFile = fileUri && fileUri.fsPath.endsWith('_test.go');
+	const buildFlags: string[] = isTestFile
+		? getTestFlags(goConfig)
+		: Array.isArray(goConfig['buildFlags'])
+		? [...goConfig['buildFlags']]
+		: [];
+	const buildArgs: string[] = isTestFile ? ['test', '-c'] : ['build'];
+
+	if (goConfig['installDependenciesWhenBuilding'] === true && !isMod) {
+		buildArgs.push('-i');
+		// Remove the -i flag from user as we add it anyway
+		if (buildFlags.indexOf('-i') > -1) {
+			buildFlags.splice(buildFlags.indexOf('-i'), 1);
+		}
+	}
+	buildArgs.push(...buildFlags);
+	if (goConfig['buildTags'] && buildFlags.indexOf('-tags') === -1) {
+		buildArgs.push('-tags');
+		buildArgs.push(goConfig['buildTags']);
+	}
+
+	if (buildWorkspace && currentWorkspace && !isTestFile) {
+		outputChannel.appendLine(`Starting building the current workspace at ${currentWorkspace}`);
+		return getNonVendorPackages(currentWorkspace).then((pkgs) => {
+			running = true;
+			return runTool(
+				buildArgs.concat(Array.from(pkgs.keys())),
+				currentWorkspace,
+				'error',
+				true,
+				null,
+				buildEnv,
+				true,
+				tokenSource.token
+			).then((v) => {
+				updateRunning();
+				return v;
+			});
+		});
+	}
+
+	outputChannel.appendLine(`Starting building the current package at ${cwd}`);
+
+	// Find the right importPath instead of directly using `.`. Fixes https://github.com/Microsoft/vscode-go/issues/846
+	const currentGoWorkspace = getCurrentGoWorkspaceFromGOPATH(getCurrentGoPath(), cwd);
+	let importPath = '.';
+	if (currentGoWorkspace && !isMod) {
+		importPath = cwd.substr(currentGoWorkspace.length + 1);
+	} else {
+		outputChannel.appendLine(
+			`Not able to determine import path of current package by using cwd: ${cwd} and Go workspace: ${currentGoWorkspace}`
+		);
+	}
+
+	running = true;
+	return runTool(
+		buildArgs.concat('-o', tmpPath, importPath),
+		cwd,
+		'error',
+		true,
+		null,
+		buildEnv,
+		true,
+		tokenSource.token
+	).then((v) => {
+		updateRunning();
+		return v;
+	});
+}
+
+let epoch = 0;
+let tokenSource: vscode.CancellationTokenSource;
+let running = false;
diff --git a/src/goCover.ts b/src/goCover.ts
index 2ad8e54..d05b9c4 100644
--- a/src/goCover.ts
+++ b/src/goCover.ts
@@ -29,6 +29,10 @@
 	coveredGutterStyle: string;
 	uncoveredGutterStyle: string;
 };
+// a list of modified, unsaved go files with actual code edits (rather than comment edits)
+let modifiedFiles: {
+	[key: string]: boolean;
+};
 
 /**
  * Initializes the decorators used for Code coverage.
@@ -288,11 +292,32 @@
 }
 
 /**
- * Listener for change in the editor.
- * A change in a Go file means the coverage data is stale. Therefore it should be cleared.
+ * Listener for file save that clears potential stale coverage data.
+ * Local cache tracks files with changes outside of comments to determine
+ * files for which the save event can cause stale coverage data.
+ * @param e TextDocument
+ */
+export function removeCodeCoverageOnFileSave(e: vscode.TextDocument) {
+	if (e.languageId !== 'go' || !isCoverageApplied || !e.isDirty) {
+		return;
+	}
+
+	if (vscode.window.visibleTextEditors.every((editor) => editor.document !== e)) {
+		return;
+	}
+
+	if (modifiedFiles[e.fileName]) {
+		clearCoverage();
+		modifiedFiles = {}; // reset the list of modified files
+	}
+}
+
+/**
+ * Listener for file change that tracks files with changes outside of comments
+ * to determine files for which an eventual save can cause stale coverage data.
  * @param e TextDocumentChangeEvent
  */
-export function removeCodeCoverageOnFileChange(e: vscode.TextDocumentChangeEvent) {
+export function trackCodeCoverageRemovalOnFileChange(e: vscode.TextDocumentChangeEvent) {
 	if (e.document.languageId !== 'go' || !e.contentChanges.length || !isCoverageApplied) {
 		return;
 	}
@@ -305,7 +330,7 @@
 		return;
 	}
 
-	clearCoverage();
+	modifiedFiles[e.document.fileName] = true;
 }
 
 /**
diff --git a/src/goDebugConfiguration.ts b/src/goDebugConfiguration.ts
index 7e145e4..db1c20f 100644
--- a/src/goDebugConfiguration.ts
+++ b/src/goDebugConfiguration.ts
@@ -1,146 +1,146 @@
-/*---------------------------------------------------------

- * Copyright (C) Microsoft Corporation. All rights reserved.

- * Licensed under the MIT License. See License.txt in the project root for license information.

- *--------------------------------------------------------*/

-

-'use strict';

-

-import path = require('path');

-import vscode = require('vscode');

-import { promptForMissingTool } from './goInstallTools';

-import { packagePathToGoModPathMap } from './goModules';

-import { getFromGlobalState, updateGlobalState } from './stateUtils';

-import { sendTelemetryEventForDebugConfiguration } from './telemetry';

-import { getBinPath, getCurrentGoPath, getGoConfig, getToolsEnvVars } from './util';

-

-export class GoDebugConfigurationProvider implements vscode.DebugConfigurationProvider {

-	public provideDebugConfigurations(

-		folder: vscode.WorkspaceFolder | undefined,

-		token?: vscode.CancellationToken

-	): vscode.DebugConfiguration[] {

-		return [

-			{

-				name: 'Launch',

-				type: 'go',

-				request: 'launch',

-				mode: 'auto',

-				program: '${fileDirname}',

-				env: {},

-				args: []

-			}

-		];

-	}

-

-	public resolveDebugConfiguration?(

-		folder: vscode.WorkspaceFolder | undefined,

-		debugConfiguration: vscode.DebugConfiguration,

-		token?: vscode.CancellationToken

-	): vscode.DebugConfiguration {

-		if (debugConfiguration) {

-			sendTelemetryEventForDebugConfiguration(debugConfiguration);

-		}

-

-		const activeEditor = vscode.window.activeTextEditor;

-		if (!debugConfiguration || !debugConfiguration.request) {

-			// if 'request' is missing interpret this as a missing launch.json

-			if (!activeEditor || activeEditor.document.languageId !== 'go') {

-				return;

-			}

-

-			debugConfiguration = Object.assign(debugConfiguration || {}, {

-				name: 'Launch',

-				type: 'go',

-				request: 'launch',

-				mode: 'auto',

-				program: path.dirname(activeEditor.document.fileName)  // matches ${fileDirname}

-			});

-		}

-

-		debugConfiguration['packagePathToGoModPathMap'] = packagePathToGoModPathMap;

-

-		const gopath = getCurrentGoPath(folder ? folder.uri : undefined);

-		if (!debugConfiguration['env']) {

-			debugConfiguration['env'] = { GOPATH: gopath };

-		} else if (!debugConfiguration['env']['GOPATH']) {

-			debugConfiguration['env']['GOPATH'] = gopath;

-		}

-

-		const goConfig = getGoConfig(folder && folder.uri);

-		const goToolsEnvVars = getToolsEnvVars();

-		Object.keys(goToolsEnvVars).forEach((key) => {

-			if (!debugConfiguration['env'].hasOwnProperty(key)) {

-				debugConfiguration['env'][key] = goToolsEnvVars[key];

-			}

-		});

-

-		const dlvConfig = goConfig.get<any>('delveConfig');

-		let useApiV1 = false;

-		if (debugConfiguration.hasOwnProperty('useApiV1')) {

-			useApiV1 = debugConfiguration['useApiV1'] === true;

-		} else if (dlvConfig.hasOwnProperty('useApiV1')) {

-			useApiV1 = dlvConfig['useApiV1'] === true;

-		}

-		if (useApiV1) {

-			debugConfiguration['apiVersion'] = 1;

-		}

-		if (!debugConfiguration.hasOwnProperty('apiVersion') && dlvConfig.hasOwnProperty('apiVersion')) {

-			debugConfiguration['apiVersion'] = dlvConfig['apiVersion'];

-		}

-		if (!debugConfiguration.hasOwnProperty('dlvLoadConfig') && dlvConfig.hasOwnProperty('dlvLoadConfig')) {

-			debugConfiguration['dlvLoadConfig'] = dlvConfig['dlvLoadConfig'];

-		}

-		if (

-			!debugConfiguration.hasOwnProperty('showGlobalVariables') &&

-			dlvConfig.hasOwnProperty('showGlobalVariables')

-		) {

-			debugConfiguration['showGlobalVariables'] = dlvConfig['showGlobalVariables'];

-		}

-		if (debugConfiguration.request === 'attach' && !debugConfiguration['cwd']) {

-			debugConfiguration['cwd'] = '${workspaceFolder}';

-		}

-

-		debugConfiguration['dlvToolPath'] = getBinPath('dlv');

-		if (!path.isAbsolute(debugConfiguration['dlvToolPath'])) {

-			promptForMissingTool('dlv');

-			return;

-		}

-

-		if (debugConfiguration['mode'] === 'auto') {

-			debugConfiguration['mode'] =

-				activeEditor && activeEditor.document.fileName.endsWith('_test.go') ? 'test' : 'debug';

-		}

-

-		if (debugConfiguration.request === 'launch' && debugConfiguration['mode'] === 'remote') {

-			this.showWarning(

-				'ignoreDebugLaunchRemoteWarning',

-				`Request type of 'launch' with mode 'remote' is deprecated, please use request type 'attach' with mode 'remote' instead.`

-			);

-		}

-

-		if (

-			debugConfiguration.request === 'attach' &&

-			debugConfiguration['mode'] === 'remote' &&

-			debugConfiguration['program']

-		) {

-			this.showWarning(

-				'ignoreUsingRemotePathAndProgramWarning',

-				`Request type of 'attach' with mode 'remote' does not work with 'program' attribute, please use 'cwd' attribute instead.`

-			);

-		}

-		return debugConfiguration;

-	}

-

-	private showWarning(ignoreWarningKey: string, warningMessage: string) {

-		const ignoreWarning = getFromGlobalState(ignoreWarningKey);

-		if (ignoreWarning) {

-			return;

-		}

-

-		const neverAgain = { title: `Don't Show Again` };

-		vscode.window.showWarningMessage(warningMessage, neverAgain).then((result) => {

-			if (result === neverAgain) {

-				updateGlobalState(ignoreWarningKey, true);

-			}

-		});

-	}

-}

+/*---------------------------------------------------------
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------*/
+
+'use strict';
+
+import path = require('path');
+import vscode = require('vscode');
+import { promptForMissingTool } from './goInstallTools';
+import { packagePathToGoModPathMap } from './goModules';
+import { getFromGlobalState, updateGlobalState } from './stateUtils';
+import { sendTelemetryEventForDebugConfiguration } from './telemetry';
+import { getBinPath, getCurrentGoPath, getGoConfig, getToolsEnvVars } from './util';
+
+export class GoDebugConfigurationProvider implements vscode.DebugConfigurationProvider {
+	public provideDebugConfigurations(
+		folder: vscode.WorkspaceFolder | undefined,
+		token?: vscode.CancellationToken
+	): vscode.DebugConfiguration[] {
+		return [
+			{
+				name: 'Launch',
+				type: 'go',
+				request: 'launch',
+				mode: 'auto',
+				program: '${fileDirname}',
+				env: {},
+				args: []
+			}
+		];
+	}
+
+	public resolveDebugConfiguration?(
+		folder: vscode.WorkspaceFolder | undefined,
+		debugConfiguration: vscode.DebugConfiguration,
+		token?: vscode.CancellationToken
+	): vscode.DebugConfiguration {
+		if (debugConfiguration) {
+			sendTelemetryEventForDebugConfiguration(debugConfiguration);
+		}
+
+		const activeEditor = vscode.window.activeTextEditor;
+		if (!debugConfiguration || !debugConfiguration.request) {
+			// if 'request' is missing interpret this as a missing launch.json
+			if (!activeEditor || activeEditor.document.languageId !== 'go') {
+				return;
+			}
+
+			debugConfiguration = Object.assign(debugConfiguration || {}, {
+				name: 'Launch',
+				type: 'go',
+				request: 'launch',
+				mode: 'auto',
+				program: path.dirname(activeEditor.document.fileName) // matches ${fileDirname}
+			});
+		}
+
+		debugConfiguration['packagePathToGoModPathMap'] = packagePathToGoModPathMap;
+
+		const gopath = getCurrentGoPath(folder ? folder.uri : undefined);
+		if (!debugConfiguration['env']) {
+			debugConfiguration['env'] = { GOPATH: gopath };
+		} else if (!debugConfiguration['env']['GOPATH']) {
+			debugConfiguration['env']['GOPATH'] = gopath;
+		}
+
+		const goConfig = getGoConfig(folder && folder.uri);
+		const goToolsEnvVars = getToolsEnvVars();
+		Object.keys(goToolsEnvVars).forEach((key) => {
+			if (!debugConfiguration['env'].hasOwnProperty(key)) {
+				debugConfiguration['env'][key] = goToolsEnvVars[key];
+			}
+		});
+
+		const dlvConfig = goConfig.get<any>('delveConfig');
+		let useApiV1 = false;
+		if (debugConfiguration.hasOwnProperty('useApiV1')) {
+			useApiV1 = debugConfiguration['useApiV1'] === true;
+		} else if (dlvConfig.hasOwnProperty('useApiV1')) {
+			useApiV1 = dlvConfig['useApiV1'] === true;
+		}
+		if (useApiV1) {
+			debugConfiguration['apiVersion'] = 1;
+		}
+		if (!debugConfiguration.hasOwnProperty('apiVersion') && dlvConfig.hasOwnProperty('apiVersion')) {
+			debugConfiguration['apiVersion'] = dlvConfig['apiVersion'];
+		}
+		if (!debugConfiguration.hasOwnProperty('dlvLoadConfig') && dlvConfig.hasOwnProperty('dlvLoadConfig')) {
+			debugConfiguration['dlvLoadConfig'] = dlvConfig['dlvLoadConfig'];
+		}
+		if (
+			!debugConfiguration.hasOwnProperty('showGlobalVariables') &&
+			dlvConfig.hasOwnProperty('showGlobalVariables')
+		) {
+			debugConfiguration['showGlobalVariables'] = dlvConfig['showGlobalVariables'];
+		}
+		if (debugConfiguration.request === 'attach' && !debugConfiguration['cwd']) {
+			debugConfiguration['cwd'] = '${workspaceFolder}';
+		}
+
+		debugConfiguration['dlvToolPath'] = getBinPath('dlv');
+		if (!path.isAbsolute(debugConfiguration['dlvToolPath'])) {
+			promptForMissingTool('dlv');
+			return;
+		}
+
+		if (debugConfiguration['mode'] === 'auto') {
+			debugConfiguration['mode'] =
+				activeEditor && activeEditor.document.fileName.endsWith('_test.go') ? 'test' : 'debug';
+		}
+
+		if (debugConfiguration.request === 'launch' && debugConfiguration['mode'] === 'remote') {
+			this.showWarning(
+				'ignoreDebugLaunchRemoteWarning',
+				`Request type of 'launch' with mode 'remote' is deprecated, please use request type 'attach' with mode 'remote' instead.`
+			);
+		}
+
+		if (
+			debugConfiguration.request === 'attach' &&
+			debugConfiguration['mode'] === 'remote' &&
+			debugConfiguration['program']
+		) {
+			this.showWarning(
+				'ignoreUsingRemotePathAndProgramWarning',
+				`Request type of 'attach' with mode 'remote' does not work with 'program' attribute, please use 'cwd' attribute instead.`
+			);
+		}
+		return debugConfiguration;
+	}
+
+	private showWarning(ignoreWarningKey: string, warningMessage: string) {
+		const ignoreWarning = getFromGlobalState(ignoreWarningKey);
+		if (ignoreWarning) {
+			return;
+		}
+
+		const neverAgain = { title: `Don't Show Again` };
+		vscode.window.showWarningMessage(warningMessage, neverAgain).then((result) => {
+			if (result === neverAgain) {
+				updateGlobalState(ignoreWarningKey, true);
+			}
+		});
+	}
+}
diff --git a/src/goFillStruct.ts b/src/goFillStruct.ts
index dddc3eb..9ec33e1 100644
--- a/src/goFillStruct.ts
+++ b/src/goFillStruct.ts
@@ -8,7 +8,7 @@
 import cp = require('child_process');
 import vscode = require('vscode');
 import { promptForMissingTool } from './goInstallTools';
-import { byteOffsetAt, getBinPath, getFileArchive, getToolsEnvVars } from './util';
+import { byteOffsetAt, getBinPath, getFileArchive, getToolsEnvVars, makeMemoizedByteOffsetConverter } from './util';
 
 // Interface for the output from fillstruct
 interface GoFillStructOutput {
@@ -78,14 +78,15 @@
 				}
 
 				const indent = '\t'.repeat(tabsCount);
+				const offsetConverter = makeMemoizedByteOffsetConverter(Buffer.from(editor.document.getText()));
 
 				editor
 					.edit((editBuilder) => {
 						output.forEach((structToFill) => {
 							const out = structToFill.code.replace(/\n/g, '\n' + indent);
 							const rangeToReplace = new vscode.Range(
-								editor.document.positionAt(structToFill.start),
-								editor.document.positionAt(structToFill.end)
+								editor.document.positionAt(offsetConverter(structToFill.start)),
+								editor.document.positionAt(offsetConverter(structToFill.end))
 							);
 							editBuilder.replace(rangeToReplace, out);
 						});
diff --git a/src/goInstall.ts b/src/goInstall.ts
index b4b0101..be7ff9f 100644
--- a/src/goInstall.ts
+++ b/src/goInstall.ts
@@ -1,64 +1,64 @@
-/*---------------------------------------------------------

- * Copyright (C) Microsoft Corporation. All rights reserved.

- * Licensed under the MIT License. See License.txt in the project root for license information.

- *--------------------------------------------------------*/

-

-import cp = require('child_process');

-import path = require('path');

-import vscode = require('vscode');

-import { isModSupported } from './goModules';

-import { envPath, getCurrentGoWorkspaceFromGOPATH } from './goPath';

-import { outputChannel } from './goStatus';

-import { getBinPath, getCurrentGoPath, getGoConfig, getModuleCache, getToolsEnvVars } from './util';

-

-export async function installCurrentPackage(): Promise<void> {

-	const editor = vscode.window.activeTextEditor;

-	if (!editor) {

-		vscode.window.showInformationMessage('No editor is active, cannot find current package to install');

-		return;

-	}

-	if (editor.document.languageId !== 'go') {

-		vscode.window.showInformationMessage(

-			'File in the active editor is not a Go file, cannot find current package to install'

-		);

-		return;

-	}

-

-	const goRuntimePath = getBinPath('go');

-	if (!goRuntimePath) {

-		vscode.window.showErrorMessage(

-			`Failed to run "go install" to install the package as the "go" binary cannot be found in either GOROOT(${process.env['GOROOT']}) or PATH(${envPath})`

-		);

-		return;

-	}

-

-	const env = Object.assign({}, getToolsEnvVars());

-	const cwd = path.dirname(editor.document.uri.fsPath);

-	const isMod = await isModSupported(editor.document.uri);

-

-	// Skip installing if cwd is in the module cache

-	if (isMod && cwd.startsWith(getModuleCache())) {

-		return;

-	}

-

-	const goConfig = getGoConfig();

-	const buildFlags = goConfig['buildFlags'] || [];

-	const args = ['install', ...buildFlags];

-

-	if (goConfig['buildTags'] && buildFlags.indexOf('-tags') === -1) {

-		args.push('-tags', goConfig['buildTags']);

-	}

-

-	// Find the right importPath instead of directly using `.`. Fixes https://github.com/Microsoft/vscode-go/issues/846

-	const currentGoWorkspace = getCurrentGoWorkspaceFromGOPATH(getCurrentGoPath(), cwd);

-	const importPath = currentGoWorkspace && !isMod ? cwd.substr(currentGoWorkspace.length + 1) : '.';

-	args.push(importPath);

-

-	outputChannel.clear();

-	outputChannel.show();

-	outputChannel.appendLine(`Installing ${importPath === '.' ? 'current package' : importPath}`);

-

-	cp.execFile(goRuntimePath, args, { env, cwd }, (err, stdout, stderr) => {

-		outputChannel.appendLine(err ? `Installation failed: ${stderr}` : `Installation successful`);

-	});

-}

+/*---------------------------------------------------------
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------*/
+
+import cp = require('child_process');
+import path = require('path');
+import vscode = require('vscode');
+import { isModSupported } from './goModules';
+import { envPath, getCurrentGoWorkspaceFromGOPATH } from './goPath';
+import { outputChannel } from './goStatus';
+import { getBinPath, getCurrentGoPath, getGoConfig, getModuleCache, getToolsEnvVars } from './util';
+
+export async function installCurrentPackage(): Promise<void> {
+	const editor = vscode.window.activeTextEditor;
+	if (!editor) {
+		vscode.window.showInformationMessage('No editor is active, cannot find current package to install');
+		return;
+	}
+	if (editor.document.languageId !== 'go') {
+		vscode.window.showInformationMessage(
+			'File in the active editor is not a Go file, cannot find current package to install'
+		);
+		return;
+	}
+
+	const goRuntimePath = getBinPath('go');
+	if (!goRuntimePath) {
+		vscode.window.showErrorMessage(
+			`Failed to run "go install" to install the package as the "go" binary cannot be found in either GOROOT(${process.env['GOROOT']}) or PATH(${envPath})`
+		);
+		return;
+	}
+
+	const env = Object.assign({}, getToolsEnvVars());
+	const cwd = path.dirname(editor.document.uri.fsPath);
+	const isMod = await isModSupported(editor.document.uri);
+
+	// Skip installing if cwd is in the module cache
+	if (isMod && cwd.startsWith(getModuleCache())) {
+		return;
+	}
+
+	const goConfig = getGoConfig();
+	const buildFlags = goConfig['buildFlags'] || [];
+	const args = ['install', ...buildFlags];
+
+	if (goConfig['buildTags'] && buildFlags.indexOf('-tags') === -1) {
+		args.push('-tags', goConfig['buildTags']);
+	}
+
+	// Find the right importPath instead of directly using `.`. Fixes https://github.com/Microsoft/vscode-go/issues/846
+	const currentGoWorkspace = getCurrentGoWorkspaceFromGOPATH(getCurrentGoPath(), cwd);
+	const importPath = currentGoWorkspace && !isMod ? cwd.substr(currentGoWorkspace.length + 1) : '.';
+	args.push(importPath);
+
+	outputChannel.clear();
+	outputChannel.show();
+	outputChannel.appendLine(`Installing ${importPath === '.' ? 'current package' : importPath}`);
+
+	cp.execFile(goRuntimePath, args, { env, cwd }, (err, stdout, stderr) => {
+		outputChannel.appendLine(err ? `Installation failed: ${stderr}` : `Installation successful`);
+	});
+}
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index f82bb8f..60ccce9 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -375,7 +375,7 @@
 
 export async function promptForUpdatingTool(toolName: string, newVersion?: SemVer) {
 	const tool = getTool(toolName);
-	const toolVersion = {...tool, version: newVersion}; // ToolWithVersion
+	const toolVersion = { ...tool, version: newVersion }; // ToolWithVersion
 
 	// If user has declined to update, then don't prompt.
 	if (containsTool(declinedUpdates, tool)) {
diff --git a/src/goLanguageServer.ts b/src/goLanguageServer.ts
index 5252b60..909ac7a 100644
--- a/src/goLanguageServer.ts
+++ b/src/goLanguageServer.ts
@@ -38,7 +38,7 @@
 import { GoWorkspaceSymbolProvider } from './goSymbol';
 import { getTool, Tool } from './goTools';
 import { GoTypeDefinitionProvider } from './goTypeDefinition';
-import { getBinPath, getCurrentGoPath, getGoConfig, getToolsEnvVars, isForNightly } from './util';
+import { getBinPath, getCurrentGoPath, getGoConfig, getToolsEnvVars } from './util';
 
 interface LanguageServerConfig {
 	enabled: boolean;
@@ -250,7 +250,7 @@
 			// TODO: We should have configs that match these names.
 			// Ultimately, we should have a centralized language server config rather than separate fields.
 			diagnostics: goConfig['languageServerExperimentalFeatures']['diagnostics'],
-			documentLink: goConfig['languageServerExperimentalFeatures']['documentLink'],
+			documentLink: goConfig['languageServerExperimentalFeatures']['documentLink']
 		},
 		checkForUpdates: goConfig['useGoProxyToCheckForToolUpdates']
 	};
@@ -335,6 +335,7 @@
 	vscode.workspace.onDidChangeTextDocument(parseLiveFile, null, ctx.subscriptions);
 }
 
+const acceptGoplsPrerelease = true;  // For nightly, we accept the prerelease version.
 const defaultLatestVersion = semver.coerce('0.3.1');
 const defaultLatestVersionTime = moment('2020-02-04', 'YYYY-MM-DD');
 async function shouldUpdateLanguageServer(
@@ -356,7 +357,7 @@
 	}
 
 	// Get the latest gopls version. If it is for nightly, using the prereleased version is ok.
-	let latestVersion = makeProxyCall ? await latestGopls(tool, isForNightly) : defaultLatestVersion;
+	let latestVersion = makeProxyCall ? await latestGopls(tool) : defaultLatestVersion;
 
 	// If we failed to get the gopls version, pick the one we know to be latest at the time of this extension's last update
 	if (!latestVersion) {
@@ -438,7 +439,7 @@
 	return time;
 }
 
-async function latestGopls(tool: Tool, includePrerelease: boolean): Promise<semver.SemVer> {
+async function latestGopls(tool: Tool): Promise<semver.SemVer> {
 	// If the user has a version of gopls that we understand,
 	// ask the proxy for the latest version, and if the user's version is older,
 	// prompt them to update.
@@ -460,8 +461,8 @@
 	}
 	versions.sort(semver.rcompare);
 
-	if (includePrerelease) {
-		return versions[0];  // The first one in the prerelease.
+	if (acceptGoplsPrerelease) {
+		return versions[0]; // The first one (newest one).
 	}
 	// The first version in the sorted list without a prerelease tag.
 	return versions.find((version) => !version.prerelease || !version.prerelease.length);
diff --git a/src/goMain.ts b/src/goMain.ts
index 52701ad..b5ac805 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -15,8 +15,9 @@
 	applyCodeCoverage,
 	applyCodeCoverageToAllEditors,
 	initCoverageDecorators,
-	removeCodeCoverageOnFileChange,
+	removeCodeCoverageOnFileSave,
 	toggleCoverageCurrentPackage,
+	trackCodeCoverageRemovalOnFileChange,
 	updateCodeCoverageDecorators
 } from './goCover';
 import { GoDebugConfigurationProvider } from './goDebugConfiguration';
@@ -574,6 +575,7 @@
 }
 
 function addOnSaveTextDocumentListeners(ctx: vscode.ExtensionContext) {
+	vscode.workspace.onDidSaveTextDocument(removeCodeCoverageOnFileSave, null, ctx.subscriptions);
 	vscode.workspace.onDidSaveTextDocument(
 		(document) => {
 			if (document.languageId !== 'go') {
@@ -606,7 +608,7 @@
 }
 
 function addOnChangeTextDocumentListeners(ctx: vscode.ExtensionContext) {
-	vscode.workspace.onDidChangeTextDocument(removeCodeCoverageOnFileChange, null, ctx.subscriptions);
+	vscode.workspace.onDidChangeTextDocument(trackCodeCoverageRemovalOnFileChange, null, ctx.subscriptions);
 	vscode.workspace.onDidChangeTextDocument(removeTestStatus, null, ctx.subscriptions);
 	vscode.workspace.onDidChangeTextDocument(notifyIfGeneratedFile, ctx, ctx.subscriptions);
 }
diff --git a/src/goPackages.ts b/src/goPackages.ts
index c840d50..1db3358 100644
--- a/src/goPackages.ts
+++ b/src/goPackages.ts
@@ -279,10 +279,7 @@
 		});
 
 		childProcess.on('close', async (status) => {
-			const lines = chunks
-				.join('')
-				.toString()
-				.split('\n');
+			const lines = chunks.join('').toString().split('\n');
 			const result = new Map<string, string>();
 
 			const version = await getGoVersion();
diff --git a/src/goVet.ts b/src/goVet.ts
index cd96c3e..72e3de3 100644
--- a/src/goVet.ts
+++ b/src/goVet.ts
@@ -1,125 +1,125 @@
-/*---------------------------------------------------------

- * Copyright (C) Microsoft Corporation. All rights reserved.

- * Licensed under the MIT License. See License.txt in the project root for license information.

- *--------------------------------------------------------*/

-

-import path = require('path');

-import vscode = require('vscode');

-import { vetDiagnosticCollection } from './goMain';

-import { diagnosticsStatusBarItem, outputChannel } from './goStatus';

-import {

-	getGoConfig,

-	getGoVersion,

-	getToolsEnvVars,

-	getWorkspaceFolderPath,

-	handleDiagnosticErrors,

-	ICheckResult,

-	resolvePath,

-	runTool

-} from './util';

-

-/**

- * Runs go vet in the current package or workspace.

- */

-export function vetCode(vetWorkspace?: boolean) {

-	const editor = vscode.window.activeTextEditor;

-	if (!editor && !vetWorkspace) {

-		vscode.window.showInformationMessage('No editor is active, cannot find current package to vet');

-		return;

-	}

-	if (editor.document.languageId !== 'go' && !vetWorkspace) {

-		vscode.window.showInformationMessage(

-			'File in the active editor is not a Go file, cannot find current package to vet'

-		);

-		return;

-	}

-

-	const documentUri = editor ? editor.document.uri : null;

-	const goConfig = getGoConfig(documentUri);

-

-	outputChannel.clear(); // Ensures stale output from vet on save is cleared

-	diagnosticsStatusBarItem.show();

-	diagnosticsStatusBarItem.text = 'Vetting...';

-

-	goVet(documentUri, goConfig, vetWorkspace)

-		.then((warnings) => {

-			handleDiagnosticErrors(editor ? editor.document : null, warnings, vetDiagnosticCollection);

-			diagnosticsStatusBarItem.hide();

-		})

-		.catch((err) => {

-			vscode.window.showInformationMessage('Error: ' + err);

-			diagnosticsStatusBarItem.text = 'Vetting Failed';

-		});

-}

-

-/**

- * Runs go vet or go tool vet and presents the output in the 'Go' channel and in the diagnostic collections.

- *

- * @param fileUri Document uri.

- * @param goConfig Configuration for the Go extension.

- * @param vetWorkspace If true vets code in all workspace.

- */

-export async function goVet(

-	fileUri: vscode.Uri,

-	goConfig: vscode.WorkspaceConfiguration,

-	vetWorkspace?: boolean

-): Promise<ICheckResult[]> {

-	epoch++;

-	const closureEpoch = epoch;

-	if (tokenSource) {

-		if (running) {

-			tokenSource.cancel();

-		}

-		tokenSource.dispose();

-	}

-	tokenSource = new vscode.CancellationTokenSource();

-

-	const currentWorkspace = getWorkspaceFolderPath(fileUri);

-	const cwd = vetWorkspace && currentWorkspace ? currentWorkspace : path.dirname(fileUri.fsPath);

-	if (!path.isAbsolute(cwd)) {

-		return Promise.resolve([]);

-	}

-

-	const vetFlags: string[] = goConfig['vetFlags'] || [];

-	const vetEnv = Object.assign({}, getToolsEnvVars());

-	const args: string[] = [];

-

-	vetFlags.forEach((flag) => {

-		if (flag.startsWith('--vettool=') || flag.startsWith('-vettool=')) {

-			let vetToolPath = flag.substr(flag.indexOf('=') + 1).trim();

-			if (!vetToolPath) {

-				return;

-			}

-			vetToolPath = resolvePath(vetToolPath);

-			args.push(`${flag.substr(0, flag.indexOf('=') + 1)}${vetToolPath}`);

-			return;

-		}

-		args.push(flag);

-	});

-

-	const goVersion = await getGoVersion();

-	const tagsArg = [];

-	if (goConfig['buildTags'] && vetFlags.indexOf('-tags') === -1) {

-		tagsArg.push('-tags');

-		tagsArg.push(goConfig['buildTags']);

-	}

-

-	let vetArgs = ['vet', ...args, ...tagsArg, vetWorkspace ? './...' : '.'];

-	if (goVersion.lt('1.10') && args.length) {

-		vetArgs = ['tool', 'vet', ...args, ...tagsArg, '.'];

-	}

-

-	outputChannel.appendLine(`Starting "go vet" under the folder ${cwd}`);

-

-	running = true;

-	return runTool(vetArgs, cwd, 'warning', true, null, vetEnv, false, tokenSource.token).then((result) => {

-		if (closureEpoch === epoch) {

-			running = false;

-		}

-		return result;

-	});

-}

-

-let epoch = 0;

-let tokenSource: vscode.CancellationTokenSource;

-let running = false;

+/*---------------------------------------------------------
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------*/
+
+import path = require('path');
+import vscode = require('vscode');
+import { vetDiagnosticCollection } from './goMain';
+import { diagnosticsStatusBarItem, outputChannel } from './goStatus';
+import {
+	getGoConfig,
+	getGoVersion,
+	getToolsEnvVars,
+	getWorkspaceFolderPath,
+	handleDiagnosticErrors,
+	ICheckResult,
+	resolvePath,
+	runTool
+} from './util';
+
+/**
+ * Runs go vet in the current package or workspace.
+ */
+export function vetCode(vetWorkspace?: boolean) {
+	const editor = vscode.window.activeTextEditor;
+	if (!editor && !vetWorkspace) {
+		vscode.window.showInformationMessage('No editor is active, cannot find current package to vet');
+		return;
+	}
+	if (editor.document.languageId !== 'go' && !vetWorkspace) {
+		vscode.window.showInformationMessage(
+			'File in the active editor is not a Go file, cannot find current package to vet'
+		);
+		return;
+	}
+
+	const documentUri = editor ? editor.document.uri : null;
+	const goConfig = getGoConfig(documentUri);
+
+	outputChannel.clear(); // Ensures stale output from vet on save is cleared
+	diagnosticsStatusBarItem.show();
+	diagnosticsStatusBarItem.text = 'Vetting...';
+
+	goVet(documentUri, goConfig, vetWorkspace)
+		.then((warnings) => {
+			handleDiagnosticErrors(editor ? editor.document : null, warnings, vetDiagnosticCollection);
+			diagnosticsStatusBarItem.hide();
+		})
+		.catch((err) => {
+			vscode.window.showInformationMessage('Error: ' + err);
+			diagnosticsStatusBarItem.text = 'Vetting Failed';
+		});
+}
+
+/**
+ * Runs go vet or go tool vet and presents the output in the 'Go' channel and in the diagnostic collections.
+ *
+ * @param fileUri Document uri.
+ * @param goConfig Configuration for the Go extension.
+ * @param vetWorkspace If true vets code in all workspace.
+ */
+export async function goVet(
+	fileUri: vscode.Uri,
+	goConfig: vscode.WorkspaceConfiguration,
+	vetWorkspace?: boolean
+): Promise<ICheckResult[]> {
+	epoch++;
+	const closureEpoch = epoch;
+	if (tokenSource) {
+		if (running) {
+			tokenSource.cancel();
+		}
+		tokenSource.dispose();
+	}
+	tokenSource = new vscode.CancellationTokenSource();
+
+	const currentWorkspace = getWorkspaceFolderPath(fileUri);
+	const cwd = vetWorkspace && currentWorkspace ? currentWorkspace : path.dirname(fileUri.fsPath);
+	if (!path.isAbsolute(cwd)) {
+		return Promise.resolve([]);
+	}
+
+	const vetFlags: string[] = goConfig['vetFlags'] || [];
+	const vetEnv = Object.assign({}, getToolsEnvVars());
+	const args: string[] = [];
+
+	vetFlags.forEach((flag) => {
+		if (flag.startsWith('--vettool=') || flag.startsWith('-vettool=')) {
+			let vetToolPath = flag.substr(flag.indexOf('=') + 1).trim();
+			if (!vetToolPath) {
+				return;
+			}
+			vetToolPath = resolvePath(vetToolPath);
+			args.push(`${flag.substr(0, flag.indexOf('=') + 1)}${vetToolPath}`);
+			return;
+		}
+		args.push(flag);
+	});
+
+	const goVersion = await getGoVersion();
+	const tagsArg = [];
+	if (goConfig['buildTags'] && vetFlags.indexOf('-tags') === -1) {
+		tagsArg.push('-tags');
+		tagsArg.push(goConfig['buildTags']);
+	}
+
+	let vetArgs = ['vet', ...args, ...tagsArg, vetWorkspace ? './...' : '.'];
+	if (goVersion.lt('1.10') && args.length) {
+		vetArgs = ['tool', 'vet', ...args, ...tagsArg, '.'];
+	}
+
+	outputChannel.appendLine(`Starting "go vet" under the folder ${cwd}`);
+
+	running = true;
+	return runTool(vetArgs, cwd, 'warning', true, null, vetEnv, false, tokenSource.token).then((result) => {
+		if (closureEpoch === epoch) {
+			running = false;
+		}
+		return result;
+	});
+}
+
+let epoch = 0;
+let tokenSource: vscode.CancellationTokenSource;
+let running = false;
diff --git a/src/testUtils.ts b/src/testUtils.ts
index 1b3851b..3c33ee9 100644
--- a/src/testUtils.ts
+++ b/src/testUtils.ts
@@ -18,11 +18,11 @@
 	getGoVersion,
 	getTempFilePath,
 	getToolsEnvVars,
+	killTree,
 	LineBuffer,
 	resolvePath
 } from './util';
 
-const sendSignal = 'SIGKILL';
 const outputChannel = vscode.window.createOutputChannel('Go Tests');
 const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
 statusBarItem.command = 'go.test.cancel';
@@ -372,14 +372,6 @@
 					outBuf.done();
 					errBuf.done();
 
-					if (code) {
-						outputChannel.appendLine(`Error: ${testType} failed.`);
-					} else if (signal === sendSignal) {
-						outputChannel.appendLine(`Error: ${testType} terminated by user.`);
-					} else {
-						outputChannel.appendLine(`Success: ${testType} passed.`);
-					}
-
 					const index = runningTestProcesses.indexOf(tp, 0);
 					if (index > -1) {
 						runningTestProcesses.splice(index, 1);
@@ -420,7 +412,7 @@
 export function cancelRunningTests(): Thenable<boolean> {
 	return new Promise<boolean>((resolve, reject) => {
 		runningTestProcesses.forEach((tp) => {
-			tp.kill(sendSignal);
+			killTree(tp.pid);
 		});
 		// All processes are now dead. Empty the array to prepare for the next run.
 		runningTestProcesses.splice(0, runningTestProcesses.length);
diff --git a/src/util.ts b/src/util.ts
index 295422c..a5525ba 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -1023,6 +1023,3 @@
 	}
 	return false;
 }
-
-// isForNightly is true if the source code is built for a preview version of the extension.
-export const isForNightly: boolean = extensionId.endsWith('.go-nightly');
diff --git a/test/integration/extension.test.ts b/test/integration/extension.test.ts
index 17372c5..a8af8d1 100644
--- a/test/integration/extension.test.ts
+++ b/test/integration/extension.test.ts
@@ -39,7 +39,7 @@
 	isVendorSupported
 } from '../../src/util';
 
-suite('Go Extension Tests', function() {
+suite('Go Extension Tests', function () {
 	this.timeout(10000);
 
 	const dummyCancellationSource = new vscode.CancellationTokenSource();
@@ -1305,9 +1305,9 @@
 				assert.equal(
 					expected.length,
 					labels.length,
-					`expected number of completions: ${expected.length} Actual: ${
-						labels.length
-					} at position(${position.line + 1},${position.character + 1}) ${labels}`
+					`expected number of completions: ${expected.length} Actual: ${labels.length} at position(${
+						position.line + 1
+					},${position.character + 1}) ${labels}`
 				);
 				expected.forEach((entry, index) => {
 					assert.equal(
diff --git a/tslint.json b/tslint.json
index e5e73bd..41739c7 100644
--- a/tslint.json
+++ b/tslint.json
@@ -119,7 +119,7 @@
 		"semicolon": true,
 		"space-before-function-paren": {
 			"options": {
-				"anonymous": "never",
+				"anonymous": "always",
 				"asyncArrow": "always",
 				"constructor": "never",
 				"method": "never",