[latest] v0.16.1

Change-Id: I4209d517a161fc3016461d6941047db4f323887d
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
deleted file mode 100644
index 96e2275..0000000
--- a/.github/workflows/codeql-analysis.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-name: "Code scanning - action"
-
-on:
-  push:
-  schedule:
-    - cron: '0 22 * * 1'
-
-jobs:
-  CodeQL-Build:
-    if: github.ref == 'refs/heads/master' && github.repository == 'golang/vscode-go'
-
-    # CodeQL runs on ubuntu-latest and windows-latest
-    runs-on: ubuntu-latest
-
-    steps:
-    - name: Checkout repository
-      uses: actions/checkout@v2
-
-    # Initializes the CodeQL tools for scanning.
-    - name: Initialize CodeQL
-      uses: github/codeql-action/init@v1
-      with:
-        languages: go, javascript
-
-    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
-    # If this step fails, then you should remove it and run the build manually (see below)
-    - name: Autobuild
-      uses: github/codeql-action/autobuild@v1
-
-    # ℹī¸ Command-line programs to run using the OS shell.
-    # 📚 https://git.io/JvXDl
-
-    # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines
-    #    and modify them (or add more) to build your code if your project
-    #    uses a compiled language
-
-    #- run: |
-    #   make bootstrap
-    #   make release
-
-    - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v1
diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml
index a04eaae..0df894b 100644
--- a/.github/workflows/release-nightly.yml
+++ b/.github/workflows/release-nightly.yml
@@ -40,37 +40,36 @@
       - name: Compile
         run: npm run vscode:prepublish
 
+      # TODO: use prerelease versions of tools (how? or master?)
+
       - name: Install Go tools (Modules mode)
         run: |
             go version
-            go get github.com/acroca/go-symbols \
-               github.com/davidrjenni/reftools/cmd/fillstruct \
-               github.com/haya14busa/goplay/cmd/goplay \
-               github.com/mdempsky/gocode \
-               github.com/sqs/goreturns \
-               github.com/uudashr/gopkgs/v2/cmd/gopkgs \
-               github.com/zmb3/gogetdoc \
-               golang.org/x/lint/golint \
-               golang.org/x/tools/cmd/gorename \
-               golang.org/x/tools/gopls
-
+            go get github.com/acroca/go-symbols
+            go get github.com/davidrjenni/reftools/cmd/fillstruct
+            go get github.com/haya14busa/goplay/cmd/goplay
+            go get github.com/mdempsky/gocode
+            go get github.com/sqs/goreturns
+            go get github.com/uudashr/gopkgs/v2/cmd/gopkgs
+            go get github.com/zmb3/gogetdoc
+            go get golang.org/x/lint/golint
+            go get golang.org/x/tools/cmd/gorename
+            go get golang.org/x/tools/gopls
         env:
-          GO111MODULE: on
-
+          GO111MODULE: on   
+          
       - name: Install Go tools (GOPATH mode)
         run: |
           go version
-          go get github.com/cweill/gotests/... \
-            github.com/rogpeppe/godef \
-            github.com/ramya-rao-a/go-outline
+          go get github.com/cweill/gotests/...
+          go get github.com/rogpeppe/godef
+          go get github.com/ramya-rao-a/go-outline
             # Because some tests depend on the source code checked in GOPATH. TODO: FIX THEM.
         env:
           GO111MODULE: off
 
-
       - name: Run unit tests
         run: npm run unit-test
-        continue-on-error: true
 
       - name: Run tests
         uses: GabrielBB/xvfb-action@v1.0
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 74b17a3..c984375 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -21,10 +21,9 @@
 #    the 'Release (golang.go)' workflow specified in this file.
 #      - For stable version release (vX.X.X), check if the package.json has the matching version.
 #      - Packaging using 'vsce package'
-#      - Create a release in Github
+#      - Create a release in GitHub
 #      - Upload the vsix file as an asset of the release
 #      - For stable version release (vX.X.X), upload to the vscode market place
-#        (not implemented in this CL)
 
 on:
   push:
@@ -32,9 +31,10 @@
       - v*
 
 jobs:
-  build:
+  release:
     name: create release
     runs-on: ubuntu-latest
+    if: github.repository == 'golang/vscode-go'
 
     steps:
       - name: checkout code
@@ -95,6 +95,14 @@
           asset_path: ./go-${{ env.EXT_VERSION }}.vsix
           asset_name: go-${{ env.EXT_VERSION }}.vsix
           asset_content_type: application/zip
+
+      - name: publish
+        if: env.EXT_ISPREVIEW != 1 && github.repository == 'golang/vscode-go'
+        uses: lannonbr/vsce-action@704da577da0f27de5cdb4ae018374c2f08b5f523
+        with:
+          args: "publish -p $VSCE_TOKEN"
+        env:
+          VSCE_TOKEN: ${{ secrets.VSCE_TOKEN }}
+
 # TODO: check if the commit is in green state. (test-long.yml results)
-# TODO: publish to the market if VERSION is for a stable version.
 # TODO: after publishing, create a gerrit CL to update 'latest' branch if VERSION is for a stable version.
diff --git a/.github/workflows/test-long.yml b/.github/workflows/test-long.yml
index 1b5f75e..6fcbbd7 100644
--- a/.github/workflows/test-long.yml
+++ b/.github/workflows/test-long.yml
@@ -69,7 +69,6 @@
       
       - name: Run unit tests
         run: npm run unit-test
-        continue-on-error: true
         
       - name: Run tests
         uses: GabrielBB/xvfb-action@v1.0
diff --git a/.github/workflows/test-smoke.yml b/.github/workflows/test-smoke.yml
index 96e517f..150b21a 100644
--- a/.github/workflows/test-smoke.yml
+++ b/.github/workflows/test-smoke.yml
@@ -65,7 +65,6 @@
       
       - name: Run unit tests
         run: npm run unit-test
-        continue-on-error: true
         
       - name: Run tests
         uses: GabrielBB/xvfb-action@v1.0
diff --git a/.gitignore b/.gitignore
index 68d1f87..d71de02 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
-out
-node_modules
-.vscode-test
+out/
+dist/
+node_modules/
+.vscode-test/
 .DS_Store
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index c6761bb..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,61 +0,0 @@
-language: go
-
-dist: bionic
-
-go:
-  - 1.13.x
-  - 1.14.x
-  - tip
-
-git:
-  depth: 1
-
-matrix:
-  allow_failures:
-    - go: tip
-
-os:
-  - osx
-  - linux
-
-before_install:
-  # Call xvfb directly on linux runs and give it time to start
-  - if [[ $TRAVIS_OS_NAME == "linux" ]]; then
-    export DISPLAY=:99.0;
-    Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
-    sleep 3;
-    sudo apt-get update && sudo apt-get install -y libsecret-1-0;
-    fi
-
-install:
-  - TRAVIS_NODE_VERSION="12";
-  # Clear out whatever version of NVM Travis has as it is old.
-  - rm -rf ~/.nvm;
-    # Grab NVM.
-  - git clone https://github.com/creationix/nvm.git ~/.nvm;
-    # Checkout the latest stable tag.
-    # Note that you can just hardcode a preferred version here.
-  - (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`);
-    # Install the desired version of Node
-  - source ~/.nvm/nvm.sh;
-  - nvm install $TRAVIS_NODE_VERSION;
-  - npm ci
-  - npm run vscode:prepublish
-  - go get -u -v github.com/acroca/go-symbols
-  - go get -u -v github.com/cweill/gotests/...
-  - go get -u -v github.com/davidrjenni/reftools/cmd/fillstruct
-  - go get -u -v github.com/haya14busa/goplay/cmd/goplay
-  - go get -u -v github.com/mdempsky/gocode
-  - go get -u -v github.com/ramya-rao-a/go-outline
-  - go get -u -v github.com/rogpeppe/godef
-  - go get -u -v github.com/sqs/goreturns
-  - go get -u -v github.com/uudashr/gopkgs/v2/cmd/gopkgs
-  - go get -u -v github.com/zmb3/gogetdoc
-  - go get -u -v golang.org/x/lint/golint
-  - go get -u -v golang.org/x/tools/cmd/gorename
-  - GO111MODULE=on go get golang.org/x/tools/gopls
-
-script:
-  - npm run lint
-  - npm run unit-test
-  - npm test --silent
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 94310ec..4f23b75 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,7 +1,6 @@
 {
 	"version": "0.2.0",
 	"configurations": [
-		
 		{
 			"name": "Launch Extension",
 			"type": "extensionHost",
@@ -12,27 +11,45 @@
 				"--extensionDevelopmentPath=${workspaceFolder}",
 				"--disable-extensions"
 			],
+			"outFiles": [
+                "${workspaceFolder}/dist/**/*.js"
+            ],
 			"stopOnEntry": false,
 			"sourceMaps": true,
-			"outFiles": [
-				"${workspaceFolder}/out/**/*.js"
-			],
-			"preLaunchTask": "npm: watch"
+			"smartStep": true,
+			"preLaunchTask": "npm: webpack",
 		},
 		{
 			"name": "Launch as server",
 			"type": "node",
 			"protocol": "inspector",
 			"request": "launch",
-			"program": "${workspaceFolder}/out/src/debugAdapter/goDebug.js",
+			"program": "${workspaceFolder}/dist/debugAdapter.js",
+			"args": [
+				"--server=4711"
+			],
+			"outFiles": [
+				"${workspaceFolder}/dist/**/*.js"
+			],
+			"sourceMaps": true,
+			"smartStep": true,
+			"preLaunchTask": "npm: webpack"
+		},
+		{
+			"name": "Launch as server (dlv dap)",
+			"type": "node",
+			"protocol": "inspector",
+			"request": "launch",
+			"program": "${workspaceFolder}/dist/debugAdapter2.js",
 			"args": [
 				"--server=4711"
 			],
 			"sourceMaps": true,
+			"smartStep": true,
 			"outFiles": [
-				"${workspaceFolder}/out/**/*.js"
+				"${workspaceFolder}/dist/**/*.js"
 			],
-			"preLaunchTask": "npm"
+			"preLaunchTask": "npm: webpack"
 		},
 		{
 			"name": "Launch Extension Tests",
@@ -49,6 +66,7 @@
 			],
 			"stopOnEntry": false,
 			"sourceMaps": true,
+			"smartStep": true,
 			"outFiles": [
 				"${workspaceFolder}/out/test/**/*.js"
 			],
@@ -87,7 +105,8 @@
 				"--colors",
 				"${workspaceFolder}/out/test/unit"
 			],
-			"internalConsoleOptions": "openOnSessionStart"
+			"internalConsoleOptions": "openOnSessionStart",
+			"preLaunchTask": "npm: watch",
 		},
 	],
 	"compounds": [
@@ -99,4 +118,4 @@
 			]
 		}
 	]
-}
\ No newline at end of file
+}
diff --git a/.vscodeignore b/.vscodeignore
index 529c5c2..c33036f 100644
--- a/.vscodeignore
+++ b/.vscodeignore
@@ -1,18 +1,19 @@
-src/**/*
-test/
-third_party/
-typings/**/*
-.vscode/**/*
-tsconfig.json
-.gitignore
-node_modules/fs-extra
 **/*.map
 **/tslint.json
-build/**/*
-docs/
-*.md.nightly
 .github/**/*
+.gitignore
 .prettierrc.json
-out/test/**
 .vscode-test/**
+.vscode/
 SECURITY.md
+build/
+docs/
+node_modules
+out/
+src/
+test/
+third_party/
+tools/
+tsconfig.json
+typings/
+webpack.config.js
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e1d5d48..0edd6b3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,89 @@
+## v0.16.1 - 5th Aug, 2020
+
+### Fixed
+
+- Fixed the bug that made test output verbose by default ([Issue 471](https://github.com/golang/vscode-go/issues/469)).
+- Fixed the extension host crash bug due to a process-wide uncaught exception handler accidentally installed along with the inlined debug adapter. This crash bug also caused connection drops when used with the VS Code Remote extension ([Issue 467](https://github.com/golang/vscode-go/issues/467), [469](https://github.com/golang/vscode-go/issues/469)).
+- Readded the predefined variable resolution support for `go.goroot` and `go.toolsEnvVars` ([Issue 464](https://github.com/golang/vscode-go/issues/464), [413](https://github.com/golang/vscode-go/issues/413)).
+
+## v0.16.0 - 3rd Aug, 2020
+
+This version requires VS Code 1.46+.
+
+Older versions of VS Code will not receive updates any more.
+
+### New Features
+
+- Users can select/install a different version of Go with `Go: Choose Go Environment` command.
+When clicking the `Go` status bar that displays the currently active Go version, users will be
+prompted with the list of Go versions installed locally or available for download.
+This feature was built based on the [`golang.org/dl`](https://pkg.go.dev/golang.org/dl?tab=overview)
+tools.
+The selected Go version applies to the workspace, takes precedence over the
+system default or the `"go.goroot"` and `"go.alternateTools"` settings, and persists
+across sessions. You can clear the choice by selecting the `Clear Selection` item.
+([Issue 253](https://github.com/golang/vscode-go/issues/253))
+- When the Go version changes, the extension prepends `$GOROOT/bin` to the `PATH` or `Path`
+environment variable which then applies the change to the integrated terminal windows.
+- This version includes an experimental version of the new Debug Adapter that uses Delve's
+native DAP implementation. It currently supports `launch` type requests in `debug` or `test`
+mode. This is still in the early stages and requires
+[`dlv`](https://github.com/go-delve/delve) built from its unreleased, master
+branch. Subscribe to
+[golang/vscode-go#23](https://github.com/golang/vscode-go/issues/23) for updates.
+
+### Enhancement
+
+- Bundles the extension using webpack, which reduced the extension size
+(4.7MB -> 1MB) and the extension loading overhead (3.4K files -> 3 files)
+([Issue 53](https://github.com/golang/vscode-go/issues/53)).
+- `Go: Apply Cover Profile` applies code coverage for multiple packages
+([CL 238697](https://go-review.googlesource.com/c/vscode-go/+/238697)).
+We fixed bugs in processing coverage profiles on Windows.
+- Suggests the official Go download page when no `go` tool is found.
+- Utilizes the `GOMODCACHE` environment variable, introduced in
+[Go 1.15](https://tip.golang.org/doc/go1.15#go-command).
+- Prevents multiple debug sessions from launching
+([Issue 109](https://github.com/golang/vscode-go/issues/109)).
+- Streams test output when tests run with the `-v` option.
+This feature requires 1.14 or newer versions of Go
+([Issue 316](https://github.com/golang/vscode-go/issues/316)).
+- Sets `additionalProperties` to `false` for the settings that don't expect
+more properties. This allows VS Code to handle these settings better in
+its new settings GUI ([Issue 284](https://github.com/golang/vscode-go/pull/284)).
+- `Go: Locate Configured Go Tools` includes `go env` results
+([Issue 195](https://github.com/golang/vscode-go/issues/195)).
+- Avoids prompting users to switch the default format tool in modules mode
+if users enable the language server.
+
+### Fixed
+
+- Fixed the `PATH` environment variable adjustment when users use a wrapper as an alternate
+tool for `go` ([CL 239697](https://go-review.googlesource.com/c/vscode-go/+/239697)).
+- Fixed a bug in test output processing, which prevented VS code from linking test log messages with locations in the source file.
+- Fixed a `gocode-gomod` installation bug when `GOPATH` includes multiple directories
+([Issue 368](https://github.com/golang/vscode-go/issues/368)).
+- Avoids attempting to kill already terminated processes ([Issue 334](https://github.com/golang/vscode-go/issues/334)).
+- Fixed `godef` to locate standard packages correctly by passing the `GOROOT` environment variable.
+- Fixed a `golangci-lint` integration bug that prevented displaying the lint results correctly when
+linters like `nolintlint` are enabled ([Issue 411](https://github.com/golang/vscode-go/issues/411)).
+- Fixed lost test function name arguments when running `Go: Test Previous`
+([Issue 269](https://github.com/golang/vscode-go/issues/269)).
+
+### Code Health
+
+- Many enhancements to improve test reliability and test coverage were made during this dev cycle.
+- TryBot is enabled, and the test results are posted to Gerrit CL. Currently, only the internal team members
+can see the details of the test results, but we will continue working to make them public.
+- Windows tests are now fixed and enabled in GitHub Action-based CI.
+- Refactored code shared by the extension and the debug adapters to prevent accidental debug adapter breakages.
+- Updated `json-rpc2` and `lodash` to address vulnerability reports from `npm audit`.
+
+### Thanks
+
+Thank you for your contribution, fujimoto kyosuke, OneOfOne, Aditya Thakral, Oleg Butuzov, Rebecca Stambler, Peter Weinberger, Brayden Cloud, Eli Bendersky, Robert Findley, Hana Kim!
+
+
 ## v0.15.2 - 21st July, 2020
 
 ### Fixed
diff --git a/LICENSE b/LICENSE
index 54e5303..138c387 100644
--- a/LICENSE
+++ b/LICENSE
@@ -28,7 +28,7 @@
 
 -----
 
-The following software may be included in this product: ajv. A copy of the source code may be downloaded from https://github.com/epoberezkin/ajv.git. This software contains the following license and notice below:
+The following software may be included in this product: ajv. A copy of the source code may be downloaded from https://github.com/ajv-validator/ajv.git. This software contains the following license and notice below:
 
 The MIT License (MIT)
 
@@ -394,7 +394,7 @@
 
 -----
 
-The following software may be included in this product: concat-map, is-typedarray, minimist. A copy of the source code may be downloaded from git://github.com/substack/node-concat-map.git (concat-map), git://github.com/hughsk/is-typedarray.git (is-typedarray), git://github.com/substack/minimist.git (minimist). This software contains the following license and notice below:
+The following software may be included in this product: concat-map, is-typedarray. A copy of the source code may be downloaded from git://github.com/substack/node-concat-map.git (concat-map), git://github.com/hughsk/is-typedarray.git (is-typedarray). This software contains the following license and notice below:
 
 This software is released under the MIT license:
 
@@ -685,32 +685,6 @@
 
 -----
 
-The following software may be included in this product: eventemitter3. A copy of the source code may be downloaded from git://github.com/primus/eventemitter3.git. This software contains the following license and notice below:
-
-The MIT License (MIT)
-
-Copyright (c) 2014 Arnout Kazemier
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
------
-
 The following software may be included in this product: extend. A copy of the source code may be downloaded from https://github.com/justmoon/node-extend.git. This software contains the following license and notice below:
 
 The MIT License (MIT)
@@ -1433,10 +1407,20 @@
 
 The following software may be included in this product: lodash. A copy of the source code may be downloaded from https://github.com/lodash/lodash.git. This software contains the following license and notice below:
 
-Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
-Based on Underscore.js, copyright 2009-2015 Jeremy Ashkenas,
+Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
+
+Based on Underscore.js, copyright Jeremy Ashkenas,
 DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
 
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at https://github.com/lodash/lodash
+
+The following license applies to all parts of this software except as
+documented below:
+
+====
+
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
 "Software"), to deal in the Software without restriction, including
@@ -1456,6 +1440,21 @@
 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+====
+
+Copyright and related rights for sample code are waived via CC0. Sample
+code is defined as all source code displayed within the prose of the
+documentation.
+
+CC0: http://creativecommons.org/publicdomain/zero/1.0/
+
+====
+
+Files located in the node_modules and vendor directories are externally
+maintained libraries used by this software which have their own
+licenses; we recommend you read them, as their terms may differ from the
+terms above.
+
 -----
 
 The following software may be included in this product: mime-db. A copy of the source code may be downloaded from https://github.com/jshttp/mime-db.git. This software contains the following license and notice below:
@@ -1512,11 +1511,11 @@
 
 -----
 
-The following software may be included in this product: mkdirp. A copy of the source code may be downloaded from https://github.com/substack/node-mkdirp.git. This software contains the following license and notice below:
+The following software may be included in this product: mkdirp. A copy of the source code may be downloaded from https://github.com/isaacs/node-mkdirp.git. This software contains the following license and notice below:
 
-Copyright 2010 James Halliday (mail@substack.net)
+Copyright James Halliday (mail@substack.net) and Isaac Z. Schlueter (i@izs.me)
 
-This project is free software released under the MIT/X11 license:
+This project is free software released under the MIT license:
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/docs/debugging.md b/docs/debugging.md
index e71bfe5..e5b3f47 100644
--- a/docs/debugging.md
+++ b/docs/debugging.md
@@ -345,15 +345,15 @@
 
 #### OSX
 
-This usually happens on OSX due to signing issues. See the discussions in [Microsoft/vscode-go#717](https://github.com/Microsoft/vscode-go/issues/717), [Microsoft/vscode-go#269](https://github.com/Microsoft/vscode-go/issues/269) and [derekparker/delve#357](https://github.com/derekparker/delve/issues/357).
+This usually happens on OSX due to signing issues. See the discussions in [Microsoft/vscode-go#717](https://github.com/Microsoft/vscode-go/issues/717), [Microsoft/vscode-go#269](https://github.com/Microsoft/vscode-go/issues/269) and [go-delve/delve#357](https://github.com/go-delve/delve/issues/357).
 
-**_Solution_**: You may have to uninstall dlv and install it manually as described in the [Delve instructions](https://github.com/derekparker/delve/blob/master/Documentation/installation/osx/install.md#manual-install).
+**_Solution_**: You may have to uninstall dlv and install it manually as described in the [Delve instructions](https://github.com/go-delve/delve/blob/master/Documentation/installation/osx/install.md#manual-install).
 
 #### Linux/Docker
 
 Docker has security settings preventing `ptrace(2)` operations by default within the container.
 
-**_Solution_**: To run your container insecurely, pass `--security-opt=seccomp:unconfined` to `docker run`. See [derekparker/delve#515](https://github.com/derekparker/delve/issues/515) for references.
+**_Solution_**: To run your container insecurely, pass `--security-opt=seccomp:unconfined` to `docker run`. See [go-delve/delve#515](https://github.com/go-delve/delve/issues/515) for references.
 
 #### could not launch process: exec: "lldb-server": executable file not found in $PATH
 
diff --git a/docs/nightly/CHANGELOG.md b/docs/nightly/CHANGELOG.md
deleted file mode 100644
index f93a946..0000000
--- a/docs/nightly/CHANGELOG.md
+++ /dev/null
@@ -1,4 +0,0 @@
-## 2020.3.x
-* Set the extension name for VS Code Go Nightly(`go-nightly`).
-* Pick up the pre-release version of `gopls` if available.
-* Disabled the telemetry report for VS Code Go.
diff --git a/docs/nightly/README.md b/docs/nightly/README.md
deleted file mode 100644
index 13a0c43..0000000
--- a/docs/nightly/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Go Nightly for VS Code
-
-> ### **ATTENTION: This is the *preview* version of the [VS Code Go extension](https://github.com/golang/vscode-go), used for early feedback and testing.**
-> It is published nightly and contains previews of new features and bug fixes that are still under review or test. Therefore, this extension can be broken or unstable at times. If you are looking for the stable version,
-please install [the default VS Code Go extension](https://marketplace.visualstudio.com/items?itemName=golang.go) instead.
->
-> **NOTE: The stable Go extension (`golang.go`) cannot be used at the same time as the preview Go Nightly extension (`golang.go-nightly`)**. If you have installed both extensions, you **must disable or uninstall** one of them. For further guidance, read the [documentation on how to disable an extension](https://code.visualstudio.com/docs/editor/extension-gallery#_disable-an-extension).
-
-> ### **Differences between Go and Go Nightly**
->
-> * Go Nightly is released more frequently than the stable version (once per weekday).
-> * Go Nightly includes features and bug fixes that are not yet finalized.
-> * Go Nightly may use pre-release versions of tools (such as `gopls`) instead of released versions.
-> * For more information about Go Nightly, read the [Go Nightly](../nightly.md) documentation.
diff --git a/docs/tools.md b/docs/tools.md
index a99ea96..8a620aa 100644
--- a/docs/tools.md
+++ b/docs/tools.md
@@ -56,7 +56,6 @@
 
 Different versions of `gocode` are used depending on your version of Go.
 
-* Go 1.8 and below: [nsf/gocode](https://github.com/nsf/gocode)
 * Go 1.9 and above: [mdempsky/gocode](https://github.com/mdempsky/gocode)
 * Go 1.11 and above, with modules enabled: [stamblerre/gocode](https://github.com/stamblerre/gocode)
   * This version of `gocode` does not have any caching, so if you find it slow, consider using [gopls] instead.
diff --git a/package-lock.json b/package-lock.json
index 81e1db1..001259c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "go",
-  "version": "0.15.2",
+  "version": "0.16.1",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -122,15 +122,15 @@
       "dev": true
     },
     "@types/node": {
-      "version": "13.13.11",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.11.tgz",
-      "integrity": "sha512-FX7mIFKfnGCfq10DGWNhfCNxhACEeqH5uulT6wRRA1KEt7zgLe0HdrAd9/QQkObDqp2Z0KEV3OAmNgs0lTx5tQ==",
+      "version": "13.13.13",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.13.tgz",
+      "integrity": "sha512-UfvBE9oRCAJVzfR+3eWm/sdLFe/qroAPEXP3GPJ1SehQiEVgZT6NQZWYbPMiJ3UdcKM06v4j+S1lTcdWCmw+3g==",
       "dev": true
     },
     "@types/semver": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.2.0.tgz",
-      "integrity": "sha512-TbB0A8ACUWZt3Y6bQPstW9QNbhNeebdgLX4T/ZfkrswAfUzRiXrgd9seol+X379Wa589Pu4UEx9Uok0D4RjRCQ==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.1.tgz",
+      "integrity": "sha512-ooD/FJ8EuwlDKOI6D9HWxgIgJjMg2cuziXm/42npDC8y4NjxplBUn9loewZiBNCt44450lHAU0OSb51/UqXeag==",
       "dev": true,
       "requires": {
         "@types/node": "*"
@@ -152,15 +152,208 @@
       "dev": true
     },
     "@types/vscode": {
-      "version": "1.45.1",
-      "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.45.1.tgz",
-      "integrity": "sha512-0NO9qrrEJBO8FsqHCrFMgR2suKnwCsKBWvRSb2OzH5gs4i3QO5AhEMQYrSzDbU/wLPt7N617/rN9lPY213gmwg==",
+      "version": "1.46.0",
+      "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.46.0.tgz",
+      "integrity": "sha512-8m9wPEB2mcRqTWNKs9A9Eqs8DrQZt0qNFO8GkxBOnyW6xR//3s77SoMgb/nY1ctzACsZXwZj3YRTDsn4bAoaUw==",
+      "dev": true
+    },
+    "@webassemblyjs/ast": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
+      "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/helper-module-context": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/wast-parser": "1.9.0"
+      }
+    },
+    "@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
+      "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-api-error": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
+      "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-buffer": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
+      "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-code-frame": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
+      "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/wast-printer": "1.9.0"
+      }
+    },
+    "@webassemblyjs/helper-fsm": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
+      "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-module-context": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
+      "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0"
+      }
+    },
+    "@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz",
+      "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-wasm-section": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz",
+      "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0"
+      }
+    },
+    "@webassemblyjs/ieee754": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz",
+      "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==",
+      "dev": true,
+      "requires": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "@webassemblyjs/leb128": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz",
+      "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==",
+      "dev": true,
+      "requires": {
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webassemblyjs/utf8": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz",
+      "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==",
+      "dev": true
+    },
+    "@webassemblyjs/wasm-edit": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz",
+      "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/helper-wasm-section": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0",
+        "@webassemblyjs/wasm-opt": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0",
+        "@webassemblyjs/wast-printer": "1.9.0"
+      }
+    },
+    "@webassemblyjs/wasm-gen": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz",
+      "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/ieee754": "1.9.0",
+        "@webassemblyjs/leb128": "1.9.0",
+        "@webassemblyjs/utf8": "1.9.0"
+      }
+    },
+    "@webassemblyjs/wasm-opt": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz",
+      "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0"
+      }
+    },
+    "@webassemblyjs/wasm-parser": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz",
+      "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-api-error": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/ieee754": "1.9.0",
+        "@webassemblyjs/leb128": "1.9.0",
+        "@webassemblyjs/utf8": "1.9.0"
+      }
+    },
+    "@webassemblyjs/wast-parser": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz",
+      "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/floating-point-hex-parser": "1.9.0",
+        "@webassemblyjs/helper-api-error": "1.9.0",
+        "@webassemblyjs/helper-code-frame": "1.9.0",
+        "@webassemblyjs/helper-fsm": "1.9.0",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webassemblyjs/wast-printer": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz",
+      "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/wast-parser": "1.9.0",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+      "dev": true
+    },
+    "@xtuc/long": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+      "dev": true
+    },
+    "acorn": {
+      "version": "6.4.1",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
+      "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
       "dev": true
     },
     "adm-zip": {
-      "version": "0.4.14",
-      "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz",
-      "integrity": "sha512-/9aQCnQHF+0IiCl0qhXoK7qs//SwYE7zX8lsr/DNk1BRAHYxeLZPL4pguwK29gUEqasYQjqPtEpDRSWEkdHn9g==",
+      "version": "0.4.16",
+      "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz",
+      "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==",
       "dev": true
     },
     "agent-base": {
@@ -183,6 +376,18 @@
         "uri-js": "^4.2.2"
       }
     },
+    "ajv-errors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
+      "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
+      "dev": true
+    },
+    "ajv-keywords": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.0.tgz",
+      "integrity": "sha512-eyoaac3btgU8eJlvh01En8OCKzRqlLe2G5jDsCr3RiE2uLGMEEB1aaGwVVpwR8M95956tGH6R+9edC++OvzaVw==",
+      "dev": true
+    },
     "ansi-colors": {
       "version": "3.2.3",
       "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
@@ -214,6 +419,12 @@
         "picomatch": "^2.0.4"
       }
     },
+    "aproba": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+      "dev": true
+    },
     "argparse": {
       "version": "1.0.10",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -223,11 +434,35 @@
         "sprintf-js": "~1.0.2"
       }
     },
+    "arr-diff": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+      "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+      "dev": true
+    },
+    "arr-flatten": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+      "dev": true
+    },
+    "arr-union": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+      "dev": true
+    },
     "array-filter": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
       "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM="
     },
+    "array-unique": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+      "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+      "dev": true
+    },
     "asn1": {
       "version": "0.2.4",
       "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -236,11 +471,70 @@
         "safer-buffer": "~2.1.0"
       }
     },
+    "asn1.js": {
+      "version": "4.10.1",
+      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
+      "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.0.0",
+        "inherits": "^2.0.1",
+        "minimalistic-assert": "^1.0.0"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
+    "assert": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+      "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+      "dev": true,
+      "requires": {
+        "object-assign": "^4.1.1",
+        "util": "0.10.3"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+          "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+          "dev": true
+        },
+        "util": {
+          "version": "0.10.3",
+          "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+          "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+          "dev": true,
+          "requires": {
+            "inherits": "2.0.1"
+          }
+        }
+      }
+    },
     "assert-plus": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
     },
+    "assign-symbols": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+      "dev": true
+    },
+    "async-each": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+      "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
+      "dev": true,
+      "optional": true
+    },
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -252,6 +546,12 @@
       "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
       "dev": true
     },
+    "atob": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+      "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+      "dev": true
+    },
     "available-typed-arrays": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz",
@@ -275,6 +575,67 @@
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
     },
+    "base": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+      "dev": true,
+      "requires": {
+        "cache-base": "^1.0.1",
+        "class-utils": "^0.3.5",
+        "component-emitter": "^1.2.1",
+        "define-property": "^1.0.0",
+        "isobject": "^3.0.1",
+        "mixin-deep": "^1.2.0",
+        "pascalcase": "^0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "base64-js": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
+      "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==",
+      "dev": true
+    },
     "bcrypt-pbkdf": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
@@ -288,12 +649,40 @@
       "resolved": "https://registry.npmjs.org/better-curry/-/better-curry-1.6.0.tgz",
       "integrity": "sha1-OPcWskyM7geiYqvEHCLDFOIOOGk="
     },
+    "big.js": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+      "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+      "dev": true
+    },
     "binary-extensions": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
       "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
       "dev": true
     },
+    "bindings": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "file-uri-to-path": "1.0.0"
+      }
+    },
+    "bluebird": {
+      "version": "3.7.2",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+      "dev": true
+    },
+    "bn.js": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
+      "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==",
+      "dev": true
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -312,18 +701,195 @@
         "fill-range": "^7.0.1"
       }
     },
+    "brorand": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+      "dev": true
+    },
     "browser-stdout": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
       "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
       "dev": true
     },
+    "browserify-aes": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+      "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+      "dev": true,
+      "requires": {
+        "buffer-xor": "^1.0.3",
+        "cipher-base": "^1.0.0",
+        "create-hash": "^1.1.0",
+        "evp_bytestokey": "^1.0.3",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "browserify-cipher": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+      "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+      "dev": true,
+      "requires": {
+        "browserify-aes": "^1.0.4",
+        "browserify-des": "^1.0.0",
+        "evp_bytestokey": "^1.0.0"
+      }
+    },
+    "browserify-des": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+      "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+      "dev": true,
+      "requires": {
+        "cipher-base": "^1.0.1",
+        "des.js": "^1.0.0",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "browserify-rsa": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+      "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "randombytes": "^2.0.1"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
+    "browserify-sign": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz",
+      "integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^5.1.1",
+        "browserify-rsa": "^4.0.1",
+        "create-hash": "^1.2.0",
+        "create-hmac": "^1.1.7",
+        "elliptic": "^6.5.2",
+        "inherits": "^2.0.4",
+        "parse-asn1": "^5.1.5",
+        "readable-stream": "^3.6.0",
+        "safe-buffer": "^5.2.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "browserify-zlib": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+      "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+      "dev": true,
+      "requires": {
+        "pako": "~1.0.5"
+      }
+    },
+    "buffer": {
+      "version": "4.9.2",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
+      "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+      "dev": true,
+      "requires": {
+        "base64-js": "^1.0.2",
+        "ieee754": "^1.1.4",
+        "isarray": "^1.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        }
+      }
+    },
+    "buffer-from": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+      "dev": true
+    },
+    "buffer-xor": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+      "dev": true
+    },
     "builtin-modules": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
       "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
       "dev": true
     },
+    "builtin-status-codes": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+      "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+      "dev": true
+    },
+    "cacache": {
+      "version": "12.0.4",
+      "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
+      "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
+      "dev": true,
+      "requires": {
+        "bluebird": "^3.5.5",
+        "chownr": "^1.1.1",
+        "figgy-pudding": "^3.5.1",
+        "glob": "^7.1.4",
+        "graceful-fs": "^4.1.15",
+        "infer-owner": "^1.0.3",
+        "lru-cache": "^5.1.1",
+        "mississippi": "^3.0.0",
+        "mkdirp": "^0.5.1",
+        "move-concurrently": "^1.0.1",
+        "promise-inflight": "^1.0.1",
+        "rimraf": "^2.6.3",
+        "ssri": "^6.0.1",
+        "unique-filename": "^1.1.1",
+        "y18n": "^4.0.0"
+      }
+    },
+    "cache-base": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+      "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+      "dev": true,
+      "requires": {
+        "collection-visit": "^1.0.0",
+        "component-emitter": "^1.2.1",
+        "get-value": "^2.0.6",
+        "has-value": "^1.0.0",
+        "isobject": "^3.0.1",
+        "set-value": "^2.0.0",
+        "to-object-path": "^0.3.0",
+        "union-value": "^1.0.0",
+        "unset-value": "^1.0.0"
+      }
+    },
     "camelcase": {
       "version": "5.3.1",
       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
@@ -373,6 +939,54 @@
         "readdirp": "~3.2.0"
       }
     },
+    "chownr": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+      "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+      "dev": true
+    },
+    "chrome-trace-event": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
+      "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "cipher-base": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "class-utils": {
+      "version": "0.3.6",
+      "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+      "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+      "dev": true,
+      "requires": {
+        "arr-union": "^3.1.0",
+        "define-property": "^0.2.5",
+        "isobject": "^3.0.0",
+        "static-extend": "^0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        }
+      }
+    },
     "cliui": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
@@ -412,6 +1026,16 @@
         }
       }
     },
+    "collection-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+      "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+      "dev": true,
+      "requires": {
+        "map-visit": "^1.0.0",
+        "object-visit": "^1.0.0"
+      }
+    },
     "color-convert": {
       "version": "1.9.3",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -441,16 +1065,163 @@
       "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
       "dev": true
     },
+    "commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+      "dev": true
+    },
+    "component-emitter": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+      "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+      "dev": true
+    },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
+    "concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
+    "console-browserify": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
+      "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==",
+      "dev": true
+    },
+    "constants-browserify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+      "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+      "dev": true
+    },
+    "copy-concurrently": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+      "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.1.1",
+        "fs-write-stream-atomic": "^1.0.8",
+        "iferr": "^0.1.5",
+        "mkdirp": "^0.5.1",
+        "rimraf": "^2.5.4",
+        "run-queue": "^1.0.0"
+      }
+    },
+    "copy-descriptor": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+      "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+      "dev": true
+    },
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
     },
+    "create-ecdh": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
+      "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "elliptic": "^6.0.0"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
+    "create-hash": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+      "dev": true,
+      "requires": {
+        "cipher-base": "^1.0.1",
+        "inherits": "^2.0.1",
+        "md5.js": "^1.3.4",
+        "ripemd160": "^2.0.1",
+        "sha.js": "^2.4.0"
+      }
+    },
+    "create-hmac": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+      "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+      "dev": true,
+      "requires": {
+        "cipher-base": "^1.0.3",
+        "create-hash": "^1.1.0",
+        "inherits": "^2.0.1",
+        "ripemd160": "^2.0.0",
+        "safe-buffer": "^5.0.1",
+        "sha.js": "^2.4.8"
+      }
+    },
+    "cross-spawn": {
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+      "dev": true,
+      "requires": {
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
+      }
+    },
+    "crypto-browserify": {
+      "version": "3.12.0",
+      "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+      "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+      "dev": true,
+      "requires": {
+        "browserify-cipher": "^1.0.0",
+        "browserify-sign": "^4.0.0",
+        "create-ecdh": "^4.0.0",
+        "create-hash": "^1.1.0",
+        "create-hmac": "^1.1.0",
+        "diffie-hellman": "^5.0.0",
+        "inherits": "^2.0.1",
+        "pbkdf2": "^3.0.3",
+        "public-encrypt": "^4.0.0",
+        "randombytes": "^2.0.0",
+        "randomfill": "^1.0.3"
+      }
+    },
+    "cyclist": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
+      "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
+      "dev": true
+    },
     "dashdash": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -463,6 +1234,7 @@
       "version": "2.6.9",
       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
       "requires": {
         "ms": "2.0.0"
       }
@@ -473,6 +1245,12 @@
       "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
       "dev": true
     },
+    "decode-uri-component": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+      "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+      "dev": true
+    },
     "deep-equal": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.3.tgz",
@@ -509,16 +1287,110 @@
         "object-keys": "^1.0.12"
       }
     },
+    "define-property": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+      "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+      "dev": true,
+      "requires": {
+        "is-descriptor": "^1.0.2",
+        "isobject": "^3.0.1"
+      },
+      "dependencies": {
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
     "delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
     },
+    "des.js": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
+      "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "minimalistic-assert": "^1.0.0"
+      }
+    },
+    "detect-file": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
+      "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
+      "dev": true
+    },
     "diff": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
       "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
     },
+    "diffie-hellman": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+      "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "miller-rabin": "^4.0.0",
+        "randombytes": "^2.0.0"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
+    "domain-browser": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+      "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+      "dev": true
+    },
+    "duplexify": {
+      "version": "3.7.1",
+      "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+      "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.0.0",
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.0",
+        "stream-shift": "^1.0.0"
+      }
+    },
     "ecc-jsbn": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -528,12 +1400,70 @@
         "safer-buffer": "^2.1.0"
       }
     },
+    "elliptic": {
+      "version": "6.5.3",
+      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
+      "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.4.0",
+        "brorand": "^1.0.1",
+        "hash.js": "^1.0.0",
+        "hmac-drbg": "^1.0.0",
+        "inherits": "^2.0.1",
+        "minimalistic-assert": "^1.0.0",
+        "minimalistic-crypto-utils": "^1.0.0"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
     "emoji-regex": {
       "version": "7.0.3",
       "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
       "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
       "dev": true
     },
+    "emojis-list": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+      "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+      "dev": true
+    },
+    "end-of-stream": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+      "dev": true,
+      "requires": {
+        "once": "^1.4.0"
+      }
+    },
+    "enhanced-resolve": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.2.0.tgz",
+      "integrity": "sha512-S7eiFb/erugyd1rLb6mQ3Vuq+EXHv5cpCkNqqIkYkBgN2QdFnyCZzFBleqwGEx4lgNGYij81BWnCrFNK7vxvjQ==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "memory-fs": "^0.5.0",
+        "tapable": "^1.0.0"
+      }
+    },
+    "errno": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+      "dev": true,
+      "requires": {
+        "prr": "~1.0.1"
+      }
+    },
     "es-abstract": {
       "version": "1.17.5",
       "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
@@ -612,22 +1542,188 @@
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
       "dev": true
     },
+    "eslint-scope": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+      "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
+      "dev": true,
+      "requires": {
+        "esrecurse": "^4.1.0",
+        "estraverse": "^4.1.1"
+      }
+    },
     "esprima": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
       "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
       "dev": true
     },
-    "eventemitter3": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz",
-      "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg="
+    "esrecurse": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^4.1.0"
+      }
+    },
+    "estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+      "dev": true
+    },
+    "events": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
+      "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==",
+      "dev": true
+    },
+    "evp_bytestokey": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+      "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+      "dev": true,
+      "requires": {
+        "md5.js": "^1.3.4",
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "expand-brackets": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+      "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+      "dev": true,
+      "requires": {
+        "debug": "^2.3.3",
+        "define-property": "^0.2.5",
+        "extend-shallow": "^2.0.1",
+        "posix-character-classes": "^0.1.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "expand-tilde": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
+      "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
+      "dev": true,
+      "requires": {
+        "homedir-polyfill": "^1.0.1"
+      }
     },
     "extend": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
       "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
     },
+    "extend-shallow": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+      "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+      "dev": true,
+      "requires": {
+        "assign-symbols": "^1.0.0",
+        "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "dev": true,
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
+      }
+    },
+    "extglob": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+      "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+      "dev": true,
+      "requires": {
+        "array-unique": "^0.3.2",
+        "define-property": "^1.0.0",
+        "expand-brackets": "^2.1.4",
+        "extend-shallow": "^2.0.1",
+        "fragment-cache": "^0.2.1",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
     "extsprintf": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
@@ -651,6 +1747,19 @@
         "websocket-driver": ">=0.5.1"
       }
     },
+    "figgy-pudding": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
+      "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==",
+      "dev": true
+    },
+    "file-uri-to-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+      "dev": true,
+      "optional": true
+    },
     "fill-range": {
       "version": "7.0.1",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -660,6 +1769,17 @@
         "to-regex-range": "^5.0.1"
       }
     },
+    "find-cache-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+      "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+      "dev": true,
+      "requires": {
+        "commondir": "^1.0.1",
+        "make-dir": "^2.0.0",
+        "pkg-dir": "^3.0.0"
+      }
+    },
     "find-up": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
@@ -669,6 +1789,129 @@
         "locate-path": "^3.0.0"
       }
     },
+    "findup-sync": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz",
+      "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==",
+      "dev": true,
+      "requires": {
+        "detect-file": "^1.0.0",
+        "is-glob": "^4.0.0",
+        "micromatch": "^3.0.4",
+        "resolve-dir": "^1.0.1"
+      },
+      "dependencies": {
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "dev": true,
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "fill-range": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+          "dev": true,
+          "requires": {
+            "extend-shallow": "^2.0.1",
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1",
+            "to-regex-range": "^2.1.0"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "dev": true,
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "micromatch": {
+          "version": "3.1.10",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+          "dev": true,
+          "requires": {
+            "arr-diff": "^4.0.0",
+            "array-unique": "^0.3.2",
+            "braces": "^2.3.1",
+            "define-property": "^2.0.2",
+            "extend-shallow": "^3.0.2",
+            "extglob": "^2.0.4",
+            "fragment-cache": "^0.2.1",
+            "kind-of": "^6.0.2",
+            "nanomatch": "^1.2.9",
+            "object.pick": "^1.3.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.2"
+          }
+        },
+        "to-regex-range": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+          "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+          "dev": true,
+          "requires": {
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1"
+          }
+        }
+      }
+    },
     "flat": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
@@ -678,6 +1921,22 @@
         "is-buffer": "~2.0.3"
       }
     },
+    "flush-write-stream": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
+      "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.3.6"
+      }
+    },
+    "for-in": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+      "dev": true
+    },
     "foreach": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
@@ -698,6 +1957,25 @@
         "mime-types": "^2.1.12"
       }
     },
+    "fragment-cache": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+      "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+      "dev": true,
+      "requires": {
+        "map-cache": "^0.2.2"
+      }
+    },
+    "from2": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+      "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.0"
+      }
+    },
     "fs-extra": {
       "version": "9.0.1",
       "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
@@ -710,6 +1988,18 @@
         "universalify": "^1.0.0"
       }
     },
+    "fs-write-stream-atomic": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+      "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "iferr": "^0.1.5",
+        "imurmurhash": "^0.1.4",
+        "readable-stream": "1 || 2"
+      }
+    },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -733,6 +2023,12 @@
       "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
       "dev": true
     },
+    "get-value": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+      "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+      "dev": true
+    },
     "getpass": {
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@@ -763,6 +2059,41 @@
         "is-glob": "^4.0.1"
       }
     },
+    "global-modules": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
+      "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
+      "dev": true,
+      "requires": {
+        "global-prefix": "^3.0.0"
+      },
+      "dependencies": {
+        "global-prefix": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
+          "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
+          "dev": true,
+          "requires": {
+            "ini": "^1.3.5",
+            "kind-of": "^6.0.2",
+            "which": "^1.3.1"
+          }
+        }
+      }
+    },
+    "global-prefix": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
+      "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
+      "dev": true,
+      "requires": {
+        "expand-tilde": "^2.0.2",
+        "homedir-polyfill": "^1.0.1",
+        "ini": "^1.3.4",
+        "is-windows": "^1.0.1",
+        "which": "^1.2.14"
+      }
+    },
     "graceful-fs": {
       "version": "4.2.4",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
@@ -808,16 +2139,128 @@
       "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
       "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
     },
+    "has-value": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+      "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+      "dev": true,
+      "requires": {
+        "get-value": "^2.0.6",
+        "has-values": "^1.0.0",
+        "isobject": "^3.0.0"
+      }
+    },
+    "has-values": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+      "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+      "dev": true,
+      "requires": {
+        "is-number": "^3.0.0",
+        "kind-of": "^4.0.0"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "dev": true,
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "kind-of": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+          "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "hash-base": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+      "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.6.0",
+        "safe-buffer": "^5.2.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "hash.js": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+      "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "minimalistic-assert": "^1.0.1"
+      }
+    },
     "he": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
       "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
       "dev": true
     },
+    "hmac-drbg": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+      "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+      "dev": true,
+      "requires": {
+        "hash.js": "^1.0.3",
+        "minimalistic-assert": "^1.0.0",
+        "minimalistic-crypto-utils": "^1.0.1"
+      }
+    },
+    "homedir-polyfill": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
+      "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
+      "dev": true,
+      "requires": {
+        "parse-passwd": "^1.0.0"
+      }
+    },
     "http-parser-js": {
-      "version": "0.4.10",
-      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz",
-      "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q="
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz",
+      "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ=="
     },
     "http-proxy-agent": {
       "version": "2.1.0",
@@ -850,6 +2293,12 @@
         "sshpk": "^1.7.0"
       }
     },
+    "https-browserify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+      "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
+      "dev": true
+    },
     "https-proxy-agent": {
       "version": "2.2.4",
       "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
@@ -877,6 +2326,40 @@
         }
       }
     },
+    "ieee754": {
+      "version": "1.1.13",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+      "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
+      "dev": true
+    },
+    "iferr": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+      "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
+      "dev": true
+    },
+    "import-local": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+      "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+      "dev": true,
+      "requires": {
+        "pkg-dir": "^3.0.0",
+        "resolve-cwd": "^2.0.0"
+      }
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+      "dev": true
+    },
+    "infer-owner": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+      "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+      "dev": true
+    },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -891,6 +2374,44 @@
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
+    "ini": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+      "dev": true
+    },
+    "interpret": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
+      "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
+      "dev": true
+    },
+    "is-accessor-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+      "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
     "is-arguments": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
@@ -926,11 +2447,62 @@
       "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
       "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw=="
     },
+    "is-data-descriptor": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+      "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
     "is-date-object": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
       "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
     },
+    "is-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+      "dev": true,
+      "requires": {
+        "is-accessor-descriptor": "^0.1.6",
+        "is-data-descriptor": "^0.1.4",
+        "kind-of": "^5.0.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+          "dev": true
+        }
+      }
+    },
+    "is-extendable": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+      "dev": true
+    },
     "is-extglob": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -968,6 +2540,15 @@
       "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
       "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw=="
     },
+    "is-plain-object": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.1"
+      }
+    },
     "is-regex": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz",
@@ -1020,6 +2601,18 @@
       "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz",
       "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw=="
     },
+    "is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+      "dev": true
+    },
+    "is-wsl": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+      "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+      "dev": true
+    },
     "isarray": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
@@ -1032,6 +2625,12 @@
       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
       "dev": true
     },
+    "isobject": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+      "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+      "dev": true
+    },
     "isstream": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -1058,24 +2657,37 @@
       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
       "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
     },
-    "json-rpc2": {
+    "json-parse-better-errors": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/json-rpc2/-/json-rpc2-1.0.2.tgz",
-      "integrity": "sha1-63e9J7HfYGwjcCxONdSvxUdCro0=",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
+    "json-rpc2": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/json-rpc2/-/json-rpc2-2.0.0.tgz",
+      "integrity": "sha512-0jfrGSH0ZDxrpaaHUkigg/oA6MQqsZDpKSpUzeokhP2jyy6h+cH4G+MPoAa4SVdw9sTzc+YK2hzhUgdShMzKow==",
       "requires": {
-        "debug": "2.x.x",
-        "es5class": "2.x.x",
-        "eventemitter3": "1.x.x",
-        "faye-websocket": "0.x.x",
-        "jsonparse": "1.x.x",
-        "lodash": "3.x.x",
-        "object-assign": "4.x"
+        "debug": "^4.1.1",
+        "es5class": "^2.3.1",
+        "faye-websocket": "^0.11.3",
+        "jsonparse": "^1.3.1",
+        "lodash": "^4.17.15",
+        "object-assign": "^4.1.1"
       },
       "dependencies": {
-        "lodash": {
-          "version": "3.10.1",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
-          "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
         }
       }
     },
@@ -1094,6 +2706,15 @@
       "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
       "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
     },
+    "json5": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+      "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+      "dev": true,
+      "requires": {
+        "minimist": "^1.2.0"
+      }
+    },
     "jsonfile": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
@@ -1126,6 +2747,29 @@
       "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==",
       "dev": true
     },
+    "kind-of": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+      "dev": true
+    },
+    "loader-runner": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
+      "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==",
+      "dev": true
+    },
+    "loader-utils": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
+      "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
+      "dev": true,
+      "requires": {
+        "big.js": "^5.2.2",
+        "emojis-list": "^3.0.0",
+        "json5": "^1.0.1"
+      }
+    },
     "locate-path": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
@@ -1137,10 +2781,9 @@
       }
     },
     "lodash": {
-      "version": "4.17.15",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-      "dev": true
+      "version": "4.17.19",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+      "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
     },
     "lodash.get": {
       "version": "4.4.2",
@@ -1157,6 +2800,97 @@
         "chalk": "^2.4.2"
       }
     },
+    "lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "dev": true,
+      "requires": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "make-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "dev": true,
+      "requires": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
+      }
+    },
+    "map-cache": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+      "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+      "dev": true
+    },
+    "map-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+      "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+      "dev": true,
+      "requires": {
+        "object-visit": "^1.0.0"
+      }
+    },
+    "md5.js": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+      "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+      "dev": true,
+      "requires": {
+        "hash-base": "^3.0.0",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "memory-fs": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
+      "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
+      "dev": true,
+      "requires": {
+        "errno": "^0.1.3",
+        "readable-stream": "^2.0.1"
+      }
+    },
+    "micromatch": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
+      "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+      "dev": true,
+      "requires": {
+        "braces": "^3.0.1",
+        "picomatch": "^2.0.5"
+      }
+    },
+    "miller-rabin": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+      "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.0.0",
+        "brorand": "^1.0.1"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
     "mime-db": {
       "version": "1.43.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
@@ -1170,6 +2904,18 @@
         "mime-db": "1.43.0"
       }
     },
+    "minimalistic-assert": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+      "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+      "dev": true
+    },
+    "minimalistic-crypto-utils": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+      "dev": true
+    },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -1183,6 +2929,45 @@
       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
       "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
     },
+    "mississippi": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+      "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+      "dev": true,
+      "requires": {
+        "concat-stream": "^1.5.0",
+        "duplexify": "^3.4.2",
+        "end-of-stream": "^1.1.0",
+        "flush-write-stream": "^1.0.0",
+        "from2": "^2.1.0",
+        "parallel-transform": "^1.1.0",
+        "pump": "^3.0.0",
+        "pumpify": "^1.3.3",
+        "stream-each": "^1.1.0",
+        "through2": "^2.0.0"
+      }
+    },
+    "mixin-deep": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+      "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+      "dev": true,
+      "requires": {
+        "for-in": "^1.0.2",
+        "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "dev": true,
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
+      }
+    },
     "mkdirp": {
       "version": "0.5.5",
       "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
@@ -1261,14 +3046,66 @@
       }
     },
     "moment": {
-      "version": "2.26.0",
-      "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
-      "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw=="
+      "version": "2.27.0",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
+      "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
+    },
+    "move-concurrently": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+      "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.1.1",
+        "copy-concurrently": "^1.0.0",
+        "fs-write-stream-atomic": "^1.0.8",
+        "mkdirp": "^0.5.1",
+        "rimraf": "^2.5.4",
+        "run-queue": "^1.0.3"
+      }
     },
     "ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+      "dev": true
+    },
+    "nan": {
+      "version": "2.14.1",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
+      "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==",
+      "dev": true
+    },
+    "nanomatch": {
+      "version": "1.2.13",
+      "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+      "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+      "dev": true,
+      "requires": {
+        "arr-diff": "^4.0.0",
+        "array-unique": "^0.3.2",
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "fragment-cache": "^0.2.1",
+        "is-windows": "^1.0.2",
+        "kind-of": "^6.0.2",
+        "object.pick": "^1.3.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      }
+    },
+    "neo-async": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
+      "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
+      "dev": true
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
     },
     "nise": {
       "version": "4.0.3",
@@ -1301,6 +3138,45 @@
         }
       }
     },
+    "node-libs-browser": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
+      "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==",
+      "dev": true,
+      "requires": {
+        "assert": "^1.1.1",
+        "browserify-zlib": "^0.2.0",
+        "buffer": "^4.3.0",
+        "console-browserify": "^1.1.0",
+        "constants-browserify": "^1.0.0",
+        "crypto-browserify": "^3.11.0",
+        "domain-browser": "^1.1.1",
+        "events": "^3.0.0",
+        "https-browserify": "^1.0.0",
+        "os-browserify": "^0.3.0",
+        "path-browserify": "0.0.1",
+        "process": "^0.11.10",
+        "punycode": "^1.2.4",
+        "querystring-es3": "^0.2.0",
+        "readable-stream": "^2.3.3",
+        "stream-browserify": "^2.0.1",
+        "stream-http": "^2.7.2",
+        "string_decoder": "^1.0.0",
+        "timers-browserify": "^2.0.4",
+        "tty-browserify": "0.0.0",
+        "url": "^0.11.0",
+        "util": "^0.11.0",
+        "vm-browserify": "^1.0.1"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+          "dev": true
+        }
+      }
+    },
     "normalize-path": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -1317,6 +3193,43 @@
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
     },
+    "object-copy": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+      "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+      "dev": true,
+      "requires": {
+        "copy-descriptor": "^0.1.0",
+        "define-property": "^0.2.5",
+        "kind-of": "^3.0.3"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
     "object-inspect": {
       "version": "1.7.0",
       "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
@@ -1336,6 +3249,15 @@
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
       "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
     },
+    "object-visit": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+      "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.0"
+      }
+    },
     "object.assign": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
@@ -1357,6 +3279,15 @@
         "es-abstract": "^1.17.0-next.1"
       }
     },
+    "object.pick": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+      "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.1"
+      }
+    },
     "once": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -1365,6 +3296,12 @@
         "wrappy": "1"
       }
     },
+    "os-browserify": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+      "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
+      "dev": true
+    },
     "p-limit": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
@@ -1389,6 +3326,62 @@
       "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
       "dev": true
     },
+    "pako": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+      "dev": true
+    },
+    "parallel-transform": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
+      "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
+      "dev": true,
+      "requires": {
+        "cyclist": "^1.0.1",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.1.5"
+      }
+    },
+    "parse-asn1": {
+      "version": "5.1.5",
+      "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
+      "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
+      "dev": true,
+      "requires": {
+        "asn1.js": "^4.0.0",
+        "browserify-aes": "^1.0.0",
+        "create-hash": "^1.1.0",
+        "evp_bytestokey": "^1.0.0",
+        "pbkdf2": "^3.0.3",
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "parse-passwd": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
+      "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
+      "dev": true
+    },
+    "pascalcase": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+      "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+      "dev": true
+    },
+    "path-browserify": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
+      "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==",
+      "dev": true
+    },
+    "path-dirname": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+      "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+      "dev": true,
+      "optional": true
+    },
     "path-exists": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
@@ -1400,6 +3393,12 @@
       "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
     },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
+    },
     "path-parse": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
@@ -1415,6 +3414,19 @@
         "isarray": "0.0.1"
       }
     },
+    "pbkdf2": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz",
+      "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==",
+      "dev": true,
+      "requires": {
+        "create-hash": "^1.1.2",
+        "create-hmac": "^1.1.4",
+        "ripemd160": "^2.0.1",
+        "safe-buffer": "^5.0.1",
+        "sha.js": "^2.4.8"
+      }
+    },
     "performance-now": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -1426,17 +3438,117 @@
       "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
       "dev": true
     },
+    "pify": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+      "dev": true
+    },
+    "pkg-dir": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+      "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+      "dev": true,
+      "requires": {
+        "find-up": "^3.0.0"
+      }
+    },
+    "posix-character-classes": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+      "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+      "dev": true
+    },
     "prettier": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
       "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==",
       "dev": true
     },
+    "process": {
+      "version": "0.11.10",
+      "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+      "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+      "dev": true
+    },
+    "process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "dev": true
+    },
+    "promise-inflight": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+      "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+      "dev": true
+    },
+    "prr": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+      "dev": true
+    },
     "psl": {
       "version": "1.8.0",
       "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
       "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
     },
+    "public-encrypt": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+      "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "browserify-rsa": "^4.0.0",
+        "create-hash": "^1.1.0",
+        "parse-asn1": "^5.0.0",
+        "randombytes": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      },
+      "dependencies": {
+        "bn.js": {
+          "version": "4.11.9",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "dev": true
+        }
+      }
+    },
+    "pump": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+      "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "pumpify": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+      "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+      "dev": true,
+      "requires": {
+        "duplexify": "^3.6.0",
+        "inherits": "^2.0.3",
+        "pump": "^2.0.0"
+      },
+      "dependencies": {
+        "pump": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+          "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+          "dev": true,
+          "requires": {
+            "end-of-stream": "^1.1.0",
+            "once": "^1.3.1"
+          }
+        }
+      }
+    },
     "punycode": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@@ -1447,6 +3559,66 @@
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
       "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
     },
+    "querystring": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+      "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+      "dev": true
+    },
+    "querystring-es3": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+      "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+      "dev": true
+    },
+    "randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "randomfill": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+      "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+      "dev": true,
+      "requires": {
+        "randombytes": "^2.0.5",
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.7",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+      "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+      "dev": true,
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "dev": true
+        }
+      }
+    },
     "readdirp": {
       "version": "3.2.0",
       "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz",
@@ -1456,6 +3628,16 @@
         "picomatch": "^2.0.4"
       }
     },
+    "regex-not": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+      "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^3.0.2",
+        "safe-regex": "^1.1.0"
+      }
+    },
     "regexp.prototype.flags": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
@@ -1465,6 +3647,25 @@
         "es-abstract": "^1.17.0-next.1"
       }
     },
+    "remove-trailing-separator": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+      "dev": true,
+      "optional": true
+    },
+    "repeat-element": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+      "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+      "dev": true
+    },
+    "repeat-string": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+      "dev": true
+    },
     "request": {
       "version": "2.88.2",
       "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
@@ -1513,6 +3714,56 @@
         "path-parse": "^1.0.6"
       }
     },
+    "resolve-cwd": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+      "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+      "dev": true,
+      "requires": {
+        "resolve-from": "^3.0.0"
+      }
+    },
+    "resolve-dir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
+      "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
+      "dev": true,
+      "requires": {
+        "expand-tilde": "^2.0.0",
+        "global-modules": "^1.0.0"
+      },
+      "dependencies": {
+        "global-modules": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
+          "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
+          "dev": true,
+          "requires": {
+            "global-prefix": "^1.0.1",
+            "is-windows": "^1.0.1",
+            "resolve-dir": "^1.0.0"
+          }
+        }
+      }
+    },
+    "resolve-from": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+      "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+      "dev": true
+    },
+    "resolve-url": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+      "dev": true
+    },
+    "ret": {
+      "version": "0.1.15",
+      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+      "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+      "dev": true
+    },
     "rimraf": {
       "version": "2.7.1",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -1522,27 +3773,129 @@
         "glob": "^7.1.3"
       }
     },
+    "ripemd160": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+      "dev": true,
+      "requires": {
+        "hash-base": "^3.0.0",
+        "inherits": "^2.0.1"
+      }
+    },
+    "run-queue": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+      "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.1.1"
+      }
+    },
     "safe-buffer": {
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
       "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
     },
+    "safe-regex": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+      "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+      "dev": true,
+      "requires": {
+        "ret": "~0.1.10"
+      }
+    },
     "safer-buffer": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
+    "schema-utils": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+      "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.1.0",
+        "ajv-errors": "^1.0.0",
+        "ajv-keywords": "^3.1.0"
+      }
+    },
     "semver": {
       "version": "7.3.2",
       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
       "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
     },
+    "serialize-javascript": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
+      "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==",
+      "dev": true,
+      "requires": {
+        "randombytes": "^2.1.0"
+      }
+    },
     "set-blocking": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
       "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
       "dev": true
     },
+    "set-value": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+      "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^2.0.1",
+        "is-extendable": "^0.1.1",
+        "is-plain-object": "^2.0.3",
+        "split-string": "^3.0.1"
+      },
+      "dependencies": {
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+      "dev": true
+    },
+    "sha.js": {
+      "version": "2.4.11",
+      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+      "dev": true,
+      "requires": {
+        "shebang-regex": "^1.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+      "dev": true
+    },
     "side-channel": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz",
@@ -1584,6 +3937,177 @@
         }
       }
     },
+    "snapdragon": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+      "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+      "dev": true,
+      "requires": {
+        "base": "^0.11.1",
+        "debug": "^2.2.0",
+        "define-property": "^0.2.5",
+        "extend-shallow": "^2.0.1",
+        "map-cache": "^0.2.2",
+        "source-map": "^0.5.6",
+        "source-map-resolve": "^0.5.0",
+        "use": "^3.1.0"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "snapdragon-node": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+      "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+      "dev": true,
+      "requires": {
+        "define-property": "^1.0.0",
+        "isobject": "^3.0.0",
+        "snapdragon-util": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "snapdragon-util": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+      "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.2.0"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "source-list-map": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+      "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
+      "dev": true
+    },
+    "source-map": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+      "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+      "dev": true
+    },
+    "source-map-resolve": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
+      "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
+      "dev": true,
+      "requires": {
+        "atob": "^2.1.2",
+        "decode-uri-component": "^0.2.0",
+        "resolve-url": "^0.2.1",
+        "source-map-url": "^0.4.0",
+        "urix": "^0.1.0"
+      }
+    },
+    "source-map-support": {
+      "version": "0.5.19",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+      "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "source-map-url": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+      "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+      "dev": true
+    },
+    "split-string": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+      "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^3.0.0"
+      }
+    },
     "sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -1606,6 +4130,75 @@
         "tweetnacl": "~0.14.0"
       }
     },
+    "ssri": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+      "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+      "dev": true,
+      "requires": {
+        "figgy-pudding": "^3.5.1"
+      }
+    },
+    "static-extend": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+      "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+      "dev": true,
+      "requires": {
+        "define-property": "^0.2.5",
+        "object-copy": "^0.1.0"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        }
+      }
+    },
+    "stream-browserify": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+      "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
+      "dev": true,
+      "requires": {
+        "inherits": "~2.0.1",
+        "readable-stream": "^2.0.2"
+      }
+    },
+    "stream-each": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
+      "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.1.0",
+        "stream-shift": "^1.0.0"
+      }
+    },
+    "stream-http": {
+      "version": "2.8.3",
+      "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
+      "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
+      "dev": true,
+      "requires": {
+        "builtin-status-codes": "^3.0.0",
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.3.6",
+        "to-arraybuffer": "^1.0.0",
+        "xtend": "^4.0.0"
+      }
+    },
+    "stream-shift": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
+      "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
+      "dev": true
+    },
     "string-width": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -1654,6 +4247,23 @@
         "es-abstract": "^1.17.5"
       }
     },
+    "string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.1.0"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "dev": true
+        }
+      }
+    },
     "strip-ansi": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@@ -1678,6 +4288,119 @@
         "has-flag": "^3.0.0"
       }
     },
+    "tapable": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+      "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+      "dev": true
+    },
+    "terser": {
+      "version": "4.8.0",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
+      "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
+      "dev": true,
+      "requires": {
+        "commander": "^2.20.0",
+        "source-map": "~0.6.1",
+        "source-map-support": "~0.5.12"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "terser-webpack-plugin": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz",
+      "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==",
+      "dev": true,
+      "requires": {
+        "cacache": "^12.0.2",
+        "find-cache-dir": "^2.1.0",
+        "is-wsl": "^1.1.0",
+        "schema-utils": "^1.0.0",
+        "serialize-javascript": "^3.1.0",
+        "source-map": "^0.6.1",
+        "terser": "^4.1.2",
+        "webpack-sources": "^1.4.0",
+        "worker-farm": "^1.7.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "through2": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+      "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+      "dev": true,
+      "requires": {
+        "readable-stream": "~2.3.6",
+        "xtend": "~4.0.1"
+      }
+    },
+    "timers-browserify": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz",
+      "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==",
+      "dev": true,
+      "requires": {
+        "setimmediate": "^1.0.4"
+      }
+    },
+    "to-arraybuffer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+      "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+      "dev": true
+    },
+    "to-object-path": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+      "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "to-regex": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+      "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+      "dev": true,
+      "requires": {
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "regex-not": "^1.0.2",
+        "safe-regex": "^1.1.0"
+      }
+    },
     "to-regex-range": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -1700,6 +4423,27 @@
       "version": "file:third_party/tree-kill",
       "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="
     },
+    "ts-loader": {
+      "version": "7.0.5",
+      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-7.0.5.tgz",
+      "integrity": "sha512-zXypEIT6k3oTc+OZNx/cqElrsbBtYqDknf48OZos0NQ3RTt045fBIU8RRSu+suObBzYB355aIPGOe/3kj9h7Ig==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.3.0",
+        "enhanced-resolve": "^4.0.0",
+        "loader-utils": "^1.0.2",
+        "micromatch": "^4.0.0",
+        "semver": "^6.0.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
     "tslib": {
       "version": "1.13.0",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
@@ -1744,6 +4488,12 @@
         "tslib": "^1.8.1"
       }
     },
+    "tty-browserify": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+      "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+      "dev": true
+    },
     "tunnel-agent": {
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -1763,18 +4513,107 @@
       "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
       "dev": true
     },
-    "typescript": {
-      "version": "3.9.5",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz",
-      "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==",
+    "typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
       "dev": true
     },
+    "typescript": {
+      "version": "3.9.6",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz",
+      "integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==",
+      "dev": true
+    },
+    "union-value": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+      "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+      "dev": true,
+      "requires": {
+        "arr-union": "^3.1.0",
+        "get-value": "^2.0.6",
+        "is-extendable": "^0.1.1",
+        "set-value": "^2.0.1"
+      }
+    },
+    "unique-filename": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+      "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+      "dev": true,
+      "requires": {
+        "unique-slug": "^2.0.0"
+      }
+    },
+    "unique-slug": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+      "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+      "dev": true,
+      "requires": {
+        "imurmurhash": "^0.1.4"
+      }
+    },
     "universalify": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
       "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
       "dev": true
     },
+    "unset-value": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+      "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+      "dev": true,
+      "requires": {
+        "has-value": "^0.3.1",
+        "isobject": "^3.0.0"
+      },
+      "dependencies": {
+        "has-value": {
+          "version": "0.3.1",
+          "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+          "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+          "dev": true,
+          "requires": {
+            "get-value": "^2.0.3",
+            "has-values": "^0.1.4",
+            "isobject": "^2.0.0"
+          },
+          "dependencies": {
+            "isobject": {
+              "version": "2.1.0",
+              "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+              "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+              "dev": true,
+              "requires": {
+                "isarray": "1.0.0"
+              }
+            }
+          }
+        },
+        "has-values": {
+          "version": "0.1.4",
+          "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+          "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+          "dev": true
+        },
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        }
+      }
+    },
+    "upath": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+      "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
+      "dev": true,
+      "optional": true
+    },
     "uri-js": {
       "version": "4.2.2",
       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
@@ -1783,11 +4622,70 @@
         "punycode": "^2.1.0"
       }
     },
+    "urix": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+      "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+      "dev": true
+    },
+    "url": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+      "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+      "dev": true,
+      "requires": {
+        "punycode": "1.3.2",
+        "querystring": "0.2.0"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+          "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+          "dev": true
+        }
+      }
+    },
+    "use": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+      "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+      "dev": true
+    },
+    "util": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
+      "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+          "dev": true
+        }
+      }
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
     "uuid": {
       "version": "3.4.0",
       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
       "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
     },
+    "v8-compile-cache": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
+      "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
+      "dev": true
+    },
     "verror": {
       "version": "1.10.0",
       "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
@@ -1798,6 +4696,12 @@
         "extsprintf": "^1.2.0"
       }
     },
+    "vm-browserify": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
+      "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
+      "dev": true
+    },
     "vscode-debugadapter": {
       "version": "1.41.0",
       "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.41.0.tgz",
@@ -1818,12 +4722,12 @@
       "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A=="
     },
     "vscode-languageclient": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.0.tgz",
-      "integrity": "sha512-Tcp0VoOaa0YzxL4nEfK9tsmcy76Eo8jNLvFQZwh2c8oMm02luL8uGYPLQNAiZ3XGgegfcwiQFZMqbW7DNV0vxA==",
+      "version": "6.1.3",
+      "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz",
+      "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==",
       "requires": {
         "semver": "^6.3.0",
-        "vscode-languageserver-protocol": "^3.15.2"
+        "vscode-languageserver-protocol": "^3.15.3"
       },
       "dependencies": {
         "semver": {
@@ -1858,6 +4762,284 @@
         "rimraf": "^2.6.3"
       }
     },
+    "watchpack": {
+      "version": "1.7.2",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz",
+      "integrity": "sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g==",
+      "dev": true,
+      "requires": {
+        "chokidar": "^3.4.0",
+        "graceful-fs": "^4.1.2",
+        "neo-async": "^2.5.0",
+        "watchpack-chokidar2": "^2.0.0"
+      },
+      "dependencies": {
+        "chokidar": {
+          "version": "3.4.0",
+          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
+          "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "anymatch": "~3.1.1",
+            "braces": "~3.0.2",
+            "fsevents": "~2.1.2",
+            "glob-parent": "~5.1.0",
+            "is-binary-path": "~2.1.0",
+            "is-glob": "~4.0.1",
+            "normalize-path": "~3.0.0",
+            "readdirp": "~3.4.0"
+          }
+        },
+        "readdirp": {
+          "version": "3.4.0",
+          "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
+          "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "picomatch": "^2.2.1"
+          }
+        }
+      }
+    },
+    "watchpack-chokidar2": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz",
+      "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "chokidar": "^2.1.8"
+      },
+      "dependencies": {
+        "anymatch": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+          "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "micromatch": "^3.1.4",
+            "normalize-path": "^2.1.1"
+          },
+          "dependencies": {
+            "normalize-path": {
+              "version": "2.1.1",
+              "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+              "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "remove-trailing-separator": "^1.0.1"
+              }
+            }
+          }
+        },
+        "binary-extensions": {
+          "version": "1.13.1",
+          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+          "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+          "dev": true,
+          "optional": true
+        },
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "chokidar": {
+          "version": "2.1.8",
+          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+          "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "anymatch": "^2.0.0",
+            "async-each": "^1.0.1",
+            "braces": "^2.3.2",
+            "fsevents": "^1.2.7",
+            "glob-parent": "^3.1.0",
+            "inherits": "^2.0.3",
+            "is-binary-path": "^1.0.0",
+            "is-glob": "^4.0.0",
+            "normalize-path": "^3.0.0",
+            "path-is-absolute": "^1.0.0",
+            "readdirp": "^2.2.1",
+            "upath": "^1.1.1"
+          }
+        },
+        "fill-range": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "extend-shallow": "^2.0.1",
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1",
+            "to-regex-range": "^2.1.0"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "fsevents": {
+          "version": "1.2.13",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+          "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "bindings": "^1.5.0",
+            "nan": "^2.12.1"
+          }
+        },
+        "glob-parent": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "is-glob": "^3.1.0",
+            "path-dirname": "^1.0.0"
+          },
+          "dependencies": {
+            "is-glob": {
+              "version": "3.1.0",
+              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+              "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "is-extglob": "^2.1.0"
+              }
+            }
+          }
+        },
+        "is-binary-path": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+          "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "binary-extensions": "^1.0.0"
+          }
+        },
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true,
+          "optional": true
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "micromatch": {
+          "version": "3.1.10",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "arr-diff": "^4.0.0",
+            "array-unique": "^0.3.2",
+            "braces": "^2.3.1",
+            "define-property": "^2.0.2",
+            "extend-shallow": "^3.0.2",
+            "extglob": "^2.0.4",
+            "fragment-cache": "^0.2.1",
+            "kind-of": "^6.0.2",
+            "nanomatch": "^1.2.9",
+            "object.pick": "^1.3.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.2"
+          }
+        },
+        "readdirp": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+          "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "graceful-fs": "^4.1.11",
+            "micromatch": "^3.1.10",
+            "readable-stream": "^2.0.2"
+          }
+        },
+        "to-regex-range": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+          "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1"
+          }
+        }
+      }
+    },
     "web-request": {
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/web-request/-/web-request-1.0.7.tgz",
@@ -1866,12 +5048,212 @@
         "request": "^2.69.0"
       }
     },
-    "websocket-driver": {
-      "version": "0.7.3",
-      "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz",
-      "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==",
+    "webpack": {
+      "version": "4.43.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz",
+      "integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==",
+      "dev": true,
       "requires": {
-        "http-parser-js": ">=0.4.0 <0.4.11",
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-module-context": "1.9.0",
+        "@webassemblyjs/wasm-edit": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0",
+        "acorn": "^6.4.1",
+        "ajv": "^6.10.2",
+        "ajv-keywords": "^3.4.1",
+        "chrome-trace-event": "^1.0.2",
+        "enhanced-resolve": "^4.1.0",
+        "eslint-scope": "^4.0.3",
+        "json-parse-better-errors": "^1.0.2",
+        "loader-runner": "^2.4.0",
+        "loader-utils": "^1.2.3",
+        "memory-fs": "^0.4.1",
+        "micromatch": "^3.1.10",
+        "mkdirp": "^0.5.3",
+        "neo-async": "^2.6.1",
+        "node-libs-browser": "^2.2.1",
+        "schema-utils": "^1.0.0",
+        "tapable": "^1.1.3",
+        "terser-webpack-plugin": "^1.4.3",
+        "watchpack": "^1.6.1",
+        "webpack-sources": "^1.4.1"
+      },
+      "dependencies": {
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "dev": true,
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "fill-range": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+          "dev": true,
+          "requires": {
+            "extend-shallow": "^2.0.1",
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1",
+            "to-regex-range": "^2.1.0"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "kind-of": {
+              "version": "3.2.2",
+              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+              "dev": true,
+              "requires": {
+                "is-buffer": "^1.1.5"
+              }
+            }
+          }
+        },
+        "memory-fs": {
+          "version": "0.4.1",
+          "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+          "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+          "dev": true,
+          "requires": {
+            "errno": "^0.1.3",
+            "readable-stream": "^2.0.1"
+          }
+        },
+        "micromatch": {
+          "version": "3.1.10",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+          "dev": true,
+          "requires": {
+            "arr-diff": "^4.0.0",
+            "array-unique": "^0.3.2",
+            "braces": "^2.3.1",
+            "define-property": "^2.0.2",
+            "extend-shallow": "^3.0.2",
+            "extglob": "^2.0.4",
+            "fragment-cache": "^0.2.1",
+            "kind-of": "^6.0.2",
+            "nanomatch": "^1.2.9",
+            "object.pick": "^1.3.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.2"
+          }
+        },
+        "to-regex-range": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+          "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+          "dev": true,
+          "requires": {
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1"
+          }
+        }
+      }
+    },
+    "webpack-cli": {
+      "version": "3.3.12",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz",
+      "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.4.2",
+        "cross-spawn": "^6.0.5",
+        "enhanced-resolve": "^4.1.1",
+        "findup-sync": "^3.0.0",
+        "global-modules": "^2.0.0",
+        "import-local": "^2.0.0",
+        "interpret": "^1.4.0",
+        "loader-utils": "^1.4.0",
+        "supports-color": "^6.1.0",
+        "v8-compile-cache": "^2.1.1",
+        "yargs": "^13.3.2"
+      },
+      "dependencies": {
+        "supports-color": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "webpack-sources": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
+      "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
+      "dev": true,
+      "requires": {
+        "source-list-map": "^2.0.0",
+        "source-map": "~0.6.1"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "websocket-driver": {
+      "version": "0.7.4",
+      "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+      "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+      "requires": {
+        "http-parser-js": ">=0.5.1",
         "safe-buffer": ">=5.1.0",
         "websocket-extensions": ">=0.1.1"
       }
@@ -1941,6 +5323,15 @@
         "string-width": "^1.0.2 || 2"
       }
     },
+    "worker-farm": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+      "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+      "dev": true,
+      "requires": {
+        "errno": "~0.1.7"
+      }
+    },
     "wrap-ansi": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
@@ -1985,12 +5376,24 @@
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
     },
+    "xtend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+      "dev": true
+    },
     "y18n": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
       "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
       "dev": true
     },
+    "yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "dev": true
+    },
     "yargs": {
       "version": "13.3.2",
       "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
diff --git a/package.json b/package.json
index ad10ee1..480cf68 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "go",
   "displayName": "Go",
-  "version": "0.15.2",
+  "version": "0.16.1",
   "publisher": "golang",
   "description": "Rich Go language support for Visual Studio Code",
   "author": {
@@ -33,13 +33,15 @@
   ],
   "scripts": {
     "vscode:prepublish": "npm run compile",
-    "compile": "tsc -p ./",
+    "webpack": "webpack --mode development",
+    "webpack-dev": "webpack --mode development --watch",
+    "test-compile": "tsc -p ./",
+    "compile": "webpack --mode production",
     "watch": "tsc -watch -p ./",
-    "pretest": "npm run compile",
-    "test": "node ./out/test/runTest.js",
+    "test": "npm run test-compile && node ./out/test/runTest.js",
     "lint": "node ./node_modules/tslint/bin/tslint --project tsconfig.json",
     "fix-lint": "node ./node_modules/tslint/bin/tslint --fix --project tsconfig.json",
-    "unit-test": "node ./node_modules/mocha/bin/_mocha -u tdd --timeout 5000 --colors ./out/test/unit",
+    "unit-test": "npm run test-compile && node ./node_modules/mocha/bin/_mocha -u tdd --timeout 5000 --colors ./out/test/unit",
     "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\""
   },
   "extensionDependencies": [],
@@ -47,13 +49,13 @@
     "deep-equal": "^2.0.2",
     "diff": "^4.0.2",
     "glob": "^7.1.6",
-    "json-rpc2": "^1.0.2",
+    "json-rpc2": "^2.0.0",
     "moment": "^2.24.0",
     "semver": "^7.3.2",
     "tree-kill": "file:third_party/tree-kill",
     "vscode-debugadapter": "^1.40.0",
     "vscode-debugprotocol": "^1.40.0",
-    "vscode-languageclient": "6.1.0",
+    "vscode-languageclient": "^6.1.3",
     "web-request": "^1.0.7"
   },
   "devDependencies": {
@@ -69,15 +71,19 @@
     "adm-zip": "^0.4.14",
     "fs-extra": "^9.0.0",
     "mocha": "^7.1.1",
+    "nan": "^2.14.1",
     "prettier": "^2.0.4",
     "sinon": "^9.0.2",
+    "ts-loader": "^7.0.5",
     "tslint": "^6.1.1",
     "typescript": "^3.8.3",
     "vscode-test": "^1.3.0",
+    "webpack": "^4.43.0",
+    "webpack-cli": "^3.3.12",
     "yarn": "^1.22.4"
   },
   "engines": {
-    "vscode": "^1.41.0"
+    "vscode": "^1.46.0"
   },
   "activationEvents": [
     "workspaceContains:**/*.go",
@@ -86,7 +92,7 @@
     "onCommand:go.tools.install",
     "onDebugResolve:go"
   ],
-  "main": "./out/src/goMain",
+  "main": "./dist/goMain.js",
   "contributes": {
     "languages": [
       {
@@ -361,7 +367,7 @@
       {
         "type": "go",
         "label": "Go",
-        "program": "./out/src/debugAdapter/goDebug.js",
+        "program": "./dist/debugAdapter.js",
         "runtime": "node",
         "languages": [
           "go"
@@ -750,6 +756,381 @@
             }
           }
         }
+      },
+      {
+        "type": "godlvdap",
+        "label": "Go Dlv Dap (Experimental)",
+        "program": "./dist/debugAdapter2.js",
+        "runtime": "node",
+        "languages": [
+          "go"
+        ],
+        "configurationSnippets": [
+          {
+            "label": "Go: Launch package",
+            "description": "Debug the package in the program attribute",
+            "body": {
+              "name": "${2:Launch Package}",
+              "type": "godlvdap",
+              "request": "launch",
+              "mode": "debug",
+              "program": "^\"\\${workspaceFolder}${1:}\""
+            }
+          },
+          {
+            "label": "Go: Launch file",
+            "description": "Debug the file in the program attribute",
+            "body": {
+              "name": "${2:Launch file}",
+              "type": "godlvdap",
+              "request": "launch",
+              "mode": "debug",
+              "program": "^\"${1:\\${file\\}}\""
+            }
+          },
+          {
+            "label": "Go: Launch test package",
+            "description": "Debug the test package in the program attribute",
+            "body": {
+              "name": "${2:Launch test package}",
+              "type": "godlvdap",
+              "request": "launch",
+              "mode": "test",
+              "program": "^\"\\${workspaceFolder}${1:}\""
+            }
+          },
+          {
+            "label": "Go: Launch test function",
+            "description": "Debug the test function in the args, ensure program attributes points to right package",
+            "body": {
+              "name": "${3:Launch test function}",
+              "type": "godlvdap",
+              "request": "launch",
+              "mode": "test",
+              "program": "^\"\\${workspaceFolder}${1:}\"",
+              "args": [
+                "-test.run",
+                "${2:MyTestFunction}"
+              ]
+            }
+          },
+          {
+            "label": "Go: Attach to local process",
+            "description": "Attach to an existing process by process ID",
+            "body": {
+              "name": "${1:Attach to Process}",
+              "type": "godlvdap",
+              "request": "attach",
+              "mode": "local",
+              "processId": 0
+            }
+          },
+          {
+            "label": "Go: Connect to server",
+            "description": "Connect to a remote headless debug server",
+            "body": {
+              "name": "${1:Connect to server}",
+              "type": "godlvdap",
+              "request": "attach",
+              "mode": "remote",
+              "remotePath": "^\"\\${workspaceFolder}\"",
+              "port": 2345,
+              "host": "127.0.0.1"
+            }
+          }
+        ],
+        "configurationAttributes": {
+          "launch": {
+            "required": [],
+            "properties": {
+              "program": {
+                "type": "string",
+                "description": "Path to the program folder (or any file within that folder) when in 'debug' or 'test' mode, and to the pre-built binary file to debug in 'exec' mode.",
+                "default": "${workspaceFolder}"
+              },
+              "mode": {
+                "enum": [
+                  "auto",
+                  "debug",
+                  "test",
+                  "exec"
+                ],
+                "description": "One of 'auto', 'debug', 'test', 'exec'.",
+                "default": "auto"
+              },
+              "stopOnEntry": {
+                "type": "boolean",
+                "description": "Automatically stop program after launch.",
+                "default": false
+              },
+              "args": {
+                "type": "array",
+                "description": "Command line arguments passed to the program.",
+                "items": {
+                  "type": "string"
+                },
+                "default": []
+              },
+              "showLog": {
+                "type": "boolean",
+                "description": "Show log output from the delve debugger.",
+                "default": false
+              },
+              "cwd": {
+                "type": "string",
+                "description": "Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.",
+                "default": "."
+              },
+              "env": {
+                "type": "object",
+                "description": "Environment variables passed to the program.",
+                "default": {}
+              },
+              "buildFlags": {
+                "type": "string",
+                "description": "Build flags, to be passed to the Go compiler.",
+                "default": ""
+              },
+              "init": {
+                "type": "string",
+                "description": "Init file, executed by the terminal client.",
+                "default": ""
+              },
+              "remotePath": {
+                "type": "string",
+                "description": "Absolute path to the file being debugged on the remote machine in case of remote debugging.",
+                "default": ""
+              },
+              "port": {
+                "type": "number",
+                "description": "The port that the delve debugger will be listening on.",
+                "default": 2345
+              },
+              "host": {
+                "type": "string",
+                "description": "The host name of the machine the delve debugger will be listening on.",
+                "default": "127.0.0.1"
+              },
+              "trace": {
+                "type": "string",
+                "enum": [
+                  "log",
+                  "verbose",
+                  "error"
+                ],
+                "default": "error",
+                "description": "Various levels of logging shown in the debug console. When set to 'log' or 'verbose', the logs will also be written to a file."
+              },
+              "envFile": {
+                "type": [
+                  "string",
+                  "array"
+                ],
+                "items": {
+                  "type": "string"
+                },
+                "description": "Absolute path to a file containing environment variable definitions. Multiple files can be specified by provided an array of absolute paths",
+                "default": "${workspaceFolder}/.env"
+              },
+              "backend": {
+                "type": "string",
+                "enum": [
+                  "default",
+                  "native",
+                  "lldb"
+                ],
+                "description": "Backend used by delve. Only available in delve version 0.12.2 and above."
+              },
+              "output": {
+                "type": "string",
+                "description": "Output path for the binary of delve",
+                "default": "debug"
+              },
+              "logOutput": {
+                "type": "string",
+                "enum": [
+                  "debugger",
+                  "gdbwire",
+                  "lldbout",
+                  "debuglineerr",
+                  "dap"
+                ],
+                "description": "Comma separated list of components that should produce debug output.",
+                "default": "debugger"
+              },
+              "dlvLoadConfig": {
+                "type": "object",
+                "properties": {
+                  "followPointers": {
+                    "type": "boolean",
+                    "description": "FollowPointers requests pointers to be automatically dereferenced",
+                    "default": true
+                  },
+                  "maxVariableRecurse": {
+                    "type": "number",
+                    "description": "MaxVariableRecurse is how far to recurse when evaluating nested types",
+                    "default": 1
+                  },
+                  "maxStringLen": {
+                    "type": "number",
+                    "description": "MaxStringLen is the maximum number of bytes read from a string",
+                    "default": 64
+                  },
+                  "maxArrayValues": {
+                    "type": "number",
+                    "description": "MaxArrayValues is the maximum number of elements read from an array, a slice or a map",
+                    "default": 64
+                  },
+                  "maxStructFields": {
+                    "type": "number",
+                    "description": "MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields",
+                    "default": -1
+                  }
+                },
+                "description": "LoadConfig describes to delve, how to load values from target's memory",
+                "default": {
+                  "followPointers": true,
+                  "maxVariableRecurse": 1,
+                  "maxStringLen": 64,
+                  "maxArrayValues": 64,
+                  "maxStructFields": -1
+                }
+              },
+              "stackTraceDepth": {
+                "type": "number",
+                "description": "Maximum depth of stack trace collected from Delve",
+                "default": 50
+              },
+              "showGlobalVariables": {
+                "type": "boolean",
+                "default": true,
+                "description": "Boolean value to indicate whether global package variables should be shown in the variables pane or not."
+              }
+            }
+          },
+          "attach": {
+            "required": [],
+            "properties": {
+              "processId": {
+                "type": "number",
+                "description": "The ID of the process to be debugged."
+              },
+              "mode": {
+                "enum": [
+                  "local",
+                  "remote"
+                ],
+                "description": "Indicates local or remote debugging.  Local maps to the dlv 'attach' command, remote maps to 'connect'.",
+                "default": "local"
+              },
+              "showLog": {
+                "type": "boolean",
+                "description": "Show log output from the delve debugger.",
+                "default": false
+              },
+              "cwd": {
+                "type": "string",
+                "description": "Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.",
+                "default": "${workspaceFolder}"
+              },
+              "remotePath": {
+                "type": "string",
+                "description": "If remote debugging, the path to the source code on the remote machine, if different from the local machine.",
+                "default": ""
+              },
+              "port": {
+                "type": "number",
+                "description": "The port that the delve debugger will be listening on.",
+                "default": 2345
+              },
+              "host": {
+                "type": "string",
+                "description": "The host name of the machine the delve debugger will be listening on.",
+                "default": "127.0.0.1"
+              },
+              "trace": {
+                "type": "string",
+                "enum": [
+                  "log",
+                  "verbose",
+                  "error"
+                ],
+                "default": "error",
+                "description": "Various levels of logging shown in the debug console. When set to 'log' or 'verbose', the logs will also be written to a file."
+              },
+              "backend": {
+                "type": "string",
+                "enum": [
+                  "default",
+                  "native",
+                  "lldb"
+                ],
+                "description": "Backend used by delve. Only available in delve version 0.12.2 and above."
+              },
+              "logOutput": {
+                "type": "string",
+                "enum": [
+                  "debugger",
+                  "gdbwire",
+                  "lldbout",
+                  "debuglineerr",
+                  "dap",
+                  "rpc"
+                ],
+                "description": "Comma separated list of components that should produce debug output.",
+                "default": "debugger"
+              },
+              "dlvLoadConfig": {
+                "type": "object",
+                "properties": {
+                  "followPointers": {
+                    "type": "boolean",
+                    "description": "FollowPointers requests pointers to be automatically dereferenced",
+                    "default": true
+                  },
+                  "maxVariableRecurse": {
+                    "type": "number",
+                    "description": "MaxVariableRecurse is how far to recurse when evaluating nested types",
+                    "default": 1
+                  },
+                  "maxStringLen": {
+                    "type": "number",
+                    "description": "MaxStringLen is the maximum number of bytes read from a string",
+                    "default": 64
+                  },
+                  "maxArrayValues": {
+                    "type": "number",
+                    "description": "MaxArrayValues is the maximum number of elements read from an array, a slice or a map",
+                    "default": 64
+                  },
+                  "maxStructFields": {
+                    "type": "number",
+                    "description": "MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields",
+                    "default": -1
+                  }
+                },
+                "description": "LoadConfig describes to delve, how to load values from target's memory",
+                "default": {
+                  "followPointers": true,
+                  "maxVariableRecurse": 1,
+                  "maxStringLen": 64,
+                  "maxArrayValues": 64,
+                  "maxStructFields": -1
+                }
+              },
+              "stackTraceDepth": {
+                "type": "number",
+                "description": "Maximum depth of stack trace collected from Delve",
+                "default": 50
+              },
+              "showGlobalVariables": {
+                "type": "boolean",
+                "default": true,
+                "description": "Boolean value to indicate whether global package variables should be shown in the variables pane or not."
+              }
+            }
+          }
+        }
       }
     ],
     "configuration": {
@@ -999,6 +1380,7 @@
               "description": "Gutter style to indicate covered code."
             }
           },
+          "additionalProperties": false,
           "default": {
             "type": "highlight",
             "coveredHighlightColor": "rgba(64,128,128,0.5)",
@@ -1137,6 +1519,7 @@
               "description": "If true, the language server will provide clickable Godoc links for import statements."
             }
           },
+          "additionalProperties": false,
           "default": {
             "diagnostics": true,
             "documentLink": true
@@ -1184,6 +1567,7 @@
               "description": "If true, enables code lens for running and debugging tests"
             }
           },
+          "additionalProperties": false,
           "default": {
             "references": false,
             "runtest": true
@@ -1219,6 +1603,7 @@
               "description": "Transformation rule used by Go: Add Tags command to add tags"
             }
           },
+          "additionalProperties": false,
           "default": {
             "tags": "json",
             "options": "json=omitempty",
@@ -1242,6 +1627,7 @@
               "description": "The number of milliseconds to delay before execution. Resets with each keystroke."
             }
           },
+          "additionalProperties": false,
           "default": {
             "enabled": false,
             "delay": 500
@@ -1268,6 +1654,7 @@
               "description": "Comma separated tag=options pairs to be used by Go: Remove Tags command"
             }
           },
+          "additionalProperties": false,
           "default": {
             "tags": "",
             "options": "",
@@ -1296,6 +1683,7 @@
             },
             "description": "The flags configured here will be passed through to command `goplay`"
           },
+          "additionalProperties": false,
           "default": {
             "openbrowser": true,
             "share": true,
@@ -1376,6 +1764,7 @@
               "description": "If true, adds command to debug the test under the cursor to the editor context menu"
             }
           },
+          "additionalProperties": false,
           "default": {
             "toggleTestFile": true,
             "addTags": true,
@@ -1509,7 +1898,8 @@
               "default": "guru",
               "description": "Alternate tool to use instead of the guru binary or alternate path to use for the guru binary."
             }
-          }
+          },
+          "additionalProperties": false
         }
       }
     },
diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts
index 0dc9901..b784148 100644
--- a/src/debugAdapter/goDebug.ts
+++ b/src/debugAdapter/goDebug.ts
@@ -11,7 +11,6 @@
 import { Client, RPCConnection } from 'json-rpc2';
 import * as os from 'os';
 import * as path from 'path';
-import kill = require('tree-kill');
 import * as util from 'util';
 import {
 	DebugSession,
@@ -37,7 +36,8 @@
 	getCurrentGoWorkspaceFromGOPATH,
 	getInferredGopath,
 	parseEnvFile
-} from '../goPath';
+} from '../utils/goPath';
+import {killProcessTree} from '../utils/processUtils';
 
 const fsAccess = util.promisify(fs.access);
 const fsUnlink = util.promisify(fs.unlink);
@@ -514,7 +514,7 @@
 						} or ${envPath}`
 					);
 					return reject(
-						`Cannot find Delve debugger. Install from https://github.com/derekparker/delve & ensure it is in your Go tools path, "GOPATH/bin" or "PATH".`
+						`Cannot find Delve debugger. Install from https://github.com/go-delve/delve & ensure it is in your Go tools path, "GOPATH/bin" or "PATH".`
 					);
 				}
 
@@ -695,7 +695,7 @@
 	public async close(): Promise<void> {
 		const forceCleanup = async () => {
 			log(`killing debugee (pid: ${this.debugProcess.pid})...`);
-			await killProcessTree(this.debugProcess);
+			await killProcessTree(this.debugProcess, log);
 			await removeFile(this.localDebugeePath);
 		};
 
@@ -2314,23 +2314,6 @@
 	}
 }
 
-function killProcessTree(p: ChildProcess): Promise<void> {
-	if (!p || !p.pid) {
-		log(`no process to kill`);
-		return Promise.resolve();
-	}
-	return new Promise((resolve) => {
-		kill(p.pid, (err) => {
-			if (err) {
-				logError(`Error killing process ${p.pid}: ${err}`);
-			} else {
-				log(`killed process ${p.pid}`);
-			}
-			resolve();
-		});
-	});
-}
-
 // queryGOROOT returns `go env GOROOT`.
 function queryGOROOT(cwd: any, env: any): Promise<string> {
 	return new Promise<string>((resolve) => {
diff --git a/src/debugAdapter2/README.md b/src/debugAdapter2/README.md
new file mode 100644
index 0000000..f0ca4fb
--- /dev/null
+++ b/src/debugAdapter2/README.md
@@ -0,0 +1,6 @@
+# Debug Adapter
+
+This debug adapter is experimental, in-development code. If you
+actually need to debug Go code, please use the default adapter ("type": "go").
+
+See the [contribution documentation](../../docs/contributing.md) to learn how to develop the debug adapter.
diff --git a/src/debugAdapter2/dapClient.ts b/src/debugAdapter2/dapClient.ts
new file mode 100644
index 0000000..14d38a0
--- /dev/null
+++ b/src/debugAdapter2/dapClient.ts
@@ -0,0 +1,100 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+import { EventEmitter } from 'events';
+import stream = require('stream');
+
+import { DebugProtocol } from 'vscode-debugprotocol';
+
+// DapClient implements a simple client for the DAP protocol.
+// It's initialized with a pair of streams that the caller creats and enables
+// sending and receiving DAP messages over these streams.
+// After calling connect():
+//
+//  - For sending messages call send().
+//  - For receiving messages, subscibe to events this class emits.
+//      - 'event', 'respones', 'request' - each carrying an appropriate
+//        DebugProtocol type as an argument.
+export class DAPClient extends EventEmitter {
+	private static readonly TWO_CRLF = '\r\n\r\n';
+
+	private outputStream: stream.Writable;
+
+	private rawData = Buffer.alloc(0);
+	private contentLength: number = -1;
+
+	constructor() {
+		super();
+	}
+
+	public send(req: any): void {
+		const json = JSON.stringify(req);
+		this.outputStream.write(`Content-Length: ${Buffer.byteLength(json, 'utf8')}\r\n\r\n${json}`, 'utf8');
+	}
+
+	// Connect this client to a server, which is represented by read and write
+	// streams. Before this method is called, send() won't work and no messages
+	// from the server will be delivered.
+	protected connect(readable: stream.Readable, writable: stream.Writable): void {
+		this.outputStream = writable;
+
+		readable.on('data', (data: Buffer) => {
+			this.handleData(data);
+		});
+	}
+
+	// Implements parsing of the DAP protocol. We cannot use ProtocolClient
+	// from the vscode-debugadapter package, because it's not exported and
+	// is not meant for external usage.
+	// See https://github.com/microsoft/vscode-debugadapter-node/issues/232
+	private handleData(data: Buffer): void {
+		this.rawData = Buffer.concat([this.rawData, data]);
+
+		while (true) {
+			if (this.contentLength >= 0) {
+				if (this.rawData.length >= this.contentLength) {
+					const message = this.rawData.toString('utf8', 0, this.contentLength);
+					this.rawData = this.rawData.slice(this.contentLength);
+					this.contentLength = -1;
+					if (message.length > 0) {
+						this.dispatch(message);
+					}
+					continue;	// there may be more complete messages to process
+				}
+			} else {
+				const idx = this.rawData.indexOf(DAPClient.TWO_CRLF);
+				if (idx !== -1) {
+					const header = this.rawData.toString('utf8', 0, idx);
+					const lines = header.split('\r\n');
+					for (const line of lines) {
+						const pair = line.split(/: +/);
+						if (pair[0] === 'Content-Length') {
+							this.contentLength = +pair[1];
+						}
+					}
+					this.rawData = this.rawData.slice(idx + DAPClient.TWO_CRLF.length);
+					continue;
+				}
+			}
+			break;
+		}
+	}
+
+	private dispatch(body: string): void {
+		const rawData = JSON.parse(body);
+
+		if (rawData.type === 'event') {
+			const event = <DebugProtocol.Event>rawData;
+			this.emit('event', event);
+		} else if (rawData.type === 'response') {
+			const response = <DebugProtocol.Response>rawData;
+			this.emit('response', response);
+		} else if (rawData.type === 'request') {
+			const request = <DebugProtocol.Request>rawData;
+			this.emit('request', request);
+		} else {
+			throw new Error(`unknown message ${JSON.stringify(rawData)}`);
+		}
+	}
+}
diff --git a/src/debugAdapter2/goDlvDebug.ts b/src/debugAdapter2/goDlvDebug.ts
new file mode 100644
index 0000000..e1c5b2f
--- /dev/null
+++ b/src/debugAdapter2/goDlvDebug.ts
@@ -0,0 +1,788 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+// NOTE: This debug adapter is experimental, in-development code. If you
+// actually need to debug Go code, please use the default adapter.
+
+import { ChildProcess, spawn } from 'child_process';
+import * as fs from 'fs';
+import net = require('net');
+import * as os from 'os';
+import * as path from 'path';
+
+import {
+	logger,
+	Logger,
+	LoggingDebugSession,
+	OutputEvent,
+	TerminatedEvent
+} from 'vscode-debugadapter';
+import { DebugProtocol } from 'vscode-debugprotocol';
+
+import {
+	envPath,
+	getBinPathWithPreferredGopathGoroot,
+	parseEnvFile
+} from '../utils/goPath';
+
+import { killProcessTree } from '../utils/processUtils';
+
+import { DAPClient } from './dapClient';
+
+interface LoadConfig {
+	// FollowPointers requests pointers to be automatically dereferenced.
+	followPointers: boolean;
+	// MaxVariableRecurse is how far to recurse when evaluating nested types.
+	maxVariableRecurse: number;
+	// MaxStringLen is the maximum number of bytes read from a string
+	maxStringLen: number;
+	// MaxArrayValues is the maximum number of elements read from an array, a slice or a map.
+	maxArrayValues: number;
+	// MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields.
+	maxStructFields: number;
+}
+
+// This interface should always match the schema found in `package.json`.
+interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
+	request: 'launch';
+	[key: string]: any;
+	program: string;
+	stopOnEntry?: boolean;
+	args?: string[];
+	showLog?: boolean;
+	logOutput?: string;
+	cwd?: string;
+	env?: { [key: string]: string };
+	mode?: 'auto' | 'debug' | 'remote' | 'test' | 'exec';
+	remotePath?: string;
+	port?: number;
+	host?: string;
+	buildFlags?: string;
+	init?: string;
+	trace?: 'verbose' | 'log' | 'error';
+	/** Optional path to .env file. */
+	envFile?: string | string[];
+	backend?: string;
+	output?: string;
+	/** Delve LoadConfig parameters */
+	dlvLoadConfig?: LoadConfig;
+	dlvToolPath: string;
+	/** Delve Version */
+	apiVersion: number;
+	/** Delve maximum stack trace depth */
+	stackTraceDepth: number;
+
+	showGlobalVariables?: boolean;
+	packagePathToGoModPathMap: { [key: string]: string };
+}
+
+interface AttachRequestArguments extends DebugProtocol.AttachRequestArguments {
+	request: 'attach';
+	processId?: number;
+	stopOnEntry?: boolean;
+	showLog?: boolean;
+	logOutput?: string;
+	cwd?: string;
+	mode?: 'local' | 'remote';
+	remotePath?: string;
+	port?: number;
+	host?: string;
+	trace?: 'verbose' | 'log' | 'error';
+	backend?: string;
+	/** Delve LoadConfig parameters */
+	dlvLoadConfig?: LoadConfig;
+	dlvToolPath: string;
+	/** Delve Version */
+	apiVersion: number;
+	/** Delve maximum stack trace depth */
+	stackTraceDepth: number;
+
+	showGlobalVariables?: boolean;
+}
+
+function logArgsToString(args: any[]): string {
+	return args
+		.map((arg) => {
+			return typeof arg === 'string' ? arg : JSON.stringify(arg);
+		})
+		.join(' ');
+}
+
+function log(...args: any[]) {
+	logger.warn(logArgsToString(args));
+}
+
+function logError(...args: any[]) {
+	logger.error(logArgsToString(args));
+}
+
+// GoDlvDapDebugSession implements a DAP debug adapter to talk to the editor.
+//
+// This adapter serves as a DAP proxy between the editor and the DAP server
+// inside Delve. It relies on functionality inherited from DebugSession to
+// implement the server side interfacing the editor, and on DapClient to
+// implement the client side interfacing Delve:
+//
+//      Editor                GoDlvDapDebugSession                 Delve
+//  +------------+        +--------------+-----------+         +------------+
+//  | DAP Client | <====> | DebugSession | DAPClient |  <====> | DAP Server |
+//  +------------+        +--------------+-----------+         +------------+
+export class GoDlvDapDebugSession extends LoggingDebugSession {
+	private readonly DEFAULT_DELVE_HOST = '127.0.0.1';
+	private readonly DEFAULT_DELVE_PORT = 42042;
+
+	private logLevel: Logger.LogLevel = Logger.LogLevel.Error;
+
+	private dlvClient: DelveClient = null;
+
+	// Child process used to track debugee launched without debugging (noDebug
+	// mode). Either debugProcess or dlvClient are null.
+	private debugProcess: ChildProcess = null;
+
+	public constructor() {
+		super();
+
+		// Invoke logger.init here because we want logging to work in 'inline'
+		// DA mode. It's typically called in the start() method of our parent
+		// class, but this method isn't called in 'inline' mode.
+		logger.init((e) => this.sendEvent(e));
+
+		// this debugger uses zero-based lines and columns
+		this.setDebuggerLinesStartAt1(false);
+		this.setDebuggerColumnsStartAt1(false);
+	}
+
+	protected initializeRequest(
+		response: DebugProtocol.InitializeResponse,
+		args: DebugProtocol.InitializeRequestArguments,
+		request?: DebugProtocol.Request
+	): void {
+		log('InitializeRequest');
+		response.body.supportsConfigurationDoneRequest = true;
+
+		// We respond to InitializeRequest here, because Delve hasn't been
+		// launched yet. Delve will start responding to DAP requests after
+		// LaunchRequest is received, which tell us how to start it.
+
+		// TODO: we could send an InitializeRequest to Delve when
+		// it launches, wait for its response and sanity check the capabilities
+		// it reports. Once DAP support in Delve is complete, this can be part
+		// of making sure that the "dlv" binary we find is sufficiently
+		// up-to-date to talk DAP with us.
+		this.sendResponse(response);
+		log('InitializeResponse');
+	}
+
+	protected launchRequest(
+		response: DebugProtocol.LaunchResponse,
+		args: LaunchRequestArguments,
+		request: DebugProtocol.Request
+	): void {
+		// Setup logger now that we have the 'trace' level passed in from
+		// LaunchRequestArguments.
+		this.logLevel =
+			args.trace === 'verbose'
+				? Logger.LogLevel.Verbose
+				: args.trace === 'log'
+					? Logger.LogLevel.Log
+					: Logger.LogLevel.Error;
+		const logPath =
+			this.logLevel !== Logger.LogLevel.Error ? path.join(os.tmpdir(), 'vscode-godlvdapdebug.txt') : undefined;
+		logger.setup(this.logLevel, logPath);
+		log('launchRequest');
+
+		// In noDebug mode with the 'debug' launch mode, we don't launch Delve
+		// but run the debugee directly.
+		// For other launch modes we currently still defer to Delve, for
+		// compatibility with the old debugAdapter.
+		// See https://github.com/golang/vscode-go/issues/336
+		if (args.noDebug && args.mode === 'debug') {
+			try {
+				this.launchNoDebug(args);
+			} catch (e) {
+				logError(`launchNoDebug failed: "${e}"`);
+				// TODO: define error constants
+				// https://github.com/golang/vscode-go/issues/305
+				this.sendErrorResponse(
+					response,
+					3000,
+					`Failed to launch "${e}"`);
+			}
+			return;
+		}
+
+		if (!args.port) {
+			args.port = this.DEFAULT_DELVE_PORT;
+		}
+		if (!args.host) {
+			args.host = this.DEFAULT_DELVE_HOST;
+		}
+
+		this.dlvClient = new DelveClient(args);
+
+		this.dlvClient.on('stdout', (str) => {
+			log('dlv stdout:', str);
+		});
+
+		this.dlvClient.on('stderr', (str) => {
+			log('dlv stderr:', str);
+		});
+
+		this.dlvClient.on('connected', () => {
+			// Once the client is connected to Delve, forward it the launch
+			// request to begin the actual debugging session.
+			this.dlvClient.send(request);
+		});
+
+		this.dlvClient.on('close', (rc) => {
+			if (rc !== 0) {
+				// TODO: define error constants
+				// https://github.com/golang/vscode-go/issues/305
+				this.sendErrorResponse(
+					response,
+					3000,
+					'Failed to continue: Check the debug console for details.');
+			}
+			log('Sending TerminatedEvent as delve is closed');
+			this.sendEvent(new TerminatedEvent());
+		});
+
+		// Relay events and responses back to vscode. In the future we will
+		// add middleware here to intercept specific kinds of responses/events
+		// for special handling.
+		this.dlvClient.on('event', (event) => {
+			this.sendEvent(event);
+		});
+
+		this.dlvClient.on('response', (resp) => {
+			this.sendResponse(resp);
+		});
+	}
+
+	protected attachRequest(
+		response: DebugProtocol.AttachResponse,
+		args: AttachRequestArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected disconnectRequest(
+		response: DebugProtocol.DisconnectResponse,
+		args: DebugProtocol.DisconnectArguments,
+		request?: DebugProtocol.Request
+	): void {
+		log('DisconnectRequest');
+		// How we handle DisconnectRequest depends on whether Delve was launched
+		// at all.
+		// * In noDebug node, the Go program was spawned directly without
+		//   debugging: this.debugProcess will be non-null, and this.dlvClient
+		//   will be null.
+		// * Otherwise, Delve was spawned: this.debugProcess will be null, and
+		//   this.dlvClient will be non-null.
+		if (this.debugProcess !== null) {
+			log(`killing debugee (pid: ${this.debugProcess.pid})...`);
+
+			// Kill the debugee and notify the client when the killing is
+			// completed, to ensure a clean shutdown sequence.
+			killProcessTree(this.debugProcess, log).then(() => {
+				super.disconnectRequest(response, args);
+				log('DisconnectResponse');
+			});
+		} else if (this.dlvClient !== null) {
+			// Forward this DisconnectRequest to Delve.
+			this.dlvClient.send(request);
+		} else {
+			logError(`both debug process and dlv client are null`);
+			// TODO: define all error codes as constants
+			// https://github.com/golang/vscode-go/issues/305
+			this.sendErrorResponse(
+				response,
+				3000,
+				'Failed to disconnect: Check the debug console for details.');
+		}
+	}
+
+	protected terminateRequest(
+		response: DebugProtocol.TerminateResponse,
+		args: DebugProtocol.TerminateArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected restartRequest(
+		response: DebugProtocol.RestartResponse,
+		args: DebugProtocol.RestartArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setBreakPointsRequest(
+		response: DebugProtocol.SetBreakpointsResponse,
+		args: DebugProtocol.SetBreakpointsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setFunctionBreakPointsRequest(
+		response: DebugProtocol.SetFunctionBreakpointsResponse,
+		args: DebugProtocol.SetFunctionBreakpointsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setExceptionBreakPointsRequest(
+		response: DebugProtocol.SetExceptionBreakpointsResponse,
+		args: DebugProtocol.SetExceptionBreakpointsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected configurationDoneRequest(
+		response: DebugProtocol.ConfigurationDoneResponse,
+		args: DebugProtocol.ConfigurationDoneArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected continueRequest(
+		response: DebugProtocol.ContinueResponse,
+		args: DebugProtocol.ContinueArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected nextRequest(
+		response: DebugProtocol.NextResponse,
+		args: DebugProtocol.NextArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected stepInRequest(
+		response: DebugProtocol.StepInResponse,
+		args: DebugProtocol.StepInArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected stepOutRequest(
+		response: DebugProtocol.StepOutResponse,
+		args: DebugProtocol.StepOutArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected stepBackRequest(
+		response: DebugProtocol.StepBackResponse,
+		args: DebugProtocol.StepBackArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected reverseContinueRequest(
+		response: DebugProtocol.ReverseContinueResponse,
+		args: DebugProtocol.ReverseContinueArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected restartFrameRequest(
+		response: DebugProtocol.RestartFrameResponse,
+		args: DebugProtocol.RestartFrameArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected gotoRequest(
+		response: DebugProtocol.GotoResponse,
+		args: DebugProtocol.GotoArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected pauseRequest(
+		response: DebugProtocol.PauseResponse,
+		args: DebugProtocol.PauseArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected sourceRequest(
+		response: DebugProtocol.SourceResponse,
+		args: DebugProtocol.SourceArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected threadsRequest(
+		response: DebugProtocol.ThreadsResponse,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected terminateThreadsRequest(
+		response: DebugProtocol.TerminateThreadsResponse,
+		args: DebugProtocol.TerminateThreadsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected stackTraceRequest(
+		response: DebugProtocol.StackTraceResponse,
+		args: DebugProtocol.StackTraceArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected scopesRequest(
+		response: DebugProtocol.ScopesResponse,
+		args: DebugProtocol.ScopesArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected variablesRequest(
+		response: DebugProtocol.VariablesResponse,
+		args: DebugProtocol.VariablesArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setVariableRequest(
+		response: DebugProtocol.SetVariableResponse,
+		args: DebugProtocol.SetVariableArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setExpressionRequest(
+		response: DebugProtocol.SetExpressionResponse,
+		args: DebugProtocol.SetExpressionArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected evaluateRequest(
+		response: DebugProtocol.EvaluateResponse,
+		args: DebugProtocol.EvaluateArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected stepInTargetsRequest(
+		response: DebugProtocol.StepInTargetsResponse,
+		args: DebugProtocol.StepInTargetsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected gotoTargetsRequest(
+		response: DebugProtocol.GotoTargetsResponse,
+		args: DebugProtocol.GotoTargetsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected completionsRequest(
+		response: DebugProtocol.CompletionsResponse,
+		args: DebugProtocol.CompletionsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected exceptionInfoRequest(
+		response: DebugProtocol.ExceptionInfoResponse,
+		args: DebugProtocol.ExceptionInfoArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected loadedSourcesRequest(
+		response: DebugProtocol.LoadedSourcesResponse,
+		args: DebugProtocol.LoadedSourcesArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected dataBreakpointInfoRequest(
+		response: DebugProtocol.DataBreakpointInfoResponse,
+		args: DebugProtocol.DataBreakpointInfoArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setDataBreakpointsRequest(
+		response: DebugProtocol.SetDataBreakpointsResponse,
+		args: DebugProtocol.SetDataBreakpointsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected readMemoryRequest(
+		response: DebugProtocol.ReadMemoryResponse,
+		args: DebugProtocol.ReadMemoryArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected disassembleRequest(
+		response: DebugProtocol.DisassembleResponse,
+		args: DebugProtocol.DisassembleArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected cancelRequest(
+		response: DebugProtocol.CancelResponse,
+		args: DebugProtocol.CancelArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected breakpointLocationsRequest(
+		response: DebugProtocol.BreakpointLocationsResponse,
+		args: DebugProtocol.BreakpointLocationsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	protected setInstructionBreakpointsRequest(
+		response: DebugProtocol.SetInstructionBreakpointsResponse,
+		args: DebugProtocol.SetInstructionBreakpointsArguments,
+		request?: DebugProtocol.Request
+	): void {
+		this.dlvClient.send(request);
+	}
+
+	// Launch the debugee process without starting a debugger.
+	// This implements the `Run > Run Without Debugger` functionality in vscode.
+	// Note: this method currently assumes launchArgs.mode === 'debug'.
+	private launchNoDebug(launchArgs: LaunchRequestArguments): void {
+		if (launchArgs.mode !== 'debug') {
+			throw new Error('launchNoDebug requires "debug" mode');
+		}
+		const {program, dirname, programIsDirectory} = parseProgramArgSync(launchArgs);
+		const goRunArgs = ['run'];
+		if (launchArgs.buildFlags) {
+			goRunArgs.push(launchArgs.buildFlags);
+		}
+
+		if (programIsDirectory) {
+			goRunArgs.push('.');
+		} else {
+			goRunArgs.push(program);
+		}
+
+		if (launchArgs.args) {
+			goRunArgs.push(...launchArgs.args);
+		}
+
+		// Read env from disk and merge into env variables.
+		const fileEnvs = [];
+		if (typeof launchArgs.envFile === 'string') {
+			fileEnvs.push(parseEnvFile(launchArgs.envFile));
+		}
+		if (Array.isArray(launchArgs.envFile)) {
+			launchArgs.envFile.forEach((envFile) => {
+				fileEnvs.push(parseEnvFile(envFile));
+			});
+		}
+
+		const launchArgsEnv = launchArgs.env || {};
+		const programEnv = Object.assign({}, process.env, ...fileEnvs, launchArgsEnv);
+
+		log(`Current working directory: ${dirname}`);
+		const goExe = getBinPathWithPreferredGopathGoroot('go', []);
+		log(`Running: ${goExe} ${goRunArgs.join(' ')}`);
+
+		this.debugProcess = spawn(goExe, goRunArgs, {
+			cwd: dirname,
+			env: programEnv
+		});
+		this.debugProcess.stderr.on('data', (str) => {
+			this.sendEvent(new OutputEvent(str.toString(), 'stderr'));
+		});
+		this.debugProcess.stdout.on('data', (str) => {
+			this.sendEvent(new OutputEvent(str.toString(), 'stdout'));
+		});
+		this.debugProcess.on('close', (rc) => {
+			this.sendEvent(new TerminatedEvent());
+		});
+	}
+}
+
+// DelveClient provides a DAP client to talk to a DAP server in Delve.
+//
+// After creation, it emits the following events:
+//
+//    'connected':            client is connected to delve
+//    'request (request)':    delve sent request
+//    'response (response)':  delve sent response
+//    'event (event)':        delve sent event
+//    'stdout' (str):         delve emitted str to stdout
+//    'stderr' (str):         delve emitted str to stderr
+//    'close' (rc):           delve exited with return code rc
+class DelveClient extends DAPClient {
+	private debugProcess: ChildProcess;
+	private serverStarted: boolean = false;
+
+	constructor(launchArgs: LaunchRequestArguments) {
+		super();
+
+		const launchArgsEnv = launchArgs.env || {};
+		const env = Object.assign({}, process.env, launchArgsEnv);
+
+		// Let users override direct path to delve by setting it in the env
+		// map in launch.json; if unspecified, fall back to dlvToolPath.
+		let dlvPath = launchArgsEnv['dlvPath'];
+		if (!dlvPath) {
+			dlvPath = launchArgs.dlvToolPath;
+		}
+
+		if (!fs.existsSync(dlvPath)) {
+			log(
+				`Couldn't find dlv at the Go tools path, ${process.env['GOPATH']}${
+				env['GOPATH'] ? ', ' + env['GOPATH'] : ''
+				} or ${envPath}`
+			);
+			throw new Error(
+				`Cannot find Delve debugger. Install from https://github.com/go-delve/delve/ & ensure it is in your Go tools path, "GOPATH/bin" or "PATH".`
+			);
+		}
+
+		const dlvArgs = new Array<string>();
+		dlvArgs.push('dap');
+		dlvArgs.push(`--listen=${launchArgs.host}:${launchArgs.port}`);
+		if (launchArgs.showLog) {
+			dlvArgs.push('--log=' + launchArgs.showLog.toString());
+		}
+		if (launchArgs.logOutput) {
+			dlvArgs.push('--log-output=' + launchArgs.logOutput);
+		}
+
+		log(`Running: ${dlvPath} ${dlvArgs.join(' ')}`);
+
+		this.debugProcess = spawn(dlvPath, dlvArgs, {
+			cwd: parseProgramArgSync(launchArgs).dirname,
+			env
+		});
+
+		this.debugProcess.stderr.on('data', (chunk) => {
+			const str = chunk.toString();
+			this.emit('stderr', str);
+		});
+
+		this.debugProcess.stdout.on('data', (chunk) => {
+			const str = chunk.toString();
+			this.emit('stdout', str);
+
+			if (!this.serverStarted) {
+				this.serverStarted = true;
+				this.connectSocketToServer(launchArgs.port, launchArgs.host);
+			}
+		});
+
+		this.debugProcess.on('close', (rc) => {
+			if (rc) {
+				logError(`Process exiting with code: ${rc} signal: ${this.debugProcess.killed}`);
+			} else {
+				log(`Process exiting normally ${this.debugProcess.killed}`);
+			}
+			this.emit('close', rc);
+		});
+
+		this.debugProcess.on('error', (err) => {
+			throw err;
+		});
+	}
+
+	// Connect this client to the server. The server is expected to be listening
+	// on host:port.
+	private connectSocketToServer(port: number, host: string) {
+		// Add a slight delay to ensure that Delve started up the server.
+		setTimeout(() => {
+			const socket = net.createConnection(
+				port,
+				host,
+				() => {
+					this.connect(socket, socket);
+					this.emit('connected');
+				});
+
+			socket.on('error', (err) => {
+				throw err;
+			});
+		}, 200);
+	}
+}
+
+// Helper function to parse a program from LaunchRequestArguments. Returns:
+// {
+//    program: the program arg,
+//    dirname: the directory containing the program (or 'program' itself if
+//             it's already a directory),
+//    programIsDirectory: is the program a directory?
+// }
+//
+// The program argument is taken as-is from launchArgs. If the program path
+// is relative, dirname will also be relative. If the program path is absolute,
+// dirname will also be absolute.
+//
+// Throws an exception in case args.program is not a valid file or directory.
+// This function can block because it calls a blocking fs function.
+function parseProgramArgSync(launchArgs: LaunchRequestArguments
+): { program: string, dirname: string, programIsDirectory: boolean } {
+	const program = launchArgs.program;
+	if (!program) {
+		throw new Error('The program attribute is missing in the debug configuration in launch.json');
+	}
+	let programIsDirectory = false;
+	try {
+		programIsDirectory = fs.lstatSync(program).isDirectory();
+	} catch (e) {
+		throw new Error('The program attribute must point to valid directory, .go file or executable.');
+	}
+	if (!programIsDirectory && path.extname(program) !== '.go') {
+		throw new Error('The program attribute must be a directory or .go file in debug mode');
+	}
+	const dirname = programIsDirectory ? program : path.dirname(program);
+	return {program, dirname, programIsDirectory};
+}
diff --git a/src/debugAdapter2/goDlvDebugMain.ts b/src/debugAdapter2/goDlvDebugMain.ts
new file mode 100644
index 0000000..8fc3073
--- /dev/null
+++ b/src/debugAdapter2/goDlvDebugMain.ts
@@ -0,0 +1,22 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+// This file is for running the godlvdap debug adapter as a standalone program
+// in a separate process (e.g. when working in --server mode).
+//
+// NOTE: we must not include this file when we switch to the inline debug adapter
+// launch mode. This installs a process-wide uncaughtException handler
+// which can result in the extension host crash.
+
+import { logger } from 'vscode-debugadapter';
+import { GoDlvDapDebugSession } from './goDlvDebug';
+
+process.on('uncaughtException', (err: any) => {
+	const errMessage = err && (err.stack || err.message);
+	logger.error(`Unhandled error in debug adapter: ${errMessage}`);
+	throw err;
+});
+
+GoDlvDapDebugSession.run(GoDlvDapDebugSession);
diff --git a/src/diffUtils.ts b/src/diffUtils.ts
index f001229..e0895a1 100644
--- a/src/diffUtils.ts
+++ b/src/diffUtils.ts
@@ -5,7 +5,7 @@
 
 import jsDiff = require('diff');
 import { Position, Range, TextEditorEdit, Uri, WorkspaceEdit } from 'vscode';
-import { getBinPathFromEnvVar } from './goPath';
+import { getBinPathFromEnvVar } from './utils/goPath';
 
 let diffToolAvailable: boolean | null = null;
 
diff --git a/src/goBrowsePackage.ts b/src/goBrowsePackage.ts
index f27b107..79097a3 100644
--- a/src/goBrowsePackage.ts
+++ b/src/goBrowsePackage.ts
@@ -9,8 +9,8 @@
 import path = require('path');
 import vscode = require('vscode');
 import { getAllPackages } from './goPackages';
-import { envPath, getCurrentGoRoot } from './goPath';
 import { getBinPath, getCurrentGoPath, getImportPath } from './util';
+import { envPath, getCurrentGoRoot } from './utils/goPath';
 
 export function browsePackages() {
 	let workDir = '';
diff --git a/src/goBuild.ts b/src/goBuild.ts
index 0aaee96..a265e54 100644
--- a/src/goBuild.ts
+++ b/src/goBuild.ts
@@ -9,7 +9,6 @@
 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 {
@@ -22,6 +21,8 @@
 	ICheckResult,
 	runTool
 } from './util';
+import { getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
+
 /**
  * Builds current package or workspace.
  */
diff --git a/src/goCover.ts b/src/goCover.ts
index 6ebda30..b1d3994 100644
--- a/src/goCover.ts
+++ b/src/goCover.ts
@@ -7,9 +7,9 @@
 
 import fs = require('fs');
 import path = require('path');
-import rl = require('readline');
 import vscode = require('vscode');
 import { isModSupported } from './goModules';
+import { getImportPathToFolder } from './goPackages';
 import { getTestFlags, goTest, showTestOutput, TestConfig } from './testUtils';
 import { getGoConfig } from './util';
 
@@ -29,6 +29,7 @@
 	coveredGutterStyle: string;
 	uncoveredGutterStyle: string;
 };
+
 // a list of modified, unsaved go files with actual code edits (rather than comment edits)
 let modifiedFiles: {
 	[key: string]: boolean;
@@ -93,6 +94,8 @@
 export function updateCodeCoverageDecorators(coverageDecoratorConfig: any) {
 	// These defaults are chosen to be distinguishable in nearly any color scheme (even Red)
 	// as well as by people who have difficulties with color perception.
+	// (how do these relate the defaults in package.json?)
+	// and where do the defaults actually come from? (raised as issue #256)
 	decoratorConfig = {
 		type: 'highlight',
 		coveredHighlightColor: 'rgba(64,128,128,0.5)',
@@ -151,14 +154,14 @@
 	coveredRange: vscode.Range[];
 }
 
-let coverageFiles: { [key: string]: CoverageData } = {};
+let coverageData: { [key: string]: CoverageData } = {};  // actual file path to the coverage data.
 let isCoverageApplied: boolean = false;
 
 /**
  * Clear the coverage on all files
  */
 function clearCoverage() {
-	coverageFiles = {};
+	coverageData = {};
 	disposeDecorators();
 	isCoverageApplied = false;
 }
@@ -167,48 +170,59 @@
  * Extract the coverage data from the given cover profile & apply them on the files in the open editors.
  * @param coverProfilePath Path to the file that has the cover profile data
  * @param packageDirPath Absolute path of the package for which the coverage was calculated
+ * @param testDir Directory to execute go list in, when there is no workspace, for some tests
  */
-export function applyCodeCoverageToAllEditors(coverProfilePath: string, packageDirPath: string): Promise<void> {
-	return new Promise((resolve, reject) => {
+export function applyCodeCoverageToAllEditors(coverProfilePath: string, testDir?: string): Promise<void> {
+	const v = new Promise<void>((resolve, reject) => {
 		try {
+			const coveragePath = new Map<string, CoverageData>();  // <filename> from the cover profile to the coverage data.
+
 			// Clear existing coverage files
 			clearCoverage();
 
-			const lines = rl.createInterface({
-				input: fs.createReadStream(coverProfilePath),
-				output: undefined
-			});
-
-			lines.on('line', (data: string) => {
+			// collect the packages named in the coverage file
+			const seenPaths = new Set<string>();
+			// for now read synchronously and hope for no errors
+			const contents = fs.readFileSync(coverProfilePath).toString();
+			contents.split('\n').forEach((line) => {
 				// go test coverageprofile generates output:
 				//    filename:StartLine.StartColumn,EndLine.EndColumn Hits CoverCount
-				// The first line will be "mode: set" which will be ignored
-				const fileRange = data.match(/([^:]+)\:([\d]+)\.([\d]+)\,([\d]+)\.([\d]+)\s([\d]+)\s([\d]+)/);
-				if (!fileRange) {
-					return;
+				// where the filename is either the import path + '/' + base file name, or
+				// the actual file path (either absolute or starting with .)
+				// See https://golang.org/issues/40251.
+				//
+				// The first line will be like "mode: set" which we will ignore.
+				const parse = line.match(/([^:]+)\:([\d]+)\.([\d]+)\,([\d]+)\.([\d]+)\s([\d]+)\s([\d]+)/);
+				if (!parse) { return; }
+				const lastSlash = parse[1].lastIndexOf('/');
+				if (lastSlash !== -1) {
+					seenPaths.add(parse[1].slice(0, lastSlash));
 				}
 
-				const filePath = path.join(packageDirPath, path.basename(fileRange[1]));
-				const coverage = getCoverageData(filePath);
+				// and fill in coveragePath
+				const coverage = coveragePath.get(parse[1]) || { coveredRange: [], uncoveredRange: [] };
 				const range = new vscode.Range(
 					// Start Line converted to zero based
-					parseInt(fileRange[2], 10) - 1,
+					parseInt(parse[2], 10) - 1,
 					// Start Column converted to zero based
-					parseInt(fileRange[3], 10) - 1,
+					parseInt(parse[3], 10) - 1,
 					// End Line converted to zero based
-					parseInt(fileRange[4], 10) - 1,
+					parseInt(parse[4], 10) - 1,
 					// End Column converted to zero based
-					parseInt(fileRange[5], 10) - 1
+					parseInt(parse[5], 10) - 1
 				);
 				// If is Covered (CoverCount > 0)
-				if (parseInt(fileRange[7], 10) > 0) {
+				if (parseInt(parse[7], 10) > 0) {
 					coverage.coveredRange.push(range);
 				} else {
 					coverage.uncoveredRange.push(range);
 				}
-				setCoverageData(filePath, coverage);
+				coveragePath.set(parse[1], coverage);
 			});
-			lines.on('close', () => {
+
+			getImportPathToFolder([...seenPaths], testDir)
+				.then((pathsToDirs) => {
+				createCoverageData(pathsToDirs, coveragePath);
 				setDecorators();
 				vscode.window.visibleTextEditors.forEach(applyCodeCoverage);
 				resolve();
@@ -218,23 +232,33 @@
 			reject(e);
 		}
 	});
+	return v;
 }
 
-/**
- * Get the object that holds the coverage data for given file path.
- * @param filePath
- */
-function getCoverageData(filePath: string): CoverageData {
-	if (filePath.startsWith('_')) {
-		filePath = filePath.substr(1);
-	}
-	if (process.platform === 'win32') {
-		const parts = filePath.split('/');
-		if (parts.length) {
-			filePath = parts.join(path.sep);
+function createCoverageData(
+	pathsToDirs: Map<string, string>,
+	coveragePath: Map<string, CoverageData>) {
+
+	coveragePath.forEach((cd, ip) => {
+		const lastSlash = ip.lastIndexOf('/');
+		if (lastSlash === -1) {  // malformed
+			console.log(`invalid entry: ${ip}`);
+			return;
 		}
-	}
-	return coverageFiles[filePath] || { coveredRange: [], uncoveredRange: [] };
+		const importPath = ip.slice(0, lastSlash);
+		let fileDir = importPath;
+		if (path.isAbsolute(importPath)) {
+			// This is the true file path.
+		} else if (importPath.startsWith('.')) {
+			fileDir = path.resolve(fileDir);
+		} else {
+			// This is the package import path.
+			// we need to look up `go list` output stored in pathsToDir.
+			fileDir = pathsToDirs.get(importPath) || importPath;
+		}
+		const file = fileDir + path.sep + ip.slice(lastSlash + 1);
+		setCoverageDataByFilePath(file, cd);
+	});
 }
 
 /**
@@ -242,7 +266,7 @@
  * @param filePath
  * @param data
  */
-function setCoverageData(filePath: string, data: CoverageData) {
+function setCoverageDataByFilePath(filePath: string, data: CoverageData) {
 	if (filePath.startsWith('_')) {
 		filePath = filePath.substr(1);
 	}
@@ -252,7 +276,7 @@
 			filePath = parts.join(path.sep);
 		}
 	}
-	coverageFiles[filePath] = data;
+	coverageData[filePath] = data;
 }
 
 /**
@@ -266,16 +290,16 @@
 
 	const cfg = getGoConfig(editor.document.uri);
 	const coverageOptions = cfg['coverageOptions'];
-	for (const filename in coverageFiles) {
+	for (const filename in coverageData) {
 		if (editor.document.uri.fsPath.endsWith(filename)) {
 			isCoverageApplied = true;
-			const coverageData = coverageFiles[filename];
+			const cd = coverageData[filename];
 			if (coverageOptions === 'showCoveredCodeOnly' || coverageOptions === 'showBothCoveredAndUncoveredCode') {
 				editor.setDecorations(
 					decorators.type === 'gutter'
 						? decorators.coveredGutterDecorator
 						: decorators.coveredHighlightDecorator,
-					coverageData.coveredRange
+					cd.coveredRange
 				);
 			}
 
@@ -284,7 +308,7 @@
 					decorators.type === 'gutter'
 						? decorators.uncoveredGutterDecorator
 						: decorators.uncoveredHighlightDecorator,
-					coverageData.uncoveredRange
+					cd.uncoveredRange
 				);
 			}
 		}
@@ -383,3 +407,27 @@
 		return idx > -1 && idx <= change.range.start.character;
 	});
 }
+
+// These routines enable testing without starting an editing session.
+
+export function coverageFilesForTest():  { [key: string]: CoverageData; } {
+	return coverageData;
+}
+
+export function initForTest() {
+	if (!decoratorConfig) {
+		// this code is unnecessary except for testing, where there may be no workspace
+		// nor the normal flow of initializations
+		const x = 'rgba(0,0,0,0)';
+		if (!gutterSvgs) {
+			gutterSvgs = { x };
+		}
+		decoratorConfig = {
+			type: 'highlight',
+			coveredHighlightColor: x,
+			uncoveredHighlightColor: x,
+			coveredGutterStyle: x,
+			uncoveredGutterStyle: x
+		};
+	}
+}
diff --git a/src/goDebugConfiguration.ts b/src/goDebugConfiguration.ts
index a69087a..b65b47b 100644
--- a/src/goDebugConfiguration.ts
+++ b/src/goDebugConfiguration.ts
@@ -14,6 +14,8 @@
 import { getBinPath, getCurrentGoPath, getGoConfig } from './util';
 
 export class GoDebugConfigurationProvider implements vscode.DebugConfigurationProvider {
+	constructor(private defaultDebugAdapterType: string = 'go') { }
+
 	public provideDebugConfigurations(
 		folder: vscode.WorkspaceFolder | undefined,
 		token?: vscode.CancellationToken
@@ -21,7 +23,7 @@
 		return [
 			{
 				name: 'Launch',
-				type: 'go',
+				type: this.defaultDebugAdapterType,
 				request: 'launch',
 				mode: 'auto',
 				program: '${fileDirname}',
@@ -45,13 +47,17 @@
 
 			debugConfiguration = Object.assign(debugConfiguration || {}, {
 				name: 'Launch',
-				type: 'go',
+				type: this.defaultDebugAdapterType,
 				request: 'launch',
 				mode: 'auto',
 				program: path.dirname(activeEditor.document.fileName) // matches ${fileDirname}
 			});
 		}
 
+		if (!debugConfiguration.type) {
+			debugConfiguration['type'] = this.defaultDebugAdapterType;
+		}
+
 		debugConfiguration['packagePathToGoModPathMap'] = packagePathToGoModPathMap;
 
 		const gopath = getCurrentGoPath(folder ? folder.uri : undefined);
diff --git a/src/goDeclaration.ts b/src/goDeclaration.ts
index 7eb03ee..0d13500 100644
--- a/src/goDeclaration.ts
+++ b/src/goDeclaration.ts
@@ -20,9 +20,10 @@
 	getWorkspaceFolderPath,
 	goKeywords,
 	isPositionInString,
-	killTree,
 	runGodoc
 } from './util';
+import { getCurrentGoRoot } from './utils/goPath';
+import { killProcessTree } from './utils/processUtils';
 
 const missingToolMsg = 'Missing tool: ';
 
@@ -133,9 +134,10 @@
 	}
 	const offset = byteOffsetAt(input.document, input.position);
 	const env = toolExecutionEnvironment();
+	env['GOROOT'] = getCurrentGoRoot();
 	let p: cp.ChildProcess;
 	if (token) {
-		token.onCancellationRequested(() => killTree(p.pid));
+		token.onCancellationRequested(() => killProcessTree(p));
 	}
 
 	return new Promise<GoDefinitionInformation>((resolve, reject) => {
@@ -226,7 +228,7 @@
 	const env = toolExecutionEnvironment();
 	let p: cp.ChildProcess;
 	if (token) {
-		token.onCancellationRequested(() => killTree(p.pid));
+		token.onCancellationRequested(() => killProcessTree(p));
 	}
 
 	return new Promise<GoDefinitionInformation>((resolve, reject) => {
@@ -300,7 +302,7 @@
 	const env = toolExecutionEnvironment();
 	let p: cp.ChildProcess;
 	if (token) {
-		token.onCancellationRequested(() => killTree(p.pid));
+		token.onCancellationRequested(() => killProcessTree(p));
 	}
 	return new Promise<GoDefinitionInformation>((resolve, reject) => {
 		p = cp.execFile(
diff --git a/src/goEnv.ts b/src/goEnv.ts
index b872319..0372895 100644
--- a/src/goEnv.ts
+++ b/src/goEnv.ts
@@ -7,7 +7,7 @@
 
 import path = require('path');
 import vscode = require('vscode');
-import { getCurrentGoPath, getGoConfig, getToolsGopath } from './util';
+import { getCurrentGoPath, getGoConfig, getToolsGopath, resolvePath } from './util';
 
 // toolInstallationEnvironment returns the environment in which tools should
 // be installed. It always returns a new object.
@@ -56,6 +56,13 @@
 function newEnvironment(): NodeJS.Dict<string> {
 	const toolsEnvVars = getGoConfig()['toolsEnvVars'];
 	const env = Object.assign({}, process.env, toolsEnvVars);
+	if (toolsEnvVars && typeof toolsEnvVars === 'object') {
+		Object.keys(toolsEnvVars).forEach(
+			(key) =>
+				(env[key] =
+					typeof toolsEnvVars[key] === 'string' ? resolvePath(toolsEnvVars[key]) : toolsEnvVars[key])
+		);
+	}
 
 	// The http.proxy setting takes precedence over environment variables.
 	const httpProxy = vscode.workspace.getConfiguration('http', null).get('proxy');
diff --git a/src/goEnvironmentStatus.ts b/src/goEnvironmentStatus.ts
index dbb3d8a..513b243 100644
--- a/src/goEnvironmentStatus.ts
+++ b/src/goEnvironmentStatus.ts
@@ -5,14 +5,37 @@
 
 'use strict';
 
+import cp = require('child_process');
+import fs = require('fs');
+import os = require('os');
+import path = require('path');
+import { promisify } from 'util';
 import vscode = require('vscode');
+import WebRequest = require('web-request');
+import { toolInstallationEnvironment } from './goEnv';
+import { outputChannel } from './goStatus';
+import { getFromWorkspaceState, updateWorkspaceState } from './stateUtils';
+import { getBinPath, getGoVersion, getTempFilePath, GoVersion, rmdirRecursive } from './util';
+import { correctBinname, getBinPathFromEnvVar, getCurrentGoRoot, pathExists } from './utils/goPath';
 
-import { updateGoVarsFromConfig } from './goInstallTools';
-import { getCurrentGoRoot } from './goPath';
-import { getGoVersion } from './util';
+export class GoEnvironmentOption {
+	public static fromQuickPickItem({ description, label }: vscode.QuickPickItem): GoEnvironmentOption {
+		return new GoEnvironmentOption(description, label);
+	}
+
+	constructor(public binpath: string, public label: string) {}
+
+	public toQuickPickItem(): vscode.QuickPickItem {
+		return {
+			label: this.label,
+			description: this.binpath,
+		};
+	}
+}
 
 // statusbar item for switching the Go environment
 let goEnvStatusbarItem: vscode.StatusBarItem;
+let terminalCreationListener: vscode.Disposable;
 
 /**
  * Initialize the status bar item with current Go binary
@@ -23,9 +46,10 @@
 	}
 	// set Go version and command
 	const version = await getGoVersion();
+	const goOption = new GoEnvironmentOption(version.binaryPath, formatGoVersion(version));
 
 	hideGoStatusBar();
-	goEnvStatusbarItem.text = formatGoVersion(version.format());
+	goEnvStatusbarItem.text = goOption.label;
 	goEnvStatusbarItem.command = 'go.environment.choose';
 	showGoStatusBar();
 }
@@ -37,6 +61,9 @@
 	if (!!goEnvStatusbarItem) {
 		goEnvStatusbarItem.dispose();
 	}
+	if (!!terminalCreationListener) {
+		terminalCreationListener.dispose();
+	}
 }
 
 /**
@@ -57,12 +84,280 @@
 	}
 }
 
+let environmentVariableCollection: vscode.EnvironmentVariableCollection;
+export function setEnvironmentVariableCollection(env: vscode.EnvironmentVariableCollection) {
+	environmentVariableCollection = env;
+}
+
 /**
  * Present a command palette menu to the user to select their go binary
- * TODO: remove temporary alert and implement correct functionality
  */
-export function chooseGoEnvironment() {
-	vscode.window.showInformationMessage(`Current GOROOT: ${getCurrentGoRoot()}`);
+export async function chooseGoEnvironment() {
+	if (!goEnvStatusbarItem) {
+		return;
+	}
+
+	// if there is no workspace, show GOROOT with message
+	if (!vscode.workspace.name) {
+		vscode.window.showInformationMessage(`GOROOT: ${getCurrentGoRoot()}. Switching Go version is not yet supported in single-file mode.`);
+		return;
+	}
+
+	// fetch default go and uninstalled go versions
+	let defaultOption: GoEnvironmentOption;
+	let uninstalledOptions: GoEnvironmentOption[];
+	let goSDKOptions: GoEnvironmentOption[];
+	try {
+		[defaultOption, uninstalledOptions, goSDKOptions] = await Promise.all([
+			getDefaultGoOption(),
+			fetchDownloadableGoVersions(),
+			getSDKGoOptions()
+		]);
+	} catch (e) {
+		vscode.window.showErrorMessage(e.message);
+		return;
+	}
+
+	// create quick pick items
+	const uninstalledQuickPicks = uninstalledOptions.map((op) => op.toQuickPickItem());
+	const defaultQuickPick = defaultOption.toQuickPickItem();
+	const goSDKQuickPicks = goSDKOptions.map((op) => op.toQuickPickItem());
+
+	// dedup options by eliminating duplicate paths (description)
+	const clearOption: vscode.QuickPickItem = { label: 'Clear selection' };
+	const options = [clearOption, defaultQuickPick, ...goSDKQuickPicks, ...uninstalledQuickPicks]
+		.reduce((opts, nextOption) => {
+			if (opts.find((op) => op.description === nextOption.description || op.label === nextOption.label)) {
+				return opts;
+			}
+			return [...opts, nextOption];
+		}, [] as vscode.QuickPickItem[]);
+
+	// get user's selection, return if none was made
+	const selection = await vscode.window.showQuickPick<vscode.QuickPickItem>(options);
+	if (!selection) {
+		return;
+	}
+
+	// update currently selected go
+	try {
+		const changed = await setSelectedGo(GoEnvironmentOption.fromQuickPickItem(selection));
+		if (changed) {
+			vscode.window.showInformationMessage(`Switched to ${selection.label}`);
+		}
+	} catch (e) {
+		vscode.window.showErrorMessage(e.message);
+	}
+}
+
+/**
+ * update the selected go path and label in the workspace state
+ */
+export async function setSelectedGo(goOption: GoEnvironmentOption, promptReload = true): Promise<boolean> {
+	if (!goOption) {
+		return false;
+	}
+
+	// if the selected go version is not installed, install it
+	if (goOption.binpath?.startsWith('go get')) {
+		// start a loading indicator
+		await downloadGo(goOption);
+	} else if (goOption.label === 'Clear selection') {
+		if (!getSelectedGo()) {
+			return false;  // do nothing.
+		}
+		await updateWorkspaceState('selectedGo', undefined);
+		// TODO: goEnvStatusbarItem?
+	} else {
+		// check that the given binary is not already at the beginning of the PATH
+		const go = await getGoVersion();
+		if (!!go && (go.binaryPath === goOption.binpath || 'Go ' + go.format() === goOption.label)) {
+			return false;
+		}
+		await updateWorkspaceState('selectedGo', goOption);
+	}
+	// prompt the user to reload the window.
+	// promptReload defaults to true and should only be false for tests.
+	if (promptReload) {
+		const choice = await vscode.window.showInformationMessage('Please reload the window to finish applying Go version changes.', 'Reload Window');
+		if (choice === 'Reload Window') {
+			await vscode.commands.executeCommand('workbench.action.reloadWindow');
+		}
+	}
+	goEnvStatusbarItem.text = 'Go: reload required';
+	goEnvStatusbarItem.command = 'workbench.action.reloadWindow';
+
+	return true;
+}
+
+// downloadGo downloads the specified go version available in dl.golang.org.
+async function downloadGo(goOption: GoEnvironmentOption) {
+	const execFile = promisify(cp.execFile);
+	await vscode.window.withProgress({
+		title: `Downloading ${goOption.label}`,
+		location: vscode.ProgressLocation.Notification,
+	}, async () => {
+		outputChannel.show();
+		outputChannel.clear();
+
+		outputChannel.appendLine('Finding Go executable for downloading');
+		const goExecutable = getBinPath('go');
+		if (!goExecutable) {
+			outputChannel.appendLine('Could not find Go executable.');
+			throw new Error('Could not find Go tool.');
+		}
+
+		// TODO(bcloud) dedup repeated logic below which comes from
+		// https://github.com/golang/vscode-go/blob/bc23fa854192d04200c8e4f74dca18d2c3021b46/src/goInstallTools.ts#L184
+		// Install tools in a temporary directory, to avoid altering go.mod files.
+		const mkdtemp = promisify(fs.mkdtemp);
+		const toolsTmpDir = await mkdtemp(getTempFilePath('go-tools-'));
+		let tmpGoModFile: string;
+
+		// Write a temporary go.mod file to avoid version conflicts.
+		tmpGoModFile = path.join(toolsTmpDir, 'go.mod');
+		const writeFile = promisify(fs.writeFile);
+		await writeFile(tmpGoModFile, 'module tools');
+
+		// use the current go executable to download the new version
+		const env = {
+			...toolInstallationEnvironment(),
+			GO111MODULE: 'on',
+		};
+		const [, ...args] = goOption.binpath.split(' ');
+		outputChannel.appendLine(`Running ${goExecutable} ${args.join(' ')}`);
+		try {
+			await execFile(goExecutable, args, {
+				env,
+				cwd: toolsTmpDir,
+			});
+		} catch (getErr) {
+			outputChannel.appendLine(`Error finding Go: ${getErr}`);
+			throw new Error('Could not find Go version.');
+		}
+
+		// run `goX.X download`
+		const newExecutableName = args[1].split('/')[2];
+		const goXExecutable = getBinPath(newExecutableName);
+		outputChannel.appendLine(`Running: ${goXExecutable} download`);
+		try {
+			await execFile(goXExecutable, ['download'], { env });
+		} catch (downloadErr) {
+			outputChannel.appendLine(`Error finishing installation: ${downloadErr}`);
+			throw new Error('Could not download Go version.');
+		}
+
+		outputChannel.appendLine('Finding newly downloaded Go');
+		const sdkPath = path.join(os.homedir(), 'sdk');
+		if (!await pathExists(sdkPath)) {
+			outputChannel.appendLine(`SDK path does not exist: ${sdkPath}`);
+			throw new Error(`SDK path does not exist: ${sdkPath}`);
+		}
+
+		const readdir = promisify(fs.readdir);
+		const subdirs = await readdir(sdkPath);
+		const dir = subdirs.find((subdir) => subdir === newExecutableName);
+		if (!dir) {
+			outputChannel.appendLine('Could not find newly downloaded Go');
+			throw new Error('Could not install Go version.');
+		}
+
+		const binpath = path.join(sdkPath, dir, 'bin', correctBinname('go'));
+		const newOption = new GoEnvironmentOption(binpath, goOption.label);
+		await updateWorkspaceState('selectedGo', newOption);
+
+		// remove tmp directories
+		outputChannel.appendLine('Cleaning up...');
+		rmdirRecursive(toolsTmpDir);
+		outputChannel.appendLine('Success!');
+	});
+}
+
+// PATH value cached before addGoRuntimeBaseToPath modified.
+let defaultPathEnv = '';
+
+// addGoRuntimeBaseToPATH adds the given path to the front of the PATH environment variable.
+// It removes duplicates.
+// TODO: can we avoid changing PATH but utilize toolExecutionEnv?
+export function addGoRuntimeBaseToPATH(newGoRuntimeBase: string) {
+	if (!newGoRuntimeBase) {
+		return;
+	}
+
+	let pathEnvVar: string;
+	if (process.env.hasOwnProperty('PATH')) {
+		pathEnvVar = 'PATH';
+	} else if (process.platform === 'win32' && process.env.hasOwnProperty('Path')) {
+		pathEnvVar = 'Path';
+	} else {
+		return;
+	}
+
+	if (!defaultPathEnv) {  // cache the default value
+		defaultPathEnv = <string>process.env[pathEnvVar];
+	}
+
+	// calling this multiple times will override the previous value.
+	// environmentVariableCollection.clear();
+	if (process.platform !== 'darwin') {
+		environmentVariableCollection?.prepend(pathEnvVar, newGoRuntimeBase + path.delimiter);
+	} else if (!terminalCreationListener) {  // process.platform === 'darwin'
+		// We don't use EnvironmentVariableCollection on mac
+		// because this gets confusing for users. Instead we send the
+		// shell command to change the PATH env var,
+		// following the suggestion to workaround described in
+		// https://github.com/microsoft/vscode/issues/99878#issuecomment-642808852
+		const terminalShellArgs = <string[]>(
+			vscode.workspace.getConfiguration('terminal.integrated.shellArgs').get('osx') || []);
+		// User explicitly chose to run the login shell. So, don't mess with their config.
+		if (!terminalShellArgs.includes('-l') && !terminalShellArgs.includes('--login')) {
+			for (const term of vscode.window.terminals) {
+				updateIntegratedTerminal(term);
+			}
+			terminalCreationListener = vscode.window.onDidOpenTerminal(updateIntegratedTerminal);
+		}
+	}
+
+	let pathVars = defaultPathEnv.split(path.delimiter);
+	pathVars = pathVars.filter((p) => p !== newGoRuntimeBase);
+	pathVars.unshift(newGoRuntimeBase);
+	process.env[pathEnvVar] = pathVars.join(path.delimiter);
+}
+
+/**
+ * update the PATH variable in the given terminal to default to the currently selected Go
+ */
+export async function updateIntegratedTerminal(terminal: vscode.Terminal): Promise<void> {
+	if (!terminal) { return; }
+	const gorootBin = path.join(getCurrentGoRoot(), 'bin');
+	const defaultGoRuntimeBin = path.dirname(getBinPathFromEnvVar('go', defaultPathEnv, false));
+	if (gorootBin === defaultGoRuntimeBin) {
+		return;
+	}
+
+	// append the goroot to the beginning of the PATH so it takes precedence
+	// TODO: add support for more terminal names
+	// this assumes all non-windows shells are bash-like.
+	if (terminal.name.toLowerCase() === 'cmd') {
+		terminal.sendText(`set PATH=${gorootBin};%Path%`, true);
+		terminal.sendText('cls');
+	} else if (['powershell', 'pwsh'].includes(terminal.name.toLowerCase())) {
+		terminal.sendText(`$env:Path="${gorootBin};$env:Path"`, true);
+		terminal.sendText('clear');
+	} else if (terminal.name.toLowerCase() === 'fish') {
+		terminal.sendText(`set -gx PATH ${gorootBin} $PATH`);
+		terminal.sendText('clear');
+	} else if (['bash', 'sh', 'zsh', 'ksh'].includes(terminal.name.toLowerCase())) {
+		terminal.sendText(`export PATH=${gorootBin}:$PATH`, true);
+		terminal.sendText('clear');
+	}
+}
+
+/**
+ * retreive the current selected Go from the workspace state
+ */
+export function getSelectedGo(): GoEnvironmentOption {
+	return getFromWorkspaceState('selectedGo');
 }
 
 /**
@@ -72,26 +367,87 @@
 	return goEnvStatusbarItem;
 }
 
-export async function getActiveGoRoot(): Promise<string | undefined> {
-	// look for current current go binary
-	let goroot = getCurrentGoRoot();
-	if (!goroot) {
-		await updateGoVarsFromConfig();
-		goroot = getCurrentGoRoot();
+export function formatGoVersion(version?: GoVersion): string {
+	if (!version || !version.isValid()) {
+		return `Go (unknown)`;
 	}
-	return goroot || undefined;
-}
-
-export function formatGoVersion(version: string): string {
-	const versionWords = version.split(' ');
-	if (versionWords[0] === 'devel') {
+	const versionStr = version.format(true);
+	const versionWords = versionStr.split(' ');
+	if (versionWords.length > 1 && versionWords[0] === 'devel') {
 		// Go devel +hash
-		return `Go ${versionWords[0]} ${versionWords[4]}`;
-	} else if (versionWords.length > 0) {
-		// some other version format
-		return `Go ${version.substr(0, 8)}`;
+		return `Go ${versionWords[1]}`;
 	} else {
-		// default semantic version format
 		return `Go ${versionWords[0]}`;
 	}
 }
+
+async function getSDKGoOptions(): Promise<GoEnvironmentOption[]> {
+	// get list of Go versions
+	const sdkPath = path.join(os.homedir(), 'sdk');
+
+	if (!await pathExists(sdkPath)) {
+		return [];
+	}
+	const readdir = promisify(fs.readdir);
+	const subdirs = await readdir(sdkPath);
+	// the dir happens to be the version, which will be used as the label
+	// the path is assembled and used as the description
+	return subdirs.map((dir: string) =>
+		new GoEnvironmentOption(
+			path.join(sdkPath, dir, 'bin', correctBinname('go')),
+			dir.replace('go', 'Go '),
+		)
+	);
+}
+
+export async function getDefaultGoOption(): Promise<GoEnvironmentOption> {
+	// make goroot default to go.goroot
+	const goroot = getCurrentGoRoot();
+	if (!goroot) {
+		throw new Error('No Go command could be found.');
+	}
+
+	// set Go version and command
+	const version = await getGoVersion();
+	return new GoEnvironmentOption(
+		path.join(goroot, 'bin', correctBinname('go')),
+		formatGoVersion(version),
+	);
+}
+
+/**
+ * make a web request to get versions of Go
+ */
+interface GoVersionWebResult {
+	version: string;
+	stable: boolean;
+	files: {
+		filename: string;
+		os: string;
+		arch: string;
+		version: string;
+		sha256: string;
+		size: number;
+		kind: string;
+	}[];
+}
+async function fetchDownloadableGoVersions(): Promise<GoEnvironmentOption[]> {
+	// fetch information about what Go versions are available to install
+	let webResults;
+	try {
+		webResults = await WebRequest.json<GoVersionWebResult[]>('https://golang.org/dl/?mode=json');
+	} catch (error) {
+		return [];
+	}
+
+	if (!webResults) {
+		return [];
+	}
+	// turn the web result into GoEnvironmentOption model
+	return webResults.reduce((opts, result: GoVersionWebResult) => {
+		// TODO: allow downloading from different sites
+		const dlPath = `go get golang.org/dl/${result.version}`;
+		const label = result.version.replace('go', 'Go ');
+		return [...opts, new GoEnvironmentOption(dlPath, label)];
+	}, []);
+}
diff --git a/src/goFormat.ts b/src/goFormat.ts
index 6321e66..8ad78d7 100644
--- a/src/goFormat.ts
+++ b/src/goFormat.ts
@@ -10,7 +10,8 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
-import { getBinPath, getGoConfig, killTree } from './util';
+import { getBinPath, getGoConfig } from './util';
+import { killProcessTree } from './utils/processUtils';
 
 export class GoDocumentFormattingEditProvider implements vscode.DocumentFormattingEditProvider {
 	public provideDocumentFormattingEdits(
@@ -78,7 +79,7 @@
 
 			// Use spawn instead of exec to avoid maxBufferExceeded error
 			const p = cp.spawn(formatCommandBinPath, formatFlags, { env, cwd });
-			token.onCancellationRequested(() => !p.killed && killTree(p.pid));
+			token.onCancellationRequested(() => !p.killed && killProcessTree(p));
 			p.stdout.setEncoding('utf8');
 			p.stdout.on('data', (data) => (stdout += data));
 			p.stderr.on('data', (data) => (stderr += data));
diff --git a/src/goGetPackage.ts b/src/goGetPackage.ts
index 272a995..bffefeb 100644
--- a/src/goGetPackage.ts
+++ b/src/goGetPackage.ts
@@ -8,9 +8,9 @@
 import cp = require('child_process');
 import vscode = require('vscode');
 import { buildCode } from './goBuild';
-import { envPath, getCurrentGoRoot } from './goPath';
 import { outputChannel } from './goStatus';
 import { getBinPath, getCurrentGoPath, getImportPath } from './util';
+import { envPath, getCurrentGoRoot } from './utils/goPath';
 
 export function goGetPackage() {
 	const editor = vscode.window.activeTextEditor;
diff --git a/src/goImplementations.ts b/src/goImplementations.ts
index da39a51..05e44bc 100644
--- a/src/goImplementations.ts
+++ b/src/goImplementations.ts
@@ -10,15 +10,15 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool } from './goInstallTools';
-import { envPath, getCurrentGoRoot } from './goPath';
 import {
 	byteOffsetAt,
 	canonicalizeGOPATHPrefix,
 	getBinPath,
 	getGoConfig,
-	getWorkspaceFolderPath,
-	killTree,
+	getWorkspaceFolderPath
 } from './util';
+import { envPath, getCurrentGoRoot } from './utils/goPath';
+import {killProcessTree} from './utils/processUtils';
 
 interface GoListOutput {
 	Dir: string;
@@ -130,10 +130,10 @@
 
 						return resolve(results);
 					});
-					token.onCancellationRequested(() => killTree(guruProcess.pid));
+					token.onCancellationRequested(() => killProcessTree(guruProcess));
 				}
 			);
-			token.onCancellationRequested(() => killTree(listProcess.pid));
+			token.onCancellationRequested(() => killProcessTree(listProcess));
 		});
 	}
 }
diff --git a/src/goImport.ts b/src/goImport.ts
index 5a9df7e..82fa2a9 100644
--- a/src/goImport.ts
+++ b/src/goImport.ts
@@ -11,8 +11,8 @@
 import { promptForMissingTool } from './goInstallTools';
 import { documentSymbols, GoOutlineImportsOptions } from './goOutline';
 import { getImportablePackages } from './goPackages';
-import { envPath, getCurrentGoRoot } from './goPath';
 import { getBinPath, getImportPath, parseFilePrelude } from './util';
+import { envPath, getCurrentGoRoot } from './utils/goPath';
 
 const missingToolMsg = 'Missing tool: ';
 
diff --git a/src/goInstall.ts b/src/goInstall.ts
index 859da2a..d2131ac 100644
--- a/src/goInstall.ts
+++ b/src/goInstall.ts
@@ -8,9 +8,9 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { isModSupported } from './goModules';
-import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './goPath';
 import { outputChannel } from './goStatus';
 import { getBinPath, getCurrentGoPath, getGoConfig, getModuleCache } from './util';
+import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
 
 export async function installCurrentPackage(): Promise<void> {
 	const editor = vscode.window.activeTextEditor;
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index 1781391..7f2527d 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -12,10 +12,9 @@
 import util = require('util');
 import vscode = require('vscode');
 import { toolInstallationEnvironment } from './goEnv';
-import { initGoStatusBar } from './goEnvironmentStatus';
+import { addGoRuntimeBaseToPATH, initGoStatusBar } from './goEnvironmentStatus';
 import { getLanguageServerToolPath } from './goLanguageServer';
 import { restartLanguageServer } from './goMain';
-import { envPath, getCurrentGoRoot, getToolFromToolPath, setCurrentGoRoot } from './goPath';
 import { hideGoStatus, outputChannel, showGoStatus } from './goStatus';
 import {
 	containsTool,
@@ -36,6 +35,7 @@
 	GoVersion,
 	rmdirRecursive,
 } from './util';
+import { envPath, getCurrentGoRoot, getToolFromToolPath, setCurrentGoRoot } from './utils/goPath';
 
 // declinedUpdates tracks the tools that the user has declined to update.
 const declinedUpdates: Tool[] = [];
@@ -112,7 +112,8 @@
 	if (envForTools['GOBIN']) {
 		installingMsg += `the configured GOBIN: ${envForTools['GOBIN']}`;
 	} else {
-		installingMsg += `${toolsGopath}${path.sep}bin`;
+		const p = toolsGopath.split(path.delimiter).map((e) => path.join(e, 'bin')).join(path.delimiter);
+		installingMsg += `${p}`;
 	}
 
 	// If the user is on Go >= 1.11, tools should be installed with modules enabled.
@@ -176,7 +177,7 @@
 	envForTools: NodeJS.Dict<string>, modulesOn: boolean): Promise<string> {
 	// Some tools may have to be closed before we reinstall them.
 	if (tool.close) {
-		const reason = await tool.close();
+		const reason = await tool.close(envForTools);
 		if (reason) {
 			return reason;
 		}
@@ -235,10 +236,13 @@
 			if (!gopath) {
 				return `GOPATH not configured in environment`;
 			}
-			const outputFile = path.join(gopath, 'bin', process.platform === 'win32' ? `${tool.name}.exe` : tool.name);
+			const destDir = gopath.split(path.delimiter)[0];
+			const outputFile = path.join(destDir, 'bin', process.platform === 'win32' ? `${tool.name}.exe` : tool.name);
 			await execFile(goVersion.binaryPath, ['build', '-o', outputFile, importPath], opts);
 		}
-		outputChannel.appendLine(`Installing ${importPath} SUCCEEDED`);
+		const toolImportPath = tool.version ? importPath + '@' + tool.version : importPath;
+		const toolInstallPath = getBinPath(tool.name);
+		outputChannel.appendLine(`Installing ${toolImportPath} (${toolInstallPath}) SUCCEEDED`);
 	} catch (e) {
 		outputChannel.appendLine(`Installing ${importPath} FAILED`);
 		result = `failed to install ${tool}: ${e} ${output} `;
@@ -326,7 +330,7 @@
 		case 'Release Notes':
 			vscode.commands.executeCommand(
 				'vscode.open',
-				vscode.Uri.parse('https://github.com/golang/go/issues/33030#issuecomment-510151934')
+				vscode.Uri.parse(`https://github.com/golang/tools/releases/tag/${tool.name}/v${newVersion}`)
 			);
 			break;
 		default:
@@ -336,25 +340,16 @@
 }
 
 export function updateGoVarsFromConfig(): Promise<void> {
-	// FIXIT: when user changes the environment variable settings or go.gopath, the following
-	// condition prevents from updating the process.env accordingly, so the extension will lie.
-	// Needs to clean up.
-	if (process.env['GOPATH'] && process.env['GOPROXY'] && process.env['GOBIN']) {
-		return Promise.resolve();
-	}
-
 	// FIXIT: if updateGoVarsFromConfig is called again after addGoRuntimeBaseToPATH sets PATH,
 	// the go chosen by getBinPath based on PATH will not change.
 	const goRuntimePath = getBinPath('go', false);
 	if (!goRuntimePath) {
-		vscode.window.showErrorMessage(
-			`Failed to run "go env" to find GOPATH as the "go" binary cannot be found in either GOROOT(${getCurrentGoRoot()}) or PATH(${envPath})`
-		);
+		suggestDownloadGo();
 		return;
 	}
 
 	return new Promise<void>((resolve, reject) => {
-		cp.execFile(goRuntimePath, ['env', 'GOPATH', 'GOROOT', 'GOPROXY', 'GOBIN'], (err, stdout, stderr) => {
+		cp.execFile(goRuntimePath, ['env', 'GOPATH', 'GOROOT', 'GOPROXY', 'GOBIN', 'GOMODCACHE'], (err, stdout, stderr) => {
 			if (err) {
 				return reject();
 			}
@@ -371,6 +366,9 @@
 			if (!process.env['GOBIN'] && envOutput[3] && envOutput[3].trim()) {
 				process.env['GOBIN'] = envOutput[3].trim();
 			}
+			if (!process.env['GOMODCACHE'] && envOutput[4] && envOutput[4].trim()) {
+				process.env['GOMODCACHE'] = envOutput[4].trim();
+			}
 
 			// cgo, gopls, and other underlying tools will inherit the environment and attempt
 			// to locate 'go' from the PATH env var.
@@ -383,36 +381,6 @@
 	});
 }
 
-// PATH value cached before addGoRuntimeBaseToPath modified.
-let defaultPathEnv = '';
-
-// addGoRuntimeBaseToPATH adds the given path to the front of the PATH environment variable.
-// It removes duplicates.
-// TODO: can we avoid changing PATH but utilize toolExecutionEnv?
-function addGoRuntimeBaseToPATH(newGoRuntimeBase: string) {
-	if (!newGoRuntimeBase) {
-		return;
-	}
-
-	let pathEnvVar: string;
-	if (process.env.hasOwnProperty('PATH')) {
-		pathEnvVar = 'PATH';
-	} else if (process.platform === 'win32' && process.env.hasOwnProperty('Path')) {
-		pathEnvVar = 'Path';
-	} else {
-		return;
-	}
-
-	if (!defaultPathEnv) {  // cache the default value
-		defaultPathEnv = <string>process.env[pathEnvVar];
-	}
-
-	let pathVars = defaultPathEnv.split(path.delimiter);
-	pathVars = pathVars.filter((p) => p !== newGoRuntimeBase);
-	pathVars.unshift(newGoRuntimeBase);
-	process.env[pathEnvVar] = pathVars.join(path.delimiter);
-}
-
 let alreadyOfferedToInstallTools = false;
 
 export async function offerToInstallTools() {
@@ -493,3 +461,24 @@
 		return res.filter((x) => x != null);
 	});
 }
+
+let suggestedDownloadGo = false;
+
+async function suggestDownloadGo() {
+	if (suggestedDownloadGo) {
+		vscode.window.showErrorMessage(
+			`Failed to find the "go" binary in either GOROOT(${getCurrentGoRoot()}) or PATH(${envPath}).`
+		);
+		return;
+	}
+
+	const choice = await vscode.window.showErrorMessage(
+		`Failed to find the "go" binary in either GOROOT(${getCurrentGoRoot()}) or PATH(${envPath}. ` +
+		`Check PATH, or Install Go and reload the window.`,
+		'Go to Download Page'
+	);
+	if (choice === 'Go to Download Page') {
+		vscode.env.openExternal(vscode.Uri.parse('https://golang.org/dl/'));
+	}
+	suggestedDownloadGo = true;
+}
diff --git a/src/goLanguageServer.ts b/src/goLanguageServer.ts
index 03265ee..b1d783e 100644
--- a/src/goLanguageServer.ts
+++ b/src/goLanguageServer.ts
@@ -15,8 +15,16 @@
 import util = require('util');
 import vscode = require('vscode');
 import {
-	CloseAction, CompletionItemKind, ErrorAction, HandleDiagnosticsSignature, InitializeError,
-	LanguageClient, Message, ProvideCompletionItemsSignature, ProvideDocumentLinksSignature,
+	CloseAction,
+	CompletionItemKind,
+	ErrorAction,
+	ExecuteCommandSignature,
+	HandleDiagnosticsSignature,
+	InitializeError,
+	LanguageClient,
+	Message,
+	ProvideCompletionItemsSignature,
+	ProvideDocumentLinksSignature,
 	RevealOutputChannelOn,
 } from 'vscode-languageclient';
 import WebRequest = require('web-request');
@@ -32,7 +40,6 @@
 import { restartLanguageServer } from './goMain';
 import { GO_MODE } from './goMode';
 import { GoDocumentSymbolProvider } from './goOutline';
-import { getToolFromToolPath } from './goPath';
 import { GoReferenceProvider } from './goReferences';
 import { GoRenameProvider } from './goRename';
 import { GoSignatureHelpProvider } from './goSignature';
@@ -42,6 +49,7 @@
 import { GoTypeDefinitionProvider } from './goTypeDefinition';
 import { getFromGlobalState, updateGlobalState } from './stateUtils';
 import { getBinPath, getCurrentGoPath, getGoConfig } from './util';
+import { getToolFromToolPath } from './utils/goPath';
 
 interface LanguageServerConfig {
 	serverName: string;
@@ -75,31 +83,24 @@
 let restartCommand: vscode.Disposable;
 
 // When enabled, users may be prompted to fill out the gopls survey.
-const goplsSurveyOn: boolean = false;
+// For now, we turn it on in the Nightly extension to test it.
+const goplsSurveyOn: boolean = extensionId === 'golang.go-nightly';
+
+// lastUserAction is the time of the last user-triggered change.
+// A user-triggered change is a didOpen, didChange, didSave, or didClose event.
+let lastUserAction: Date = new Date();
 
 // startLanguageServerWithFallback starts the language server, if enabled,
 // or falls back to the default language providers.
 export async function startLanguageServerWithFallback(ctx: vscode.ExtensionContext, activation: boolean) {
 	const cfg = buildLanguageServerConfig();
 
-	// If the language server is gopls, we can check if the user needs to
-	// update their gopls version. We do this only once per VS Code
-	// activation to avoid inundating the user.
-	if (activation && cfg.enabled && cfg.serverName === 'gopls') {
+	// If the language server is gopls, we enable a few additional features.
+	// These include prompting for updates and surveys.
+	if (activation && cfg.serverName === 'gopls') {
 		const tool = getTool(cfg.serverName);
 		if (tool) {
-			const versionToUpdate = await shouldUpdateLanguageServer(tool, cfg.path, cfg.checkForUpdates);
-			if (versionToUpdate) {
-				promptForUpdatingTool(tool.name, versionToUpdate);
-			} else if (goplsSurveyOn) {
-				// Only prompt users to fill out the gopls survey if we are not
-				// also prompting them to update (both would be too much).
-				const timeout = 1000 * 60 * 60; // 1 hour
-				setTimeout(async () => {
-					const surveyCfg = await maybePromptForGoplsSurvey();
-					flushSurveyConfig(surveyCfg);
-				}, timeout);
-			}
+			scheduleGoplsSuggestions(tool);
 		}
 	}
 
@@ -113,6 +114,40 @@
 	}
 }
 
+// scheduleGoplsSuggestions sets timeouts for the various gopls-specific
+// suggestions. We check user's gopls versions once per day to prompt users to
+// update to the latest version. We also check if we should prompt users to
+// fill out the survey.
+function scheduleGoplsSuggestions(tool: Tool) {
+	const update = async () => {
+		setTimeout(update, timeDay);
+
+		const cfg = buildLanguageServerConfig();
+		if (!cfg.enabled) {
+			return;
+		}
+		const versionToUpdate = await shouldUpdateLanguageServer(tool, cfg);
+		if (versionToUpdate) {
+			promptForUpdatingTool(tool.name, versionToUpdate);
+		}
+	};
+	const survey = async () => {
+		setTimeout(survey, timeDay);
+
+		const cfg = buildLanguageServerConfig();
+		if (!goplsSurveyOn || !cfg.enabled) {
+			return;
+		}
+		const surveyCfg = await maybePromptForGoplsSurvey();
+		if (surveyCfg) {
+			flushSurveyConfig(surveyCfg);
+		}
+	};
+
+	setTimeout(update, 10 * timeMinute);
+	setTimeout(survey, 30 * timeMinute);
+}
+
 async function startLanguageServer(ctx: vscode.ExtensionContext, config: LanguageServerConfig): Promise<boolean> {
 	// If the client has already been started, make sure to clear existing
 	// diagnostics and stop it.
@@ -132,7 +167,7 @@
 		// Track the latest config used to start the language server,
 		// and rebuild the language client.
 		latestConfig = config;
-		languageClient = await buildLanguageClient(config);
+		languageClient = buildLanguageClient(config);
 		crashCount = 0;
 	}
 
@@ -162,7 +197,7 @@
 	return true;
 }
 
-async function buildLanguageClient(config: LanguageServerConfig): Promise<LanguageClient> {
+function buildLanguageClient(config: LanguageServerConfig): LanguageClient {
 	// Reuse the same output channel for each instance of the server.
 	if (config.enabled) {
 		if (!serverOutputChannel) {
@@ -223,6 +258,35 @@
 				},
 			},
 			middleware: {
+				provideCodeLenses: async (doc, token, next): Promise<vscode.CodeLens[]> => {
+					const codeLens = await next(doc, token);
+					if (!codeLens || codeLens.length === 0) {
+						return codeLens;
+					}
+					return codeLens.map((lens: vscode.CodeLens) => {
+						switch (lens.command.title) {
+							case 'run test': {
+								const args = lens.command.arguments;
+								return new vscode.CodeLens(lens.range, {
+									...lens.command,
+									command: 'go.test.cursor',
+									arguments: [{ functionName: args[args.indexOf('run') + 1] }],
+								});
+							}
+							case 'run benchmark': {
+								const args = lens.command.arguments;
+								return new vscode.CodeLens(lens.range, {
+									...lens.command,
+									command: 'go.benchmark.cursor',
+									arguments: [{ functionName: args[args.indexOf('bench') + 1] }],
+								});
+							}
+							default: {
+								return lens;
+							}
+						}
+					});
+				},
 				handleDiagnostics: (
 					uri: vscode.Uri,
 					diagnostics: vscode.Diagnostic[],
@@ -301,7 +365,25 @@
 						}
 					}
 					return list;
-				}
+				},
+				// Keep track of the last file change in order to not prompt
+				// user if they are actively working.
+				didOpen: (e, next) => {
+					lastUserAction = new Date();
+					next(e);
+				},
+				didChange: (e, next) => {
+					lastUserAction = new Date();
+					next(e);
+				},
+				didClose: (e, next) => {
+					lastUserAction = new Date();
+					next(e);
+				},
+				didSave: (e, next) => {
+					lastUserAction = new Date();
+					next(e);
+				},
 			}
 		}
 	);
@@ -465,8 +547,7 @@
 
 export async function shouldUpdateLanguageServer(
 	tool: Tool,
-	languageServerToolPath: string,
-	makeProxyCall: boolean
+	cfg: LanguageServerConfig,
 ): Promise<semver.SemVer> {
 	// Only support updating gopls for now.
 	if (tool.name !== 'gopls') {
@@ -474,7 +555,9 @@
 	}
 
 	// First, run the "gopls version" command and parse its results.
-	const usersVersion = await getLocalGoplsVersion(languageServerToolPath);
+	// TODO(rstambler): Confirm that the gopls binary's modtime matches the
+	// modtime in the config. Update it if needed.
+	const usersVersion = await getLocalGoplsVersion(cfg);
 
 	// We might have a developer version. Don't make the user update.
 	if (usersVersion === '(devel)') {
@@ -482,7 +565,7 @@
 	}
 
 	// Get the latest gopls version. If it is for nightly, using the prereleased version is ok.
-	let latestVersion = makeProxyCall ? await getLatestGoplsVersion(tool) : tool.latestVersion;
+	let latestVersion = cfg.checkForUpdates ? await getLatestGoplsVersion(tool) : tool.latestVersion;
 
 	// 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) {
@@ -501,7 +584,8 @@
 	const usersTime = parseTimestampFromPseudoversion(usersVersion);
 	// If the user has a pseudoversion, get the timestamp for the latest gopls version and compare.
 	if (usersTime) {
-		let latestTime = makeProxyCall ? await getTimestampForVersion(tool, latestVersion) : tool.latestVersionTimestamp;
+		let latestTime = cfg.checkForUpdates ?
+			await getTimestampForVersion(tool, latestVersion) : tool.latestVersionTimestamp;
 		if (!latestTime) {
 			latestTime = tool.latestVersionTimestamp;
 		}
@@ -510,7 +594,10 @@
 
 	// If the user's version does not contain a timestamp,
 	// default to a semver comparison of the two versions.
-	const usersVersionSemver = semver.coerce(usersVersion, { includePrerelease: true, loose: true });
+	const usersVersionSemver = semver.parse(usersVersion, {
+		includePrerelease: true,
+		loose: true,
+	});
 	return semver.lt(usersVersionSemver, latestVersion) ? latestVersion : null;
 }
 
@@ -601,11 +688,11 @@
 // getLocalGoplsVersion returns the version of gopls that is currently
 // installed on the user's machine. This is determined by running the
 // `gopls version` command.
-export const getLocalGoplsVersion = async (goplsPath: string) => {
+export const getLocalGoplsVersion = async (cfg: LanguageServerConfig) => {
 	const execFile = util.promisify(cp.execFile);
 	let output: any;
 	try {
-		const { stdout } = await execFile(goplsPath, ['version'], { env: toolExecutionEnvironment() });
+		const { stdout } = await execFile(cfg.path, ['version'], { env: toolExecutionEnvironment() });
 		output = stdout;
 	} catch (e) {
 		// The "gopls version" command is not supported, or something else went wrong.
@@ -677,6 +764,7 @@
 				throwResponseError: true
 			});
 		} catch (e) {
+			console.log(`Error sending request to ${proxy}: ${e}`);
 			return null;
 		}
 		return data;
@@ -696,9 +784,13 @@
 	// It is undefined if we have not yet made the determination.
 	promptThisMonth?: boolean;
 
-	// promptThisMonthTimestamp is the date on which we determined if the user
-	// should be prompted this month.
-	promptThisMonthTimestamp?: Date;
+	// dateToPromptThisMonth is the date on which we should prompt the user
+	// this month.
+	dateToPromptThisMonth?: Date;
+
+	// dateComputedPromptThisMonth is the date on which the values of
+	// promptThisMonth and dateToPromptThisMonth were set.
+	dateComputedPromptThisMonth?: Date;
 
 	// lastDatePrompted is the most recent date that the user has been prompted.
 	lastDatePrompted?: Date;
@@ -711,10 +803,81 @@
 async function maybePromptForGoplsSurvey(): Promise<SurveyConfig> {
 	const now = new Date();
 	const cfg = getSurveyConfig();
-	const prompt = shouldPromptForGoplsSurvey(now, cfg);
-	if (!prompt) {
+	const dateToPrompt = shouldPromptForGoplsSurvey(now, cfg);
+	if (!dateToPrompt) {
 		return cfg;
 	}
+	const callback = () => {
+		const currentTime = new Date();
+
+		// Make sure the user has been idle for at least a minute.
+		if (minutesBetween(lastUserAction, currentTime) < 1) {
+			setTimeout(callback, 5 * timeMinute);
+			return;
+		}
+		promptForSurvey(cfg, now);
+	};
+	const ms = msBetween(now, dateToPrompt);
+	setTimeout(callback, ms);
+	return cfg;
+}
+
+export function shouldPromptForGoplsSurvey(now: Date, cfg: SurveyConfig): Date {
+	// If the prompt value is not set, assume we haven't prompted the user
+	// and should do so.
+	if (cfg.prompt === undefined) {
+		cfg.prompt = true;
+	}
+	if (!cfg.prompt) {
+		return;
+	}
+
+	// Check if the user has taken the survey in the last year.
+	// Don't prompt them if they have been.
+	if (cfg.lastDateAccepted) {
+		if (daysBetween(now, cfg.lastDateAccepted) < 365) {
+			return;
+		}
+	}
+
+	// Check if the user has been prompted for the survey in the last 90 days.
+	// Don't prompt them if they have been.
+	if (cfg.lastDatePrompted) {
+		if (daysBetween(now, cfg.lastDatePrompted) < 90) {
+			return;
+		}
+	}
+
+	// Check if the extension has been activated this month.
+	if (cfg.dateComputedPromptThisMonth) {
+		// The extension has been activated this month, so we should have already
+		// decided if the user should be prompted.
+		if (daysBetween(now, cfg.dateComputedPromptThisMonth) < 30) {
+			if (cfg.dateToPromptThisMonth) {
+				return cfg.dateToPromptThisMonth;
+			}
+		}
+	}
+	// This is the first activation this month (or ever), so decide if we
+	// should prompt the user. This is done by generating a random number in
+	// the range [0, 1) and checking if it is < 0.05, for a 5% probability.
+	// We then randomly pick a day in the rest of the month on which to prompt
+	// the user.
+	cfg.promptThisMonth = Math.random() < 0.05;
+	if (cfg.promptThisMonth) {
+		// end is the last day of the month, day is the random day of the
+		// month on which to prompt.
+		const end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
+		const day = randomIntInRange(now.getUTCDate(), end.getUTCDate());
+		cfg.dateToPromptThisMonth = new Date(now.getFullYear(), now.getMonth(), day);
+	} else {
+		cfg.dateToPromptThisMonth = undefined;
+	}
+	cfg.dateComputedPromptThisMonth = now;
+	return cfg.dateToPromptThisMonth;
+}
+
+async function promptForSurvey(cfg: SurveyConfig, now: Date) {
 	const selected = await vscode.window.showInformationMessage(`Looks like you're using gopls, the Go language server.
 Would you be willing to fill out a quick survey about your experience with gopls?`, 'Yes', 'Not now', 'Never');
 
@@ -726,8 +889,7 @@
 			cfg.lastDateAccepted = now;
 			cfg.prompt = true;
 
-			// Open the link to the survey.
-			vscode.env.openExternal(vscode.Uri.parse('https://www.whattimeisitrightnow.com/'));
+			await vscode.env.openExternal(vscode.Uri.parse(`https://google.qualtrics.com/jfe/form/SV_ekAdHVcVcvKUojX`));
 			break;
 		case 'Not now':
 			cfg.prompt = true;
@@ -739,52 +901,13 @@
 
 			vscode.window.showInformationMessage(`No problem! We won't ask again.`);
 			break;
-	}
-	return cfg;
-}
+		default:
+			// If the user closes the prompt without making a selection, treat it
+			// like a "Not now" response.
+			cfg.prompt = true;
 
-export function shouldPromptForGoplsSurvey(now: Date, cfg: SurveyConfig): boolean {
-	// If the prompt value is not set, assume we haven't prompted the user
-	// and should do so.
-	if (cfg.prompt === undefined) {
-		cfg.prompt = true;
+			break;
 	}
-	if (!cfg.prompt) {
-		return false;
-	}
-
-	// Check if the user has taken the survey in the last year.
-	// Don't prompt them if they have been.
-	if (cfg.lastDateAccepted) {
-		if (daysBetween(now, cfg.lastDateAccepted) < 365) {
-			return false;
-		}
-	}
-
-	// Check if the user has been prompted for the survey in the last 90 days.
-	// Don't prompt them if they have been.
-	if (cfg.lastDatePrompted) {
-		if (daysBetween(now, cfg.lastDatePrompted) < 90) {
-			return false;
-		}
-	}
-
-	// Check if the extension has been activated this month.
-	if (cfg.promptThisMonthTimestamp) {
-		// The extension has been activated this month, so we should have already
-		// decided if the user should be prompted.
-		if (daysBetween(now, cfg.promptThisMonthTimestamp) < 30) {
-			return cfg.promptThisMonth;
-		}
-	}
-	// This is the first activation this month (or ever), so decide if we
-	// should prompt the user. This is done by generating a random number
-	// and % 20 to get a 5% chance.
-	const r = Math.floor(Math.random() * 20);
-	cfg.promptThisMonth = (r % 20 === 0);
-	cfg.promptThisMonthTimestamp = now;
-
-	return cfg.promptThisMonth;
 }
 
 export const goplsSurveyConfig = 'goplsSurveyConfig';
@@ -797,7 +920,7 @@
 	try {
 		const cfg = JSON.parse(saved, (key: string, value: any) => {
 			// Make sure values that should be dates are correctly converted.
-			if (key.includes('Date')) {
+			if (key.toLowerCase().includes('date') || key.toLowerCase().includes('timestamp')) {
 				return new Date(value);
 			}
 			return value;
@@ -898,9 +1021,27 @@
 	}
 }
 
-// daysBetween returns the number of days between a and b,
-// assuming that a occurs after b.
-function daysBetween(a: Date, b: Date) {
-	const ms = a.getTime() - b.getTime();
-	return ms / (1000 * 60 * 60 * 24);
+// randomIntInRange returns a random integer between min and max, inclusive.
+function randomIntInRange(min: number, max: number): number {
+	const low = Math.ceil(min);
+	const high = Math.floor(max);
+	return Math.floor(Math.random() * (high - low + 1)) + low;
+}
+
+const timeMinute = 1000 * 60;
+const timeHour = timeMinute * 60;
+const timeDay = timeHour * 24;
+
+// daysBetween returns the number of days between a and b.
+function daysBetween(a: Date, b: Date): number {
+	return msBetween(a, b) / timeDay;
+}
+
+// minutesBetween returns the number of days between a and b.
+function minutesBetween(a: Date, b: Date): number {
+	return msBetween(a, b) / timeMinute;
+}
+
+function msBetween(a: Date, b: Date): number {
+	return Math.abs(a.getTime() - b.getTime());
 }
diff --git a/src/goLint.ts b/src/goLint.ts
index 2eb80ea..0e8abfb 100644
--- a/src/goLint.ts
+++ b/src/goLint.ts
@@ -125,6 +125,11 @@
 			// Explicit override in case .golangci.yml calls for a format we don't understand
 			args.push('--out-format=colored-line-number');
 		}
+		if (args.indexOf('--issues-exit-code=') === -1) {
+			// adds an explicit no-error-code return argument, to avoid npm error
+			// message detection logic. See golang/vscode-go/issues/411
+			args.push('--issues-exit-code=0');
+		}
 	}
 
 	if (scope === 'workspace' && currentWorkspace) {
diff --git a/src/goMain.ts b/src/goMain.ts
index aedb95f..a5abd27 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -8,6 +8,7 @@
 
 import * as path from 'path';
 import vscode = require('vscode');
+import { GoDlvDapDebugSession } from './debugAdapter2/goDlvDebug';
 import { browsePackages } from './goBrowsePackage';
 import { buildCode } from './goBuild';
 import { check, notifyIfGeneratedFile, removeTestStatus } from './goCheck';
@@ -18,7 +19,7 @@
 import { GoDebugConfigurationProvider } from './goDebugConfiguration';
 import { extractFunction, extractVariable } from './goDoctor';
 import { toolExecutionEnvironment } from './goEnv';
-import { chooseGoEnvironment } from './goEnvironmentStatus';
+import { chooseGoEnvironment, disposeGoStatusBar, setEnvironmentVariableCollection } from './goEnvironmentStatus';
 import { runFillStruct } from './goFillStruct';
 import * as goGenerateTests from './goGenerateTests';
 import { goGetPackage } from './goGetPackage';
@@ -34,7 +35,6 @@
 import { GO_MODE } from './goMode';
 import { addTags, removeTags } from './goModifytags';
 import { GO111MODULE, isModSupported } from './goModules';
-import { clearCacheForTools, fileExists, getCurrentGoRoot, setCurrentGoRoot } from './goPath';
 import { playgroundCommand } from './goPlayground';
 import { GoReferencesCodeLensProvider } from './goReferencesCodelens';
 import { GoRunTestCodeLensProvider } from './goRunTestCodelens';
@@ -53,12 +53,15 @@
 	getCurrentGoPath,
 	getExtensionCommands,
 	getGoConfig,
+	getGoEnv,
 	getGoVersion,
 	getToolsGopath,
 	getWorkspaceFolderPath,
 	handleDiagnosticErrors,
 	isGoPathSet,
+	resolvePath,
 } from './util';
+import { clearCacheForTools, envPath, fileExists, getCurrentGoRoot, setCurrentGoRoot } from './utils/goPath';
 
 export let buildDiagnosticCollection: vscode.DiagnosticCollection;
 export let lintDiagnosticCollection: vscode.DiagnosticCollection;
@@ -69,81 +72,20 @@
 // the configuration of the server.
 export let restartLanguageServer = () => { return; };
 
-export function activate(ctx: vscode.ExtensionContext): void {
+export function activate(ctx: vscode.ExtensionContext) {
 	setGlobalState(ctx.globalState);
 	setWorkspaceState(ctx.workspaceState);
+	setEnvironmentVariableCollection(ctx.environmentVariableCollection);
+
 	const configGOROOT = getGoConfig()['goroot'];
 	if (!!configGOROOT) {
-		setCurrentGoRoot(configGOROOT);
+		setCurrentGoRoot(resolvePath(configGOROOT));
 	}
 
 	updateGoVarsFromConfig().then(async () => {
-		const updateToolsCmdText = 'Update tools';
-		interface GoInfo {
-			goroot: string;
-			version: string;
-		}
-		const toolsGoInfo: { [id: string]: GoInfo } = ctx.globalState.get('toolsGoInfo') || {};
-		const toolsGopath = getToolsGopath() || getCurrentGoPath();
-		if (!toolsGoInfo[toolsGopath]) {
-			toolsGoInfo[toolsGopath] = { goroot: null, version: null };
-		}
-		const prevGoroot = toolsGoInfo[toolsGopath].goroot;
-		const currentGoroot: string = getCurrentGoRoot().toLowerCase();
-		if (prevGoroot && prevGoroot.toLowerCase() !== currentGoroot) {
-			vscode.window
-				.showInformationMessage(
-					`Your current goroot (${currentGoroot}) is different than before (${prevGoroot}), a few Go tools may need recompiling`,
-					updateToolsCmdText
-				)
-				.then((selected) => {
-					if (selected === updateToolsCmdText) {
-						installAllTools(true);
-					}
-				});
-		} else {
-			const currentVersion = await getGoVersion();
-			if (currentVersion) {
-				const prevVersion = toolsGoInfo[toolsGopath].version;
-				const currVersionString = currentVersion.format();
-
-				if (prevVersion !== currVersionString) {
-					if (prevVersion) {
-						vscode.window
-							.showInformationMessage(
-								'Your Go version is different than before, a few Go tools may need re-compiling',
-								updateToolsCmdText
-							)
-							.then((selected) => {
-								if (selected === updateToolsCmdText) {
-									installAllTools(true);
-								}
-							});
-					}
-					toolsGoInfo[toolsGopath].version = currVersionString;
-				}
-			}
-		}
-		toolsGoInfo[toolsGopath].goroot = currentGoroot;
-		ctx.globalState.update('toolsGoInfo', toolsGoInfo);
-
+		suggestUpdates(ctx);
 		offerToInstallTools();
-
-		// Subscribe to notifications for changes to the configuration
-		// of the language server, even if it's not currently in use.
-		ctx.subscriptions.push(vscode.workspace.onDidChangeConfiguration(
-			(e) => watchLanguageServerConfiguration(e)
-		));
-
-		// Set the function that is used to restart the language server.
-		// This is necessary, even if the language server is not currently
-		// in use.
-		restartLanguageServer = async () => {
-			startLanguageServerWithFallback(ctx, false);
-		};
-
-		// Start the language server, or fallback to the default language providers.
-		startLanguageServerWithFallback(ctx, true);
+		configureLanguageServer(ctx);
 
 		if (
 			vscode.window.activeTextEditor &&
@@ -151,6 +93,7 @@
 			isGoPathSet()
 		) {
 			// Check mod status so that cache is updated and then run build/lint/vet
+			// TODO(hyangah): skip if the language server is used (it will run build too)
 			isModSupported(vscode.window.activeTextEditor.document.uri).then(() => {
 				runBuilds(vscode.window.activeTextEditor.document, getGoConfig());
 			});
@@ -172,7 +115,12 @@
 
 	ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, testCodeLensProvider));
 	ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, referencesCodeLensProvider));
-	ctx.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('go', new GoDebugConfigurationProvider()));
+
+	// debug
+	ctx.subscriptions.push(
+		vscode.debug.registerDebugConfigurationProvider('go', new GoDebugConfigurationProvider('go')));
+	ctx.subscriptions.push(
+		vscode.debug.registerDebugConfigurationProvider('godlvdap', new GoDebugConfigurationProvider('godlvdap')));
 
 	buildDiagnosticCollection = vscode.languages.createDiagnosticCollection('go');
 	ctx.subscriptions.push(buildDiagnosticCollection);
@@ -187,60 +135,13 @@
 
 	ctx.subscriptions.push(
 		vscode.commands.registerCommand('go.gopath', () => {
-			const gopath = getCurrentGoPath();
-			let msg = `${gopath} is the current GOPATH.`;
-			const wasInfered = getGoConfig()['inferGopath'];
-			const root = getWorkspaceFolderPath(
-				vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.uri
-			);
-
-			// not only if it was configured, but if it was successful.
-			if (wasInfered && root && root.indexOf(gopath) === 0) {
-				const inferredFrom = vscode.window.activeTextEditor ? 'current folder' : 'workspace root';
-				msg += ` It is inferred from ${inferredFrom}`;
-			}
-
-			vscode.window.showInformationMessage(msg);
-			return gopath;
-		})
-	);
+			getCurrentGoPathCommand();
+		}));
 
 	ctx.subscriptions.push(
 		vscode.commands.registerCommand('go.locate.tools', async () => {
-			outputChannel.show();
-			outputChannel.clear();
-			outputChannel.appendLine('Checking configured tools....');
-			// Tool's path search is done by getBinPathWithPreferredGopath
-			// which searches places in the following order
-			// 1) absolute path for the alternateTool
-			// 2) GOBIN
-			// 3) toolsGopath
-			// 4) gopath
-			// 5) GOROOT
-			// 6) PATH
-			outputChannel.appendLine('GOBIN: ' + process.env['GOBIN']);
-			outputChannel.appendLine('toolsGopath: ' + getToolsGopath());
-			outputChannel.appendLine('gopath: ' + getCurrentGoPath());
-			outputChannel.appendLine('GOROOT: ' + getCurrentGoRoot());
-			outputChannel.appendLine('PATH: ' + process.env['PATH']);
-			outputChannel.appendLine('');
-
-			const goVersion = await getGoVersion();
-			const allTools = getConfiguredTools(goVersion);
-
-			allTools.forEach((tool) => {
-				const toolPath = getBinPath(tool.name);
-				// TODO(hyangah): print alternate tool info if set.
-				let msg = 'not installed';
-				if (path.isAbsolute(toolPath)) {
-					// getBinPath returns the absolute path is the tool exists.
-					// (See getBinPathWithPreferredGopath which is called underneath)
-					msg = 'installed';
-				}
-				outputChannel.appendLine(`   ${tool.name}: ${toolPath} ${msg}`);
-			});
-		})
-	);
+			getConfiguredGoToolsCommand();
+		}));
 
 	ctx.subscriptions.push(
 		vscode.commands.registerCommand('go.add.tags', (args) => {
@@ -292,6 +193,10 @@
 
 	ctx.subscriptions.push(
 		vscode.commands.registerCommand('go.debug.cursor', (args) => {
+			if (vscode.debug.activeDebugSession) {
+				vscode.window.showErrorMessage('Debug session has already been started.');
+				return;
+			}
 			const goConfig = getGoConfig();
 			testAtCursor(goConfig, 'debug', args);
 		})
@@ -408,7 +313,7 @@
 				e.affectsConfiguration('go.gopath') ||
 				e.affectsConfiguration('go.toolsEnvVars') ||
 				e.affectsConfiguration('go.testEnvFile')) {
-					updateGoVarsFromConfig();
+				updateGoVarsFromConfig();
 			}
 			// If there was a change in "toolsGopath" setting, then clear cache for go tools
 			if (getToolsGopath() !== getToolsGopath(false)) {
@@ -555,8 +460,7 @@
 						updateWorkspaceState(lastCoverProfilePathKey, coverProfilePath);
 					}
 					applyCodeCoverageToAllEditors(
-						coverProfilePath,
-						path.dirname(vscode.window.activeTextEditor.document.fileName)
+						coverProfilePath
 					);
 				});
 		})
@@ -575,7 +479,10 @@
 }
 
 export function deactivate() {
-	return Promise.all([cancelRunningTests(), Promise.resolve(cleanupTempDir())]);
+	return Promise.all([
+		cancelRunningTests(),
+		Promise.resolve(cleanupTempDir()),
+		Promise.resolve(disposeGoStatusBar())]);
 }
 
 function runBuilds(document: vscode.TextDocument, goConfig: vscode.WorkspaceConfiguration) {
@@ -646,3 +553,147 @@
 		promptForMissingTool(tool);
 	}
 }
+
+async function suggestUpdates(ctx: vscode.ExtensionContext) {
+	const updateToolsCmdText = 'Update tools';
+	interface GoInfo {
+		goroot: string;
+		version: string;
+	}
+	const toolsGoInfo: { [id: string]: GoInfo } = ctx.globalState.get('toolsGoInfo') || {};
+	const toolsGopath = getToolsGopath() || getCurrentGoPath();
+	if (!toolsGoInfo[toolsGopath]) {
+		toolsGoInfo[toolsGopath] = { goroot: null, version: null };
+	}
+	const prevGoroot = toolsGoInfo[toolsGopath].goroot;
+	const currentGoroot: string = getCurrentGoRoot().toLowerCase();
+	if (prevGoroot && prevGoroot.toLowerCase() !== currentGoroot) {
+		vscode.window
+			.showInformationMessage(
+				`Your current goroot (${currentGoroot}) is different than before (${prevGoroot}), a few Go tools may need recompiling`,
+				updateToolsCmdText
+			)
+			.then((selected) => {
+				if (selected === updateToolsCmdText) {
+					installAllTools(true);
+				}
+			});
+	} else {
+		const currentVersion = await getGoVersion();
+		if (currentVersion) {
+			const prevVersion = toolsGoInfo[toolsGopath].version;
+			const currVersionString = currentVersion.format();
+
+			if (prevVersion !== currVersionString) {
+				if (prevVersion) {
+					vscode.window
+						.showInformationMessage(
+							'Your Go version is different than before, a few Go tools may need re-compiling',
+							updateToolsCmdText
+						)
+						.then((selected) => {
+							if (selected === updateToolsCmdText) {
+								installAllTools(true);
+							}
+						});
+				}
+				toolsGoInfo[toolsGopath].version = currVersionString;
+			}
+		}
+	}
+	toolsGoInfo[toolsGopath].goroot = currentGoroot;
+	ctx.globalState.update('toolsGoInfo', toolsGoInfo);
+}
+
+function configureLanguageServer(ctx: vscode.ExtensionContext) {
+	// Subscribe to notifications for changes to the configuration
+	// of the language server, even if it's not currently in use.
+	ctx.subscriptions.push(vscode.workspace.onDidChangeConfiguration(
+		(e) => watchLanguageServerConfiguration(e)
+	));
+
+	// Set the function that is used to restart the language server.
+	// This is necessary, even if the language server is not currently
+	// in use.
+	restartLanguageServer = async () => {
+		startLanguageServerWithFallback(ctx, false);
+	};
+
+	// Start the language server, or fallback to the default language providers.
+	startLanguageServerWithFallback(ctx, true);
+
+}
+
+function getCurrentGoPathCommand() {
+	const gopath = getCurrentGoPath();
+	let msg = `${gopath} is the current GOPATH.`;
+	const wasInfered = getGoConfig()['inferGopath'];
+	const root = getWorkspaceFolderPath(
+		vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.uri
+	);
+
+	// not only if it was configured, but if it was successful.
+	if (wasInfered && root && root.indexOf(gopath) === 0) {
+		const inferredFrom = vscode.window.activeTextEditor ? 'current folder' : 'workspace root';
+		msg += ` It is inferred from ${inferredFrom}`;
+	}
+
+	vscode.window.showInformationMessage(msg);
+	return gopath;
+}
+
+async function getConfiguredGoToolsCommand() {
+	outputChannel.show();
+	outputChannel.clear();
+	outputChannel.appendLine('Checking configured tools....');
+	// Tool's path search is done by getBinPathWithPreferredGopath
+	// which searches places in the following order
+	// 1) absolute path for the alternateTool
+	// 2) GOBIN
+	// 3) toolsGopath
+	// 4) gopath
+	// 5) GOROOT
+	// 6) PATH
+	outputChannel.appendLine('GOBIN: ' + process.env['GOBIN']);
+	outputChannel.appendLine('toolsGopath: ' + getToolsGopath());
+	outputChannel.appendLine('gopath: ' + getCurrentGoPath());
+	outputChannel.appendLine('GOROOT: ' + getCurrentGoRoot());
+	outputChannel.appendLine('PATH: ' + process.env['PATH']);
+	outputChannel.appendLine('');
+
+	const goVersion = await getGoVersion();
+	const allTools = getConfiguredTools(goVersion);
+
+	allTools.forEach((tool) => {
+		const toolPath = getBinPath(tool.name);
+		// TODO(hyangah): print alternate tool info if set.
+		let msg = 'not installed';
+		if (path.isAbsolute(toolPath)) {
+			// getBinPath returns the absolute path is the tool exists.
+			// (See getBinPathWithPreferredGopath which is called underneath)
+			msg = 'installed';
+		}
+		outputChannel.appendLine(`   ${tool.name}: ${toolPath} ${msg}`);
+	});
+
+	let folders = vscode.workspace.workspaceFolders?.map((folder) => {
+		return { name: folder.name, path: folder.uri.fsPath };
+	});
+	if (!folders) {
+		folders = [{ name: 'no folder', path: undefined }];
+	}
+
+	outputChannel.appendLine('');
+	outputChannel.appendLine('go env');
+	for (const folder of folders) {
+		outputChannel.appendLine(`Workspace Folder (${folder.name}): ${folder.path}`);
+		try {
+			const out = await getGoEnv(folder.path);
+			// Append '\t' to the beginning of every line (^) of 'out'.
+			// 'g' = 'global matching', and 'm' = 'multi-line matching'
+			outputChannel.appendLine(out.replace(/^/gm, '\t'));
+		} catch (e) {
+			outputChannel.appendLine(`failed to run 'go env': ${e}`);
+		}
+	}
+}
diff --git a/src/goModules.ts b/src/goModules.ts
index 2a41455..82077ed 100644
--- a/src/goModules.ts
+++ b/src/goModules.ts
@@ -8,10 +8,10 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { installTools } from './goInstallTools';
-import { envPath, fixDriveCasingInWindows, getCurrentGoRoot } from './goPath';
 import { getTool } from './goTools';
 import { getFromGlobalState, updateGlobalState } from './stateUtils';
 import { getBinPath, getGoConfig, getGoVersion, getModuleCache } from './util';
+import { envPath, fixDriveCasingInWindows, getCurrentGoRoot } from './utils/goPath';
 
 export let GO111MODULE: string;
 
@@ -37,14 +37,14 @@
 	});
 }
 
-export function isModSupported(fileuri: vscode.Uri): Promise<boolean> {
-	return getModFolderPath(fileuri).then((modPath) => !!modPath);
+export function isModSupported(fileuri: vscode.Uri, isDir?: boolean): Promise<boolean> {
+	return getModFolderPath(fileuri, isDir).then((modPath) => !!modPath);
 }
 
 export const packagePathToGoModPathMap: { [key: string]: string } = {};
 
-export async function getModFolderPath(fileuri: vscode.Uri): Promise<string> {
-	const pkgPath = path.dirname(fileuri.fsPath);
+export async function getModFolderPath(fileuri: vscode.Uri, isDir?: boolean): Promise<string> {
+	const pkgPath = isDir ? fileuri.fsPath : path.dirname(fileuri.fsPath);
 	if (packagePathToGoModPathMap[pkgPath]) {
 		return packagePathToGoModPathMap[pkgPath];
 	}
@@ -62,7 +62,6 @@
 
 	let goModEnvResult = await runGoModEnv(pkgPath);
 	if (goModEnvResult) {
-		logModuleUsage();
 		goModEnvResult = path.dirname(goModEnvResult);
 		const goConfig = getGoConfig(fileuri);
 
@@ -73,32 +72,23 @@
 			);
 		}
 
-		// TODO(rstambler): This will offer multiple prompts to the user, but
-		// it's still better than waiting for user input. Ideally, this should
-		// be combined into one prompt.
 		if (goConfig['useLanguageServer'] === false) {
 			const promptMsg =
 				'For better performance using Go modules, you can try the experimental Go language server, gopls.';
-			promptToUpdateToolForModules('gopls', promptMsg, goConfig);
-
-			if (goConfig['formatTool'] === 'goreturns') {
-				const promptMsgForFormatTool = `The goreturns tool does not support Go modules. Please update the "formatTool" setting to goimports.`;
-				promptToUpdateToolForModules('switchFormatToolToGoimports', promptMsgForFormatTool, goConfig);
-			}
+			promptToUpdateToolForModules('gopls', promptMsg, goConfig)
+			.then((choseToUpdate) => {
+				if (choseToUpdate || goConfig['formatTool'] !== 'goreturns') {
+					return;
+				}
+				const promptFormatToolMsg = `The goreturns tool does not support Go modules. Please update the "formatTool" setting to "goimports".`;
+				promptToUpdateToolForModules('switchFormatToolToGoimports', promptFormatToolMsg, goConfig);
+			});
 		}
 	}
 	packagePathToGoModPathMap[pkgPath] = goModEnvResult;
 	return goModEnvResult;
 }
 
-let moduleUsageLogged = false;
-function logModuleUsage() {
-	if (moduleUsageLogged) {
-		return;
-	}
-	moduleUsageLogged = true;
-}
-
 const promptedToolsForCurrentSession = new Set<string>();
 export async function promptToUpdateToolForModules(
 	tool: string,
diff --git a/src/goOutline.ts b/src/goOutline.ts
index 97af953..9e52f6d 100644
--- a/src/goOutline.ts
+++ b/src/goOutline.ts
@@ -13,9 +13,9 @@
 	getBinPath,
 	getFileArchive,
 	getGoConfig,
-	killProcess,
 	makeMemoizedByteOffsetConverter
 } from './util';
+import {killProcess} from './utils/processUtils';
 
 // Keep in sync with https://github.com/ramya-rao-a/go-outline
 export interface GoOutlineRange {
diff --git a/src/goPackages.ts b/src/goPackages.ts
index 5c7fce7..20eefef 100644
--- a/src/goPackages.ts
+++ b/src/goPackages.ts
@@ -8,8 +8,8 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
-import { envPath, fixDriveCasingInWindows, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './goPath';
 import { getBinPath, getCurrentGoPath, getGoVersion, isVendorSupported } from './util';
+import { envPath, fixDriveCasingInWindows, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
 
 type GopkgsDone = (res: Map<string, PackageInfo>) => void;
 interface Cache {
@@ -258,7 +258,14 @@
 /**
  * Returns mapping between import paths and folder paths for all packages under given folder (vendor will be excluded)
  */
-export function getNonVendorPackages(currentFolderPath: string): Promise<Map<string, string>> {
+export function getNonVendorPackages(
+	currentFolderPath: string, recursive: boolean = true): Promise<Map<string, string>> {
+
+	const target = recursive ? './...' : '.';  // go list ./... excludes vendor dirs since 1.9
+	return getImportPathToFolder([target], currentFolderPath);
+}
+
+export function getImportPathToFolder(targets: string[], cwd?: string): Promise<Map<string, string>> {
 	const goRuntimePath = getBinPath('go');
 	if (!goRuntimePath) {
 		console.warn(
@@ -266,11 +273,12 @@
 		);
 		return;
 	}
+
 	return new Promise<Map<string, string>>((resolve, reject) => {
 		const childProcess = cp.spawn(
 			goRuntimePath,
-			['list', '-f', 'ImportPath: {{.ImportPath}} FolderPath: {{.Dir}}', './...'],
-			{ cwd: currentFolderPath, env: toolExecutionEnvironment() }
+			['list', '-f', 'ImportPath: {{.ImportPath}} FolderPath: {{.Dir}}', ...targets],
+			{ cwd, env: toolExecutionEnvironment() }
 		);
 		const chunks: any[] = [];
 		childProcess.stdout.on('data', (stdout) => {
@@ -281,16 +289,13 @@
 			const lines = chunks.join('').toString().split('\n');
 			const result = new Map<string, string>();
 
-			const version = await getGoVersion();
-			const vendorAlreadyExcluded = version.gt('1.8');
-
 			lines.forEach((line) => {
 				const matches = line.match(pkgToFolderMappingRegex);
 				if (!matches || matches.length !== 3) {
 					return;
 				}
 				const [_, pkgPath, folderPath] = matches;
-				if (!pkgPath || (!vendorAlreadyExcluded && pkgPath.includes('/vendor/'))) {
+				if (!pkgPath) {
 					return;
 				}
 				result.set(pkgPath, folderPath);
diff --git a/src/goReferences.ts b/src/goReferences.ts
index 44a86fc..1aba8d9 100644
--- a/src/goReferences.ts
+++ b/src/goReferences.ts
@@ -15,9 +15,9 @@
 	canonicalizeGOPATHPrefix,
 	getBinPath,
 	getFileArchive,
-	getGoConfig,
-	killTree
+	getGoConfig
 } from './util';
+import {killProcessTree} from './utils/processUtils';
 
 export class GoReferenceProvider implements vscode.ReferenceProvider {
 	public provideReferences(
@@ -102,7 +102,7 @@
 			if (process.pid) {
 				process.stdin.end(getFileArchive(document));
 			}
-			token.onCancellationRequested(() => killTree(process.pid));
+			token.onCancellationRequested(() => killProcessTree(process));
 		});
 	}
 }
diff --git a/src/goRename.ts b/src/goRename.ts
index 55a97f7..ff71aa3 100644
--- a/src/goRename.ts
+++ b/src/goRename.ts
@@ -11,7 +11,8 @@
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool } from './goInstallTools';
 import { outputChannel } from './goStatus';
-import { byteOffsetAt, canonicalizeGOPATHPrefix, getBinPath, getGoConfig, killTree } from './util';
+import { byteOffsetAt, canonicalizeGOPATHPrefix, getBinPath, getGoConfig } from './util';
+import {killProcessTree} from './utils/processUtils';
 
 export class GoRenameProvider implements vscode.RenameProvider {
 	public provideRenameEdits(
@@ -50,7 +51,7 @@
 
 			let p: cp.ChildProcess;
 			if (token) {
-				token.onCancellationRequested(() => killTree(p.pid));
+				token.onCancellationRequested(() => killProcessTree(p));
 			}
 
 			p = cp.execFile(gorename, gorenameArgs, { env }, (err, stdout, stderr) => {
diff --git a/src/goSuggest.ts b/src/goSuggest.ts
index e676ca0..80f3278 100644
--- a/src/goSuggest.ts
+++ b/src/goSuggest.ts
@@ -13,7 +13,6 @@
 import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
 import { isModSupported } from './goModules';
 import { getImportablePackages, PackageInfo } from './goPackages';
-import { getCurrentGoWorkspaceFromGOPATH } from './goPath';
 import {
 	byteOffsetAt,
 	getBinPath,
@@ -28,6 +27,7 @@
 	parseFilePrelude,
 	runGodoc
 } from './util';
+import { getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
 
 function vscodeKindFromGoCodeClass(kind: string, type: string): vscode.CompletionItemKind {
 	switch (kind) {
diff --git a/src/goSymbol.ts b/src/goSymbol.ts
index b97e018..9c3bb15 100644
--- a/src/goSymbol.ts
+++ b/src/goSymbol.ts
@@ -9,8 +9,9 @@
 import vscode = require('vscode');
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
-import { getCurrentGoRoot } from './goPath';
-import { getBinPath, getGoConfig, getWorkspaceFolderPath, killTree } from './util';
+import { getBinPath, getGoConfig, getWorkspaceFolderPath} from './util';
+import { getCurrentGoRoot } from './utils/goPath';
+import {killProcessTree} from './utils/processUtils';
 
 // Keep in sync with github.com/acroca/go-symbols'
 interface GoSymbolDeclaration {
@@ -118,7 +119,7 @@
 	let p: cp.ChildProcess;
 
 	if (token) {
-		token.onCancellationRequested(() => killTree(p.pid));
+		token.onCancellationRequested(() => killProcessTree(p));
 	}
 
 	return new Promise((resolve, reject) => {
diff --git a/src/goTest.ts b/src/goTest.ts
index b25c78a..5b1576d 100644
--- a/src/goTest.ts
+++ b/src/goTest.ts
@@ -241,11 +241,13 @@
 		vscode.window.showInformationMessage('No workspace is open to run tests.');
 		return;
 	}
+	let workspaceUriIsDir = true;
 	let workspaceUri = vscode.workspace.workspaceFolders[0].uri;
 	if (
 		vscode.window.activeTextEditor &&
 		vscode.workspace.getWorkspaceFolder(vscode.window.activeTextEditor.document.uri)
 	) {
+		workspaceUriIsDir = false;
 		workspaceUri = vscode.workspace.getWorkspaceFolder(vscode.window.activeTextEditor.document.uri).uri;
 	}
 
@@ -258,7 +260,7 @@
 	// Remember this config as the last executed test.
 	lastTestConfig = testConfig;
 
-	isModSupported(workspaceUri).then((isMod) => {
+	isModSupported(workspaceUri, workspaceUriIsDir).then((isMod) => {
 		testConfig.isMod = isMod;
 		goTest(testConfig).then(null, (err) => {
 			console.error(err);
diff --git a/src/goTools.ts b/src/goTools.ts
index 91d72dc..0153fe3 100644
--- a/src/goTools.ts
+++ b/src/goTools.ts
@@ -36,7 +36,7 @@
 	// close performs any shutdown tasks that a tool must execute before a new
 	// version is installed. It returns a string containing an error message on
 	// failure.
-	close?: () => Promise<string>;
+	close?: (env: NodeJS.Dict<string>) => Promise<string>;
 }
 
 /**
@@ -182,19 +182,20 @@
 		importPath: 'github.com/mdempsky/gocode',
 		isImportant: true,
 		description: 'Auto-completion, does not work with modules',
-		close: async (): Promise<string> => {
+		close: async (env: NodeJS.Dict<string>): Promise<string> => {
 			const toolBinPath = getBinPath('gocode');
 			if (!path.isAbsolute(toolBinPath)) {
 				return '';
 			}
 			try {
 				const execFile = util.promisify(cp.execFile);
-				const { stderr } = await execFile(toolBinPath, ['close']);
+				const { stderr } = await execFile(toolBinPath, ['close'], {env, timeout: 10000});  // give 10sec.
 				if (stderr.indexOf(`rpc: can't find service Server.`) > -1) {
 					return `Installing gocode aborted as existing process cannot be closed. Please kill the running process for gocode and try again.`;
 				}
 			} catch (err) {
 				// This may fail if gocode isn't already running.
+				console.log(`gocode close failed: ${err}`);
 			}
 			return '';
 		},
diff --git a/src/goTypeDefinition.ts b/src/goTypeDefinition.ts
index 100deb1..0487d70 100644
--- a/src/goTypeDefinition.ts
+++ b/src/goTypeDefinition.ts
@@ -17,9 +17,9 @@
 	getBinPath,
 	getFileArchive,
 	getGoConfig,
-	goBuiltinTypes,
-	killTree
+	goBuiltinTypes
 } from './util';
+import {killProcessTree} from './utils/processUtils';
 
 interface GuruDescribeOutput {
 	desc: string;
@@ -130,7 +130,7 @@
 			if (process.pid) {
 				process.stdin.end(getFileArchive(document));
 			}
-			token.onCancellationRequested(() => killTree(process.pid));
+			token.onCancellationRequested(() => killProcessTree(process));
 		});
 	}
 }
diff --git a/src/stateUtils.ts b/src/stateUtils.ts
index c7b49c2..7a83832 100644
--- a/src/stateUtils.ts
+++ b/src/stateUtils.ts
@@ -43,3 +43,7 @@
 export function setWorkspaceState(state: vscode.Memento) {
 	workspaceState = state;
 }
+
+export function getWorkspaceState(): vscode.Memento {
+	return workspaceState;
+}
diff --git a/src/testUtils.ts b/src/testUtils.ts
index 092dc45..cd00956 100644
--- a/src/testUtils.ts
+++ b/src/testUtils.ts
@@ -12,18 +12,18 @@
 import { getCurrentPackage } from './goModules';
 import { GoDocumentSymbolProvider } from './goOutline';
 import { getNonVendorPackages } from './goPackages';
-import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH, parseEnvFile } from './goPath';
 import {
 	getBinPath,
 	getCurrentGoPath,
 	getGoVersion,
 	getTempFilePath,
-	killTree,
 	LineBuffer,
-	resolvePath,
+	resolvePath
 } from './util';
+import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH, parseEnvFile } from './utils/goPath';
+import { killProcessTree } from './utils/processUtils';
 
-const outputChannel = vscode.window.createOutputChannel('Go Tests');
+const testOutputChannel = vscode.window.createOutputChannel('Go Tests');
 const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
 statusBarItem.command = 'go.test.cancel';
 statusBarItem.text = '$(x) Cancel Running Tests';
@@ -77,6 +77,10 @@
 	 * Whether code coverage should be generated and applied.
 	 */
 	applyCodeCoverage?: boolean;
+	/**
+	 * Output channel for test output.
+	 */
+	outputChannel?: vscode.OutputChannel;
 }
 
 export function getTestEnvVars(config: vscode.WorkspaceConfiguration): any {
@@ -224,11 +228,26 @@
 }
 
 /**
+ * go test -json output format.
+ * which is a subset of https://golang.org/cmd/test2json/#hdr-Output_Format
+ * and includes only the fields that we are using.
+ */
+interface GoTestOutput {
+	Action: string;
+	Output?: string;
+	Package?: string;
+}
+
+/**
  * Runs go test and presents the output in the 'Go' channel.
  *
  * @param goConfig Configuration for the Go extension.
  */
 export async function goTest(testconfig: TestConfig): Promise<boolean> {
+	let outputChannel = testOutputChannel;
+	if (testconfig.outputChannel) {
+		outputChannel = testconfig.outputChannel;
+	}
 	const tmpCoverPath = getTempFilePath('go-code-cover');
 	const testResult = await new Promise<boolean>(async (resolve, reject) => {
 		// We do not want to clear it if tests are already running, as that could
@@ -267,32 +286,24 @@
 			return Promise.resolve();
 		}
 
-		const currentGoWorkspace = testconfig.isMod
-			? ''
-			: getCurrentGoWorkspaceFromGOPATH(getCurrentGoPath(), testconfig.dir);
-		let targets = targetArgs(testconfig);
+		let targets = testconfig.includeSubDirectories ? ['./...'] : targetArgs(testconfig);
+
+		let currentGoWorkspace = '';
 		let getCurrentPackagePromise = Promise.resolve('');
-		if (testconfig.isMod) {
-			getCurrentPackagePromise = getCurrentPackage(testconfig.dir);
-		} else if (currentGoWorkspace) {
-			getCurrentPackagePromise = Promise.resolve(testconfig.dir.substr(currentGoWorkspace.length + 1));
-		}
 		let pkgMapPromise: Promise<Map<string, string> | null> = Promise.resolve(null);
-		if (testconfig.includeSubDirectories) {
-			if (testconfig.isMod) {
-				targets = ['./...'];
-				// We need the mapping to get absolute paths for the files in the test output
-				pkgMapPromise = getNonVendorPackages(testconfig.dir);
-			} else {
+
+		if (testconfig.isMod) {
+			// We need the mapping to get absolute paths for the files in the test output.
+			pkgMapPromise = getNonVendorPackages(testconfig.dir, !!testconfig.includeSubDirectories);
+		} else {  // GOPATH mode
+			currentGoWorkspace = getCurrentGoWorkspaceFromGOPATH(getCurrentGoPath(), testconfig.dir);
+			if (currentGoWorkspace) {
+				getCurrentPackagePromise = Promise.resolve(testconfig.dir.substr(currentGoWorkspace.length + 1));
+			}
+			if (testconfig.includeSubDirectories) {
 				pkgMapPromise = getGoVersion().then((goVersion) => {
-					if (goVersion.gt('1.8')) {
-						targets = ['./...'];
-						return null; // We dont need mapping, as we can derive the absolute paths from package path
-					}
-					return getNonVendorPackages(testconfig.dir).then((pkgMap) => {
-						targets = Array.from(pkgMap.keys());
-						return pkgMap; // We need the individual package paths to pass to `go test`
-					});
+					targets = ['./...'];
+					return null; // We dont need mapping, as we can derive the absolute paths from package path
 				});
 			}
 		}
@@ -303,6 +314,7 @@
 					pkgMap = new Map<string, string>();
 				}
 				// Use the package name to be in the args to enable running tests in symlinked directories
+				// TODO(hyangah): check why modules mode didn't set currentPackage.
 				if (!testconfig.includeSubDirectories && currentPackage) {
 					targets.splice(0, 0, currentPackage);
 				}
@@ -314,6 +326,10 @@
 					outTargets.push(...targets);
 				}
 
+				if (args.includes('-v') && !args.includes('-json')) {
+					args.push('-json');
+				}
+
 				args.push(...targets);
 
 				// ensure that user provided flags are appended last (allow use of -args ...)
@@ -331,30 +347,11 @@
 				const outBuf = new LineBuffer();
 				const errBuf = new LineBuffer();
 
-				// 1=ok/FAIL, 2=package, 3=time/(cached)
-				const packageResultLineRE = /^(ok|FAIL)[ \t]+(.+?)[ \t]+([0-9\.]+s|\(cached\))/;
-				const lineWithErrorRE = /^(\t|\s\s\s\s)\S/;
 				const testResultLines: string[] = [];
+				const processTestResultLine = args.includes('-json') ?
+					processTestResultLineInJSONMode(pkgMap, currentGoWorkspace, outputChannel) :
+					processTestResultLineInStandardMode(pkgMap, currentGoWorkspace, testResultLines, outputChannel);
 
-				const processTestResultLine = (line: string) => {
-					testResultLines.push(line);
-					const result = line.match(packageResultLineRE);
-					if (result && (pkgMap.has(result[2]) || currentGoWorkspace)) {
-						const hasTestFailed = line.startsWith('FAIL');
-						const packageNameArr = result[2].split('/');
-						const baseDir = pkgMap.get(result[2]) || path.join(currentGoWorkspace, ...packageNameArr);
-						testResultLines.forEach((testResultLine) => {
-							if (hasTestFailed && lineWithErrorRE.test(testResultLine)) {
-								outputChannel.appendLine(expandFilePathInOutput(testResultLine, baseDir));
-							} else {
-								outputChannel.appendLine(testResultLine);
-							}
-						});
-						testResultLines.splice(0);
-					}
-				};
-
-				// go test emits test results on stdout, which contain file names relative to the package under test
 				outBuf.onLine((line) => processTestResultLine(line));
 				outBuf.onDone((last) => {
 					if (last) {
@@ -407,11 +404,68 @@
 	return testResult;
 }
 
+function processTestResultLineInJSONMode(
+	pkgMap: Map<string, string>,
+	currentGoWorkspace: string,
+	outputChannel: vscode.OutputChannel) {
+	return (line: string) => {
+		try {
+			const m = <GoTestOutput>(JSON.parse(line));
+			if (m.Action !== 'output' || !m.Output) {
+				return;
+			}
+			const out = m.Output;
+			const pkg = m.Package;
+			if (pkg && (pkgMap.has(pkg) || currentGoWorkspace)) {
+				const pkgNameArr = pkg.split('/');
+				const baseDir = pkgMap.get(pkg) || path.join(currentGoWorkspace, ...pkgNameArr);
+				// go test emits test results on stdout, which contain file names relative to the package under test
+				outputChannel.appendLine(expandFilePathInOutput(out, baseDir).trimRight());
+			} else {
+				outputChannel.appendLine(out.trimRight());
+			}
+		} catch (e) {
+			// TODO: disable this log if it becomes too spammy.
+			console.log(`failed to parse JSON: ${e}: ${line}`);
+			// Build failures or other messages come in non-JSON format. So, output as they are.
+			outputChannel.appendLine(line);
+		}
+	};
+}
+
+function processTestResultLineInStandardMode(
+	pkgMap: Map<string, string>,
+	currentGoWorkspace: string,
+	testResultLines: string[],
+	outputChannel: vscode.OutputChannel) {
+	// 1=ok/FAIL, 2=package, 3=time/(cached)
+	const packageResultLineRE = /^(ok|FAIL)\s+(\S+)\s+([0-9\.]+s|\(cached\))/;
+	const lineWithErrorRE = /^(\t|\s\s\s\s)\S/;
+
+	return (line: string) => {
+		testResultLines.push(line);
+		const result = line.match(packageResultLineRE);
+		if (result && (pkgMap.has(result[2]) || currentGoWorkspace)) {
+			const hasTestFailed = line.startsWith('FAIL');
+			const packageNameArr = result[2].split('/');
+			const baseDir = pkgMap.get(result[2]) || path.join(currentGoWorkspace, ...packageNameArr);
+			testResultLines.forEach((testResultLine) => {
+				if (hasTestFailed && lineWithErrorRE.test(testResultLine)) {
+					outputChannel.appendLine(expandFilePathInOutput(testResultLine, baseDir));
+				} else {
+					outputChannel.appendLine(testResultLine);
+				}
+			});
+			testResultLines.splice(0);
+		}
+	};
+}
+
 /**
  * Reveals the output channel in the UI.
  */
 export function showTestOutput() {
-	outputChannel.show(true);
+	testOutputChannel.show(true);
 }
 
 /**
@@ -420,7 +474,7 @@
 export function cancelRunningTests(): Thenable<boolean> {
 	return new Promise<boolean>((resolve, reject) => {
 		runningTestProcesses.forEach((tp) => {
-			killTree(tp.pid);
+			killProcessTree(tp);
 		});
 		// All processes are now dead. Empty the array to prepare for the next run.
 		runningTestProcesses.splice(0, runningTestProcesses.length);
@@ -431,7 +485,7 @@
 function expandFilePathInOutput(output: string, cwd: string): string {
 	const lines = output.split('\n');
 	for (let i = 0; i < lines.length; i++) {
-		const matches = lines[i].match(/^\s*(.+.go):(\d+):/);
+		const matches = lines[i].match(/\s+(\S+.go):(\d+):\s+/);
 		if (matches && matches[1] && !path.isAbsolute(matches[1])) {
 			lines[i] = lines[i].replace(matches[1], path.join(cwd, matches[1]));
 		}
@@ -464,7 +518,7 @@
 			// which will result in the correct thing to happen
 			if (testFunctions.length > 0) {
 				if (testFunctions.length === 1) {
-					params = params.concat(['-run', util.format('^%s$', testFunctions.pop())]);
+					params = params.concat(['-run', util.format('^%s$', testFunctions[0])]);
 				} else {
 					params = params.concat(['-run', util.format('^(%s)$', testFunctions.join('|'))]);
 				}
diff --git a/src/util.ts b/src/util.ts
index fc24810..23b7f59 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -8,7 +8,6 @@
 import os = require('os');
 import path = require('path');
 import semver = require('semver');
-import kill = require('tree-kill');
 import util = require('util');
 import vscode = require('vscode');
 import { NearestNeighborDict, Node } from './avlTree';
@@ -16,6 +15,8 @@
 import { toolExecutionEnvironment } from './goEnv';
 import { buildDiagnosticCollection, lintDiagnosticCollection, vetDiagnosticCollection } from './goMain';
 import { getCurrentPackage } from './goModules';
+import { outputChannel } from './goStatus';
+import { getFromWorkspaceState } from './stateUtils';
 import {
 	envPath,
 	fixDriveCasingInWindows,
@@ -23,8 +24,8 @@
 	getCurrentGoRoot,
 	getInferredGopath,
 	resolveHomeDir,
-} from './goPath';
-import { outputChannel } from './goStatus';
+} from './utils/goPath';
+import { killProcessTree } from './utils/processUtils';
 
 let userNameHash: number = 0;
 
@@ -81,20 +82,28 @@
 
 export class GoVersion {
 	public sv?: semver.SemVer;
+	// Go version tags are not following the strict semver format
+	// so semver drops the prerelease tags used in Go version.
+	// If sv is valid, let's keep the original version string
+	// including the prerelease tag parts.
+	public svString?: string;
+
 	public isDevel?: boolean;
 	private commit?: string;
 
-	constructor(public binaryPath: string, version: string) {
-		const matchesRelease = /go version go(\d.\d+).*/.exec(version);
+	constructor(public binaryPath: string, public version: string) {
+		const matchesRelease = /^go version go(\d\.\d+\S*)\s+/.exec(version);
 		const matchesDevel = /go version devel \+(.[a-zA-Z0-9]+).*/.exec(version);
 		if (matchesRelease) {
-			const sv = semver.coerce(matchesRelease[0]);
+			// note: semver.parse does not work with Go version string like go1.14.
+			const sv = semver.coerce(matchesRelease[1]);
 			if (sv) {
 				this.sv = sv;
+				this.svString = matchesRelease[1];
 			}
 		} else if (matchesDevel) {
 			this.isDevel = true;
-			this.commit = matchesDevel[0];
+			this.commit = matchesDevel[1];
 		}
 	}
 
@@ -102,11 +111,17 @@
 		return !!this.sv || !!this.isDevel;
 	}
 
-	public format(): string {
+	public format(includePrerelease?: boolean): string {
 		if (this.sv) {
+			if (includePrerelease && this.svString) {
+				return this.svString;
+			}
 			return this.sv.format();
 		}
-		return `devel +${this.commit}`;
+		if (this.isDevel) {
+			return `devel +${this.commit}`;
+		}
+		return `unknown`;
 	}
 
 	public lt(version: string): boolean {
@@ -299,9 +314,14 @@
 
 /**
  * Gets version of Go based on the output of the command `go version`.
- * Returns null if go is being used from source/tip in which case `go version` will not return release tag like go1.6.3
+ * Returns undefined if go version can't be determined because
+ * go is not available or `go version` fails.
  */
 export async function getGoVersion(): Promise<GoVersion | undefined> {
+	// TODO(hyangah): limit the number of concurrent getGoVersion call.
+	// When the extension starts, at least 4 concurrent calls race
+	// and end up calling `go version`.
+
 	const goRuntimePath = getBinPath('go');
 
 	const warn = (msg: string) => {
@@ -317,7 +337,7 @@
 		if (cachedGoVersion.isValid()) {
 			return Promise.resolve(cachedGoVersion);
 		}
-		warn(`cached Go version (${cachedGoVersion}) is invalid, recomputing`);
+		warn(`cached Go version (${JSON.stringify(cachedGoVersion)}) is invalid, recomputing`);
 	}
 	try {
 		const execFile = util.promisify(cp.execFile);
@@ -336,6 +356,21 @@
 }
 
 /**
+ * Returns the output of `go env` from the specified directory.
+ * Throws an error if the command fails.
+ */
+export async function getGoEnv(cwd?: string): Promise<string> {
+	const goRuntime = getBinPath('go');
+	const execFile = util.promisify(cp.execFile);
+	const opts = {cwd, env: toolExecutionEnvironment()};
+	const { stdout, stderr } = await execFile(goRuntime, ['env'], opts);
+	if (stderr) {
+		throw new Error(`failed to run 'go env': ${stderr}`);
+	}
+	return stdout;
+}
+
+/**
  * Returns boolean denoting if current version of Go supports vendoring
  */
 export async function isVendorSupported(): Promise<boolean> {
@@ -370,6 +405,7 @@
  */
 export function isGoPathSet(): boolean {
 	if (!getCurrentGoPath()) {
+		// TODO(hyangah): is it still possible after go1.8? (https://golang.org/doc/go1.8#gopath)
 		vscode.window
 			.showInformationMessage(
 				'Set GOPATH environment variable and restart VS Code or set GOPATH in Workspace settings',
@@ -440,11 +476,16 @@
 	const alternateTools: { [key: string]: string } = cfg.get('alternateTools');
 	const alternateToolPath: string = alternateTools[tool];
 
+	let selectedGoPath: string | undefined;
+	if (tool === 'go') {
+		selectedGoPath = getFromWorkspaceState('selectedGo')?.binpath;
+	}
+
 	return getBinPathWithPreferredGopathGoroot(
 		tool,
 		tool === 'go' ? [] : [getToolsGopath(), getCurrentGoPath()],
-		tool === 'go' && cfg.get('goroot') ? cfg.get('goroot') : undefined,
-		resolvePath(alternateToolPath),
+		tool === 'go' && cfg.get('goroot') ? resolvePath(cfg.get('goroot')) : undefined,
+		selectedGoPath ?? resolvePath(alternateToolPath),
 		useCache
 	);
 }
@@ -492,6 +533,9 @@
 }
 
 export function getModuleCache(): string {
+	if (process.env['GOMODCACHE']) {
+		return process.env['GOMODCACHE'];
+	}
 	if (currentGopath) {
 		return path.join(currentGopath.split(path.delimiter)[0], 'pkg', 'mod');
 	}
@@ -684,7 +728,7 @@
 	if (token) {
 		token.onCancellationRequested(() => {
 			if (p) {
-				killTree(p.pid);
+				killProcessTree(p);
 			}
 		});
 	}
@@ -861,28 +905,6 @@
 	}
 }
 
-export const killTree = (processId: number): void => {
-	try {
-		kill(processId, (err) => {
-			if (err) {
-				console.log(`Error killing process tree: ${err}`);
-			}
-		});
-	} catch (err) {
-		console.log(`Error killing process tree: ${err}`);
-	}
-};
-
-export function killProcess(p: cp.ChildProcess) {
-	if (p) {
-		try {
-			p.kill();
-		} catch (e) {
-			console.log('Error killing process: ' + e);
-		}
-	}
-}
-
 export function makeMemoizedByteOffsetConverter(buffer: Buffer): (byteOffset: number) => number {
 	const defaultValue = new Node<number, number>(0, 0); // 0 bytes will always be 0 characters
 	const memo = new NearestNeighborDict(defaultValue, NearestNeighborDict.NUMERIC_DISTANCE_FUNCTION);
@@ -1026,7 +1048,7 @@
 
 			if (token) {
 				token.onCancellationRequested(() => {
-					killTree(p.pid);
+					killProcessTree(p);
 				});
 			}
 		});
diff --git a/src/goPath.ts b/src/utils/goPath.ts
similarity index 96%
rename from src/goPath.ts
rename to src/utils/goPath.ts
index f85e49e..6ad1b1a 100644
--- a/src/goPath.ts
+++ b/src/utils/goPath.ts
@@ -12,6 +12,7 @@
 import fs = require('fs');
 import os = require('os');
 import path = require('path');
+import { promisify } from 'util';
 
 let binPathCache: { [bin: string]: string } = {};
 
@@ -37,7 +38,7 @@
 	preferredGoroot?: string,
 	alternateTool?: string,
 	useCache = true,
-) {
+): string {
 	if (alternateTool && path.isAbsolute(alternateTool) && executableFileExists(alternateTool)) {
 		binPathCache[toolName] = alternateTool;
 		return alternateTool;
@@ -106,7 +107,7 @@
 	currentGoRoot = goroot;
 }
 
-function correctBinname(toolName: string) {
+export function correctBinname(toolName: string) {
 	if (process.platform === 'win32') {
 		return toolName + '.exe';
 	}
@@ -134,6 +135,15 @@
 	}
 }
 
+export async function pathExists(p: string): Promise<boolean> {
+	try {
+		const stat = promisify(fs.stat);
+		return (await stat(p)).isDirectory();
+	} catch (e) {
+		return false;
+	}
+}
+
 export function clearCacheForTools() {
 	binPathCache = {};
 }
diff --git a/src/utils/processUtils.ts b/src/utils/processUtils.ts
new file mode 100644
index 0000000..ddd12ae
--- /dev/null
+++ b/src/utils/processUtils.ts
@@ -0,0 +1,46 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+import { ChildProcess } from 'child_process';
+import kill = require('tree-kill');
+
+// Kill a process and its children, returning a promise.
+export function killProcessTree(
+	p: ChildProcess,
+	logger?: (...args: any[]) => void): Promise<void> {
+	if (!logger) {
+		logger = console.log;
+	}
+	if (!p || !p.pid || p.exitCode !== null) {
+		return Promise.resolve();
+	}
+	return new Promise((resolve) => {
+		kill(p.pid, (err) => {
+			if (err) {
+				logger(`Error killing process ${p.pid}: ${err}`);
+			}
+			resolve();
+		});
+	});
+}
+
+// Kill a process.
+//
+// READ THIS BEFORE USING THE FUNCTION:
+//
+// TODO: This function is kept for historical reasons and should be removed once
+// its user (go-outline) is replaced. Outlining uses this function and not
+// killProcessTree because of performance issues that were observed in the past.
+// See https://go-review.googlesource.com/c/vscode-go/+/242518/ for more
+// details and background.
+export function killProcess(p: ChildProcess) {
+	if (p && p.pid && p.exitCode === null) {
+		try {
+			p.kill();
+		} catch (e) {
+			console.log(`Error killing process ${p.pid}: ${e}`);
+		}
+	}
+}
diff --git a/test/fixtures/coverage/a/a.go b/test/fixtures/coverage/a/a.go
new file mode 100644
index 0000000..06eae93
--- /dev/null
+++ b/test/fixtures/coverage/a/a.go
@@ -0,0 +1,7 @@
+package a
+
+func main() {
+	x := 12
+	y := x + 17
+	panic(y)
+}
diff --git a/test/fixtures/coverage/b/b.go b/test/fixtures/coverage/b/b.go
new file mode 100644
index 0000000..7de3bb6
--- /dev/null
+++ b/test/fixtures/coverage/b/b.go
@@ -0,0 +1,11 @@
+package b
+
+import (
+	"fmt"
+	"os"
+)
+
+func main() {
+	v := os.Env()
+	fmt.Print(v)
+}
diff --git a/test/fixtures/coverage/cover.out b/test/fixtures/coverage/cover.out
new file mode 100644
index 0000000..3157dc6
--- /dev/null
+++ b/test/fixtures/coverage/cover.out
@@ -0,0 +1,3 @@
+mode: set
+github.com/microsoft/vscode-go/gofixtures/coveragetest/a/a.go:19.71,22.25 3 1
+github.com/microsoft/vscode-go/gofixtures/coveragetest/b/b.go:35.2,35.14 1 1
diff --git a/test/fixtures/coverage/go.mod b/test/fixtures/coverage/go.mod
new file mode 100644
index 0000000..5f77dbf
--- /dev/null
+++ b/test/fixtures/coverage/go.mod
@@ -0,0 +1,3 @@
+module github.com/microsoft/vscode-go/gofixtures/coveragetest
+
+go 1.14
diff --git a/test/fixtures/goTestTest/a_test.go b/test/fixtures/goTestTest/a_test.go
new file mode 100644
index 0000000..66a943a
--- /dev/null
+++ b/test/fixtures/goTestTest/a_test.go
@@ -0,0 +1,10 @@
+package main
+
+import (
+	"testing"
+)
+
+func TestA(t *testing.T) {
+	t.Log("log")
+	t.Errorf("error")
+}
diff --git a/test/fixtures/goTestTest/b/b_test.go b/test/fixtures/goTestTest/b/b_test.go
new file mode 100644
index 0000000..2240f6f
--- /dev/null
+++ b/test/fixtures/goTestTest/b/b_test.go
@@ -0,0 +1,8 @@
+package main
+
+import "testing"
+
+func TestB(t *testing.T) {
+	t.Log("log")
+	t.Error("error")
+}
diff --git a/test/fixtures/goTestTest/go.mod b/test/fixtures/goTestTest/go.mod
new file mode 100644
index 0000000..24872e7
--- /dev/null
+++ b/test/fixtures/goTestTest/go.mod
@@ -0,0 +1,3 @@
+module example.com/a
+
+go 1.14
diff --git a/test/fixtures/vendoring/main.go b/test/fixtures/vendoring/main.go
new file mode 100644
index 0000000..85b606a
--- /dev/null
+++ b/test/fixtures/vendoring/main.go
@@ -0,0 +1,11 @@
+package main
+
+import (
+  "fmt"
+
+  "example.com/vendorpls"
+)
+
+func main() {
+  fmt.Prinln(vendorpls.F())
+}
diff --git a/test/fixtures/vendoring/vendor/example.com/vendorpls/lib.go b/test/fixtures/vendoring/vendor/example.com/vendorpls/lib.go
new file mode 100644
index 0000000..2993afc
--- /dev/null
+++ b/test/fixtures/vendoring/vendor/example.com/vendorpls/lib.go
@@ -0,0 +1,9 @@
+package vendorpls
+
+func F() string {
+  return "vendor please"
+}
+
+func SomethingStrange() {
+
+}
\ No newline at end of file
diff --git a/test/gopls/extension.test.ts b/test/gopls/extension.test.ts
index 64cddfc..7f5104c 100644
--- a/test/gopls/extension.test.ts
+++ b/test/gopls/extension.test.ts
@@ -46,7 +46,10 @@
 	public async setup() {
 		await this.reset();
 		await this.extension.activate();
-		await sleep(2000);  // allow extension host + gopls to start.
+		await sleep(2000);  // allow the language server to start.
+		// TODO(hyangah): find a better way to check the language server's status.
+		// I thought I'd check the languageClient.onReady(),
+		// but couldn't make it working yet.
 	}
 
 	public async reset(fixtureDirName?: string) {  // name of the fixtures subdirectory to use.
@@ -89,7 +92,9 @@
 	const projectDir = path.join(__dirname, '..', '..', '..');
 	const env = new Env(projectDir);
 
-	suiteSetup(async () => { await env.setup(); });
+	suiteSetup(async () => {
+		await env.setup();
+	});
 	suiteTeardown(async () => { await env.reset(); });
 
 	test('HoverProvider', async () => {
@@ -137,9 +142,23 @@
 			['fmt.<>', new vscode.Position(19, 5), 'Formatter'],
 		];
 		for (const [name, position, wantFilterText] of testCases) {
-			const list = await vscode.commands.executeCommand(
-				'vscode.executeCompletionItemProvider', uri, position) as vscode.CompletionList;
-
+			let list: vscode.CompletionList<vscode.CompletionItem>;
+			// Query completion items. We expect the hard coded filter text hack
+			// has been applied and gopls returns an incomplete list by default
+			// to avoid reordering by vscode. But, if the query is made before
+			// gopls is ready, we observed that gopls returns an empty result
+			// as a complete result, and vscode returns a general completion list instead.
+			// Retry a couple of times if we see a complete result as a workaround.
+			// (github.com/golang/vscode-go/issues/363)
+			for (let i = 0; i < 3; i++) {
+				list = await vscode.commands.executeCommand(
+					'vscode.executeCompletionItemProvider', uri, position) as vscode.CompletionList;
+				if (list.isIncomplete) {
+					break;
+				}
+				await sleep(100);
+				console.log(`${new Date()}: retrying...`);
+			}
 			// Confirm that the hardcoded filter text hack has been applied.
 			if (!list.isIncomplete) {
 				assert.fail(`gopls should provide an incomplete list by default`);
@@ -157,6 +176,5 @@
 				}
 			}
 		}
-
 	});
 });
diff --git a/test/gopls/index.ts b/test/gopls/index.ts
index be16d86..eae81d7 100644
--- a/test/gopls/index.ts
+++ b/test/gopls/index.ts
@@ -10,7 +10,9 @@
 	const mocha = new Mocha({
 		ui: 'tdd'
 	});
-	mocha.useColors(true);
+
+	// @types/mocha is outdated
+	(mocha as any).color(true);
 
 	const testsRoot = path.resolve(__dirname, '..');
 
diff --git a/test/gopls/survey.test.ts b/test/gopls/survey.test.ts
index bccd3d6..2f04128 100644
--- a/test/gopls/survey.test.ts
+++ b/test/gopls/survey.test.ts
@@ -20,26 +20,26 @@
 			[
 				{
 					lastDateAccepted: new Date('2020-04-02'),
-					promptThisMonthTimestamp: new Date('2020-04-10'),
+					dateComputedPromptThisMonth: new Date('2020-04-10'),
 					lastDatePrompted: new Date('2020-04-02'),
 					prompt: true,
 					promptThisMonth: false,
 				},
-				false,
+				undefined,
 			],
 			// User who has declined survey prompting.
 			[
 				{
-					promptThisMonthTimestamp: new Date('2020-04-10'),
+					dateComputedPromptThisMonth: new Date('2020-04-10'),
 					lastDatePrompted: new Date('2020-04-02'),
 					prompt: false,
 				},
-				false,
+				undefined,
 			],
 			// User who hasn't activated the extension in a while, but has opted in to prompting.
 			[
 				{
-					promptThisMonthTimestamp: new Date('2019-04-10'),
+					dateComputedPromptThisMonth: new Date('2019-04-10'),
 					lastDatePrompted: new Date('2019-01-02'),
 					prompt: true,
 				},
@@ -48,7 +48,7 @@
 			// User who hasn't activated the extension in a while, and has never been prompted.
 			[
 				{
-					promptThisMonthTimestamp: new Date('2019-04-10'),
+					dateComputedPromptThisMonth: new Date('2019-04-10'),
 					lastDatePrompted: new Date('2019-01-02'),
 				},
 				true,
@@ -57,7 +57,7 @@
 			[
 				{
 					lastDateAccepted: undefined,
-					promptThisMonthTimestamp: new Date('2020-04-10'),
+					dateComputedPromptThisMonth: new Date('2020-04-10'),
 					lastDatePrompted: new Date('2019-01-02'),
 					prompt: true,
 					promptThisMonth: true,
@@ -69,12 +69,15 @@
 			// Replace Math.Random so that it always returns 1. This means
 			// that we will always choose to prompt, in the event that the
 			// user can be prompted that month.
-			sinon.replace(Math, 'random', () => 1);
+			sinon.replace(Math, 'random', () => 0);
 
 			const now = new Date('2020-04-29');
 			const gotPrompt = shouldPromptForGoplsSurvey(now, testConfig);
-			assert.equal(wantPrompt, gotPrompt, `prompt determination failed for ${i}`);
-
+			if (wantPrompt) {
+				assert.ok(gotPrompt, `prompt determination failed for ${i}`);
+			} else {
+				assert.equal(gotPrompt, wantPrompt, `prompt determination failed for ${i}`);
+			}
 			sinon.restore();
 		});
 	});
diff --git a/test/gopls/update.test.ts b/test/gopls/update.test.ts
index dbe5312..031bea5 100644
--- a/test/gopls/update.test.ts
+++ b/test/gopls/update.test.ts
@@ -14,7 +14,7 @@
 	test('prompt for update', async () => {
 		const tool = getTool('gopls');
 
-		const toSemver = (v: string) => semver.coerce(v, {includePrerelease: true, loose: true});
+		const toSemver = (v: string) => semver.parse(v, { includePrerelease: true, loose: true });
 
 		// Fake data stubbed functions will serve.
 		const latestVersion = toSemver('0.4.1');
@@ -101,7 +101,19 @@
 					return latestPrereleaseVersionTimestamp;
 				}
 			});
-			const got = await lsp.shouldUpdateLanguageServer(tool, 'bad/path/to/gopls', true);
+			const got = await lsp.shouldUpdateLanguageServer(tool, {
+				enabled: true,
+				path: 'bad/path/to/gopls',
+				checkForUpdates: true,
+				env: {},
+				features: {
+					diagnostics: true,
+					documentLink: true,
+				},
+				flags: [],
+				modtime: new Date(),
+				serverName: 'gopls',
+			});
 			assert.deepEqual(got, want, `${name}: failed (got: '${got}' ${typeof got} want: '${want}' ${typeof want})`);
 			sinon.restore();
 		}
diff --git a/test/integration/coverage.test.ts b/test/integration/coverage.test.ts
new file mode 100644
index 0000000..fe38424
--- /dev/null
+++ b/test/integration/coverage.test.ts
@@ -0,0 +1,44 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+'use strict';
+
+import * as assert from 'assert';
+import fs = require('fs-extra');
+import path = require('path');
+import sinon = require('sinon');
+import vscode = require('vscode');
+import { applyCodeCoverageToAllEditors, coverageFilesForTest, initForTest } from '../../src/goCover';
+import { updateGoVarsFromConfig } from '../../src/goInstallTools';
+import { getCurrentGoPath, getWorkspaceFolderPath } from '../../src/util';
+
+// The ideal test would check that each open editor containing a file with coverage
+// information is displayed correctly. We cannot see the applied decorations, so the
+// test checks that the cover.out file has been read correctly, and the import paths
+// have been correctly converted to file system paths, which are what vscode uses.
+suite('Coverage for tests', function () {
+	this.timeout(10000);
+
+	let fixtureSourcePath: string;
+	let coverFilePath: string;
+
+	suiteSetup(async () => {
+		await updateGoVarsFromConfig();
+
+		// Set up the test fixtures.
+		fixtureSourcePath = path.join(__dirname, '..', '..', '..', 'test', 'fixtures', 'coverage');
+		coverFilePath = path.join(fixtureSourcePath, 'cover.out');
+		return;
+	});
+	test('resolve import paths', async () => {
+		initForTest();
+		const x = vscode.workspace.openTextDocument(coverFilePath);
+		await applyCodeCoverageToAllEditors(coverFilePath, fixtureSourcePath);
+		const files = Object.keys(coverageFilesForTest());
+		const aDotGo = files.includes(path.join(fixtureSourcePath, 'a', 'a.go'));
+		const bDotGo = files.includes(path.join(fixtureSourcePath, 'b', 'b.go'));
+		assert.equal(aDotGo && bDotGo, true, `seen a.go:${aDotGo}, seen b.go:${bDotGo}\n${files}\n`);
+	});
+});
diff --git a/test/integration/extension.test.ts b/test/integration/extension.test.ts
index b8c752d..d16d35b 100644
--- a/test/integration/extension.test.ts
+++ b/test/integration/extension.test.ts
@@ -364,8 +364,9 @@
 
 	test('Linting - concurrent process cancelation', async () => {
 		const util = require('../../src/util');
+		const processutil = require('../../src/utils/processUtils');
 		sinon.spy(util, 'runTool');
-		sinon.spy(util, 'killTree');
+		sinon.spy(processutil, 'killProcessTree');
 
 		const config = Object.create(vscode.workspace.getConfiguration('go'), {
 			vetOnSave: { value: 'package' },
@@ -373,8 +374,8 @@
 			buildOnSave: { value: 'package' },
 			lintOnSave: { value: 'package' },
 			// simulate a long running lint process by sleeping for a couple seconds
-			lintTool: { value: 'sleep' },
-			lintFlags: { value: ['2'] }
+			lintTool: { value: process.platform !== 'win32' ? 'sleep' : 'timeout' },
+			lintFlags: { value: process.platform !== 'win32' ? ['2'] : ['/t', '2'] }
 		});
 
 		const results = await Promise.all([
@@ -382,7 +383,7 @@
 			goLint(vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_2.go')), config)
 		]);
 		assert.equal(util.runTool.callCount, 2, 'should have launched 2 lint jobs');
-		assert.equal(util.killTree.callCount, 1, 'should have killed 1 lint job before launching the next');
+		assert.equal(processutil.killProcessTree.callCount, 1, 'should have killed 1 lint job before launching the next');
 	});
 
 	test('Error checking', async () => {
@@ -472,7 +473,12 @@
 		assert.equal(testFileGenerated, true, 'Test file not generated.');
 	});
 
-	test('Test diffUtils.getEditsFromUnifiedDiffStr', async () => {
+	test('Test diffUtils.getEditsFromUnifiedDiffStr', async function () {
+		if (process.platform === 'win32') {
+			// This test requires diff tool that's not available on windows
+			this.skip();
+		}
+
 		const file1path = path.join(fixturePath, 'diffTest1Data', 'file1.go');
 		const file2path = path.join(fixturePath, 'diffTest1Data', 'file2.go');
 		const file1uri = vscode.Uri.file(file1path);
@@ -628,21 +634,13 @@
 	});
 
 	test('Replace vendor packages with relative path', async () => {
-		// This test needs a go project that has vendor folder and vendor packages
-		// Since the Go extension takes a dependency on the godef tool at github.com/rogpeppe/godef
-		// which has vendor packages, we are using it here to test the "replace vendor packages with relative path" feature.
-		// If the extension ever stops depending on godef tool or if godef ever stops having vendor packages, then this test
-		// will fail and will have to be replaced with any other go project with vendor packages
-
 		const vendorSupport = await isVendorSupported();
-		const filePath = path.join(toolsGopath, 'src', 'github.com', 'rogpeppe', 'godef', 'go', 'ast', 'ast.go');
+		const filePath = path.join(fixturePath, 'vendoring', 'main.go');
 		const workDir = path.dirname(filePath);
 		const vendorPkgsFullPath = [
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/acme',
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/plan9',
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/plan9/client'
+			'test/testfixture/vendoring/vendor/example.com/vendorpls',
 		];
-		const vendorPkgsRelativePath = ['9fans.net/go/acme', '9fans.net/go/plan9', '9fans.net/go/plan9/client'];
+		const vendorPkgsRelativePath = ['example.com/vendorpls'];
 
 		const gopkgsPromise = getAllPackages(workDir).then((pkgMap) => {
 			const pkgs = Array.from(pkgMap.keys()).filter((p) => {
@@ -696,18 +694,10 @@
 	});
 
 	test('Vendor pkgs from other projects should not be allowed to import', async () => {
-		// This test needs a go project that has vendor folder and vendor packages
-		// Since the Go extension takes a dependency on the godef tool at github.com/rogpeppe/godef
-		// which has vendor packages, we are using it here to test the "replace vendor packages with relative path" feature.
-		// If the extension ever stops depending on godef tool or if godef ever stops having vendor packages, then this test
-		// will fail and will have to be replaced with any other go project with vendor packages
-
 		const vendorSupport = await isVendorSupported();
-		const filePath = path.join(toolsGopath, 'src', 'github.com', 'ramya-rao-a', 'go-outline', 'main.go');
+		const filePath = path.join(fixturePath, 'baseTest', 'test.go');
 		const vendorPkgs = [
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/acme',
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/plan9',
-			'github.com/rogpeppe/godef/vendor/9fans.net/go/plan9/client'
+			'test/testfixture/vendoring/vendor/example.com/vendorpls',
 		];
 
 		const gopkgsPromise = new Promise<void>((resolve, reject) => {
@@ -751,13 +741,7 @@
 	});
 
 	test('Workspace Symbols', () => {
-		// This test needs a go project that has vendor folder and vendor packages
-		// Since the Go extension takes a dependency on the godef tool at github.com/rogpeppe/godef
-		// which has vendor packages, we are using it here to test the "replace vendor packages with relative path" feature.
-		// If the extension ever stops depending on godef tool or if godef ever stops having vendor packages, then this test
-		// will fail and will have to be replaced with any other go project with vendor packages
-
-		const workspacePath = path.join(toolsGopath, 'src', 'github.com', 'rogpeppe', 'godef');
+		const workspacePath = path.join(fixturePath, 'vendoring');
 		const configWithoutIgnoringFolders = Object.create(vscode.workspace.getConfiguration('go'), {
 			gotoSymbol: {
 				value: {
@@ -789,16 +773,16 @@
 
 		const withoutIgnoringFolders = getWorkspaceSymbols(
 			workspacePath,
-			'WinInfo',
+			'SomethingStr',
 			dummyCancellationSource.token,
 			configWithoutIgnoringFolders
 		).then((results) => {
-			assert.equal(results[0].name, 'WinInfo');
-			assert.equal(results[0].path, path.join(workspacePath, 'vendor/9fans.net/go/acme/acme.go'));
+			assert.equal(results[0].name, 'SomethingStrange');
+			assert.equal(results[0].path, path.join(workspacePath, 'vendor/example.com/vendorpls/lib.go'));
 		});
 		const withIgnoringFolders = getWorkspaceSymbols(
 			workspacePath,
-			'WinInfo',
+			'SomethingStr',
 			dummyCancellationSource.token,
 			configWithIgnoringFolders
 		).then((results) => {
@@ -1444,12 +1428,19 @@
 		assert.equal(result4, false);
 	});
 
+	function fixEOL(eol: vscode.EndOfLine, strWithLF: string): string {
+		if (eol === vscode.EndOfLine.LF) {
+			return strWithLF;
+		}
+		return strWithLF.split('\n').join('\r\n');  // replaceAll.
+	}
+
 	test('Add imports when no imports', async () => {
 		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'noimports.go'));
 		const document = await vscode.workspace.openTextDocument(uri);
 		await vscode.window.showTextDocument(document);
 
-		const expectedText = document.getText() + '\n' + 'import (\n\t"bytes"\n)\n';
+		const expectedText = document.getText() + fixEOL(document.eol, '\n' + 'import (\n\t"bytes"\n)\n');
 		const edits = getTextEditForAddImport('bytes');
 		const edit = new vscode.WorkspaceEdit();
 		edit.set(document.uri, edits);
@@ -1466,8 +1457,11 @@
 		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'groupImports.go'));
 		const document = await vscode.workspace.openTextDocument(uri);
 		await vscode.window.showTextDocument(document);
+		const eol = document.eol;
 
-		const expectedText = document.getText().replace('\t"fmt"\n\t"math"', '\t"bytes"\n\t"fmt"\n\t"math"');
+		const expectedText = document.getText().replace(
+			fixEOL(eol, '\t"fmt"\n\t"math"'),
+			fixEOL(eol, '\t"bytes"\n\t"fmt"\n\t"math"'));
 		const edits = getTextEditForAddImport('bytes');
 		const edit = new vscode.WorkspaceEdit();
 		edit.set(document.uri, edits);
@@ -1479,12 +1473,13 @@
 		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'singleImports.go'));
 		const document = await vscode.workspace.openTextDocument(uri);
 		await vscode.window.showTextDocument(document);
+		const eol = document.eol;
 
 		const expectedText = document
 			.getText()
 			.replace(
-				'import "fmt"\nimport . "math" // comment',
-				'import (\n\t"bytes"\n\t"fmt"\n\t. "math" // comment\n)'
+				fixEOL(eol, 'import "fmt"\nimport . "math" // comment'),
+				fixEOL(eol, 'import (\n\t"bytes"\n\t"fmt"\n\t. "math" // comment\n)')
 			);
 		const edits = getTextEditForAddImport('bytes');
 		const edit = new vscode.WorkspaceEdit();
@@ -1497,12 +1492,13 @@
 		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'cgoImports.go'));
 		const document = await vscode.workspace.openTextDocument(uri);
 		await vscode.window.showTextDocument(document);
+		const eol = document.eol;
 
 		const expectedText = document
 			.getText()
 			.replace(
-				'import "math"',
-				'import (\n\t"bytes"\n\t"math"\n)'
+				fixEOL(eol, 'import "math"'),
+				fixEOL(eol, 'import (\n\t"bytes"\n\t"math"\n)')
 			);
 		const edits = getTextEditForAddImport('bytes');
 		const edit = new vscode.WorkspaceEdit();
diff --git a/test/integration/index.ts b/test/integration/index.ts
index 2d964a1..0cc6ddd 100644
--- a/test/integration/index.ts
+++ b/test/integration/index.ts
@@ -9,7 +9,9 @@
 	const mocha = new Mocha({
 		ui: 'tdd',
 	});
-	mocha.useColors(true);
+
+	// @types/mocha is outdated
+	(mocha as any).color(true);
 
 	const testsRoot = path.resolve(__dirname, '..');
 
diff --git a/test/integration/install.test.ts b/test/integration/install.test.ts
index 2c663f5..e61f606 100644
--- a/test/integration/install.test.ts
+++ b/test/integration/install.test.ts
@@ -10,12 +10,14 @@
 import os = require('os');
 import path = require('path');
 import sinon = require('sinon');
+import url = require('url');
 import util = require('util');
 import vscode = require('vscode');
 import { toolInstallationEnvironment } from '../../src/goEnv';
 import { installTools } from '../../src/goInstallTools';
 import { allToolsInformation, getTool, getToolAtVersion } from '../../src/goTools';
 import { getBinPath, getGoVersion, rmdirRecursive } from '../../src/util';
+import { correctBinname } from '../../src/utils/goPath';
 
 suite('Installation Tests', function () {
 	// Disable timeout when we are running slow tests.
@@ -26,18 +28,22 @@
 	this.timeout(timeout);
 
 	let tmpToolsGopath: string;
+	let tmpToolsGopath2: string;
 	let sandbox: sinon.SinonSandbox;
 	let toolsGopathStub: sinon.SinonStub;
 
 	setup(() => {
 		// Create a temporary directory in which to install tools.
 		tmpToolsGopath = fs.mkdtempSync(path.join(os.tmpdir(), 'install-test'));
-		fs.mkdirSync(path.join(tmpToolsGopath, 'bin'));
-		fs.mkdirSync(path.join(tmpToolsGopath, 'src'));
+
+		// a temporary directory to be used as the second GOPATH element.
+		tmpToolsGopath2 = fs.mkdtempSync(path.join(os.tmpdir(), 'install-test2'));
+
+		const toolsGopath = tmpToolsGopath + path.delimiter + tmpToolsGopath2;
 
 		sandbox = sinon.createSandbox();
 		const utils = require('../../src/util');
-		toolsGopathStub = sandbox.stub(utils, 'getToolsGopath').returns(tmpToolsGopath);
+		toolsGopathStub = sandbox.stub(utils, 'getToolsGopath').returns(toolsGopath);
 	});
 
 	teardown(async () => {
@@ -46,12 +52,15 @@
 		// Clean up the temporary GOPATH. To delete the module cache, run `go clean -modcache`.
 		const goRuntimePath = getBinPath('go');
 		const envForTest = Object.assign({}, process.env);
-		envForTest['GOPATH'] = tmpToolsGopath;
-		const execFile = util.promisify(cp.execFile);
-		await execFile(goRuntimePath, ['clean', '-modcache'], {
-			env: envForTest,
-		});
-		rmdirRecursive(tmpToolsGopath);
+
+		for (const p of [tmpToolsGopath, tmpToolsGopath2]) {
+			envForTest['GOPATH'] = p;
+			const execFile = util.promisify(cp.execFile);
+			await execFile(goRuntimePath, ['clean', '-modcache'], {
+				env: envForTest,
+			});
+			rmdirRecursive(p);
+		}
 	});
 
 	// runTest actually executes the logic of the test.
@@ -64,7 +73,7 @@
 			const goConfig = Object.create(vscode.workspace.getConfiguration('go'), {
 				toolsEnvVars: {
 					value: {
-						GOPROXY: `file://${proxyDir}`,
+						GOPROXY: url.pathToFileURL(proxyDir),
 						GOSUMDB: 'off',
 					}
 				},
@@ -86,7 +95,7 @@
 		for (const tool of testCases) {
 			checks.push(new Promise<void>(async (resolve) => {
 				// Check that the expect tool has been installed to $GOPATH/bin.
-				const ok = await exists(path.join(tmpToolsGopath, 'bin', tool));
+				const ok = await exists(path.join(tmpToolsGopath, 'bin', correctBinname(tool)));
 				if (!ok) {
 					assert.fail(`expected ${tmpToolsGopath}/bin/${tool}, not found`);
 				}
@@ -145,7 +154,7 @@
 		// Write the zip file.
 		const zip = new AdmZip();
 		const content = `package main; func main() {};`;
-		zip.addFile(path.join(`${module}@${version}`, 'main.go'), Buffer.alloc(content.length, content));
+		zip.addFile(`${module}@${version}/main.go`, Buffer.alloc(content.length, content));
 		zip.writeZip(path.join(dir, `${version}.zip`));
 	}
 	return proxyDir;
diff --git a/test/integration/statusbar.test.ts b/test/integration/statusbar.test.ts
index 42d166e..8396db6 100644
--- a/test/integration/statusbar.test.ts
+++ b/test/integration/statusbar.test.ts
@@ -5,18 +5,28 @@
  *--------------------------------------------------------*/
 
 import * as assert from 'assert';
-import cp = require('child_process');
-import fs = require('fs');
+import * as cp from 'child_process';
+import * as fs from 'fs-extra';
 import { describe, it } from 'mocha';
-import os = require('os');
-import path = require('path');
-import sinon = require('sinon');
-import util = require('util');
-import { WorkspaceConfiguration } from 'vscode';
-import { disposeGoStatusBar, formatGoVersion, getGoEnvironmentStatusbarItem } from '../../src/goEnvironmentStatus';
+import * as os from 'os';
+import * as path from 'path';
+import * as sinon from 'sinon';
+import * as util from 'util';
+import * as vscode from 'vscode';
+
+import {
+	disposeGoStatusBar,
+	formatGoVersion,
+	getGoEnvironmentStatusbarItem,
+	getSelectedGo,
+	GoEnvironmentOption,
+	setSelectedGo,
+} from '../../src/goEnvironmentStatus';
 import { updateGoVarsFromConfig } from '../../src/goInstallTools';
-import { getCurrentGoRoot } from '../../src/goPath';
+import { getWorkspaceState, setWorkspaceState } from '../../src/stateUtils';
 import ourutil = require('../../src/util');
+import { getCurrentGoRoot } from '../../src/utils/goPath';
+import { MockMemento } from '../mocks/MockMemento';
 
 describe('#initGoStatusBar()', function () {
 	this.beforeAll(async () => {
@@ -33,7 +43,7 @@
 
 	it('should create a status bar item with a label matching go.goroot version', async () => {
 		const version = await ourutil.getGoVersion();
-		const versionLabel = formatGoVersion(version.format());
+		const versionLabel = formatGoVersion(version);
 		assert.equal(
 			getGoEnvironmentStatusbarItem().text,
 			versionLabel,
@@ -42,16 +52,76 @@
 	});
 });
 
-describe('#updateGoVarsFromConfig()', function () {
+describe('#setSelectedGo()', async function () {
+	this.timeout(40000);
+	let sandbox: sinon.SinonSandbox | undefined;
+	let goOption: GoEnvironmentOption;
+	let defaultMemento: vscode.Memento;
+	const version = await ourutil.getGoVersion();
+	const defaultGoOption = new GoEnvironmentOption(version.binaryPath, formatGoVersion(version));
+
+	this.beforeAll(async () => {
+		defaultMemento = getWorkspaceState();
+		setWorkspaceState(new MockMemento());
+		await setSelectedGo(defaultGoOption);
+	});
+	this.afterAll(async () => {
+		setWorkspaceState(defaultMemento);
+	});
+	this.beforeEach(async () => {
+		goOption = await getSelectedGo();
+		sandbox = sinon.createSandbox();
+	});
+	this.afterEach(async () => {
+		await setSelectedGo(goOption, false);
+		sandbox.restore();
+	});
+
+	it('should update the workspace memento storage', async () => {
+		// set workspace setting
+		const workspaceTestOption = new GoEnvironmentOption('workspacetestpath', 'testlabel');
+		await setSelectedGo(workspaceTestOption, false);
+
+		// check that the new config is set
+		assert.equal(getSelectedGo()?.binpath, 'workspacetestpath');
+	});
+
+	it('should download an uninstalled version of Go', async () => {
+		if (!process.env['VSCODEGO_BEFORE_RELEASE_TESTS']) {
+			return;
+		}
+
+		// setup tmp home directory for sdk installation
+		const envCache = Object.assign({}, process.env);
+		process.env.HOME = os.tmpdir();
+
+		// set selected go as a version to download
+		const option = new GoEnvironmentOption('go get golang.org/dl/go1.13.12', 'Go 1.13.12');
+		await setSelectedGo(option, false);
+
+		// the temp sdk directory should now contain go1.13.12
+		const subdirs = await fs.readdir(path.join(os.tmpdir(), 'sdk'));
+		assert.ok(subdirs.includes('go1.13.12'), 'Go 1.13.12 was not installed');
+
+		// cleanup
+		process.env = envCache;
+	});
+});
+
+describe('#updateGoVarsFromConfig()', async function () {
 	this.timeout(10000);
 
-	let defaultGoConfig: WorkspaceConfiguration | undefined;
+	let defaultMemento: vscode.Memento;
 	let tmpRoot: string | undefined;
 	let tmpRootBin: string | undefined;
 	let sandbox: sinon.SinonSandbox | undefined;
+	const version = await ourutil.getGoVersion();
+	const defaultGoOption = new GoEnvironmentOption(version.binaryPath, formatGoVersion(version));
 
 	this.beforeAll(async () => {
-		defaultGoConfig = ourutil.getGoConfig();
+		defaultMemento = getWorkspaceState();
+		setWorkspaceState(new MockMemento());
+		await setSelectedGo(defaultGoOption);
 
 		tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'rootchangetest'));
 		tmpRootBin = path.join(tmpRoot, 'bin');
@@ -62,15 +132,17 @@
 		const fixtureSourcePath = path.join(__dirname, '..', '..', '..', 'test', 'fixtures', 'testhelpers');
 		const execFile = util.promisify(cp.execFile);
 		const goRuntimePath = ourutil.getBinPath('go');
-		const { stdout, stderr } = await execFile(
+		const { stderr } = await execFile(
 			goRuntimePath, ['build', '-o', path.join(tmpRootBin, 'go'), path.join(fixtureSourcePath, 'fakego.go')]);
 		if (stderr) {
 			assert.fail(`failed to build the fake go binary required for testing: ${stderr}`);
 		}
 	});
 
-	this.afterAll(() => {
+	this.afterAll(async () => {
+		setWorkspaceState(defaultMemento);
 		ourutil.rmdirRecursive(tmpRoot);
+		await updateGoVarsFromConfig();
 	});
 
 	this.beforeEach(() => {
@@ -101,21 +173,12 @@
 	});
 
 	it('should recognize the adjusted goroot using go.goroot', async () => {
-		// stub geteGoConfig to return "go.goroot": tmpRoot.
-		const getGoConfigStub = sandbox.stub(ourutil, 'getGoConfig').returns({
-			get: (s: string) => {
-				if (s === 'goroot') { return tmpRoot; }
-				return defaultGoConfig.get(s);
-			},
-		} as WorkspaceConfiguration);
-
 		// adjust the fake go binary's behavior.
 		process.env['FAKEGOROOT'] = tmpRoot;
 		process.env['FAKEGOVERSION'] = 'go version go2.0.0 darwin/amd64';
 
 		await updateGoVarsFromConfig();
 
-		sandbox.assert.calledWith(getGoConfigStub);
 		assert.equal((await ourutil.getGoVersion()).format(), '2.0.0');
 		assert.equal(getGoEnvironmentStatusbarItem().text, 'Go 2.0.0');
 		assert.equal(pathEnvVar()[0], [path.join(getCurrentGoRoot(), 'bin')],
@@ -126,21 +189,11 @@
 		// "go.alternateTools" : {"go": "go3"}
 		fs.copyFileSync(path.join(tmpRootBin, 'go'), path.join(tmpRootBin, 'go3'));
 
-		const getGoConfigStub = sandbox.stub(ourutil, 'getGoConfig').returns({
-			get: (s: string) => {
-				if (s === 'alternateTools') {
-					return { go: path.join(tmpRootBin, 'go3') };
-				}
-				return defaultGoConfig.get(s);
-			},
-		} as WorkspaceConfiguration);
-
 		process.env['FAKEGOROOT'] = tmpRoot;
 		process.env['FAKEGOVERSION'] = 'go version go3.0.0 darwin/amd64';
 
 		await updateGoVarsFromConfig();
 
-		sandbox.assert.calledWith(getGoConfigStub);
 		assert.equal((await ourutil.getGoVersion()).format(), '3.0.0');
 		assert.equal(getGoEnvironmentStatusbarItem().text, 'Go 3.0.0');
 		assert.equal(pathEnvVar()[0], [path.join(getCurrentGoRoot(), 'bin')],
diff --git a/test/integration/test.test.ts b/test/integration/test.test.ts
new file mode 100644
index 0000000..6287f7a
--- /dev/null
+++ b/test/integration/test.test.ts
@@ -0,0 +1,137 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+'use strict';
+
+import * as assert from 'assert';
+import fs = require('fs-extra');
+import os = require('os');
+import path = require('path');
+import sinon = require('sinon');
+import vscode = require('vscode');
+import { getTestFlags, goTest } from '../../src/testUtils';
+import { rmdirRecursive } from '../../src/util';
+
+suite('Test Go Test', function () {
+	this.timeout(10000);
+
+	const sourcePath = path.join(__dirname, '..', '..', '..', 'test', 'fixtures', 'goTestTest');
+
+	let tmpGopath: string;
+	let repoPath: string;
+
+	let previousEnv: any;
+
+	setup(() => {
+		previousEnv = Object.assign({}, process.env);
+	});
+
+	teardown(async () => {
+		process.env = previousEnv;
+		rmdirRecursive(tmpGopath);
+	});
+
+	function setupRepo(modulesMode: boolean) {
+		tmpGopath = fs.mkdtempSync(path.join(os.tmpdir(), 'go-test-test'));
+		fs.mkdirSync(path.join(tmpGopath, 'src'));
+		repoPath = path.join(tmpGopath, 'src', 'goTestTest');
+		fs.copySync(sourcePath, repoPath, {
+			recursive: true,
+			filter: (src: string): boolean => {
+				if (modulesMode) {
+					return true;
+				}
+				return path.basename(src) !== 'go.mod';  // skip go.mod file.
+			},
+		});
+		process.env.GOPATH = tmpGopath;
+	}
+
+	async function runTest(
+		input: { isMod: boolean, includeSubDirectories: boolean, testFlags?: string[] },
+		wantFiles: string[]) {
+
+		fs.copySync(sourcePath, repoPath, { recursive: true });
+
+		const config = Object.create(vscode.workspace.getConfiguration('go'));
+		const outputChannel = new FakeOutputChannel();
+
+		const testConfig = {
+			goConfig: config,
+			outputChannel,
+			dir: repoPath,
+			flags: input.testFlags ? input.testFlags : getTestFlags(config),
+			isMod: input.isMod,
+			includeSubDirectories: input.includeSubDirectories,
+		};
+		try {
+			const result = await goTest(testConfig);
+			assert.equal(result, false);  // we expect tests to fail.
+		} catch (e) {
+			console.log('exception: ${e}');
+		}
+
+		const testOutput = outputChannel.toString();
+		for (const want of wantFiles) {
+			assert.ok(testOutput.includes(want), `\nFully resolved file path "${want}" not found in \n${testOutput}`);
+		}
+	}
+
+	test('resolves file names in logs (modules)', async () => {
+		setupRepo(true);
+		await runTest(
+			{ isMod: true, includeSubDirectories: true },
+			[path.join(repoPath, 'a_test.go'), path.join(repoPath, 'b', 'b_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: false },
+			[path.join(repoPath, 'a_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: true, testFlags: ['-v'] },
+			[path.join(repoPath, 'a_test.go'), path.join(repoPath, 'b', 'b_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: false, testFlags: ['-v'] },
+			[path.join(repoPath, 'a_test.go')]);
+	});
+
+	test('resolves file names in logs (GOPATH)', async () => {
+		setupRepo(true);
+		await runTest(
+			{ isMod: true, includeSubDirectories: true },
+			[path.join(repoPath, 'a_test.go'), path.join(repoPath, 'b', 'b_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: false },
+			[path.join(repoPath, 'a_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: true, testFlags: ['-v'] },
+			[path.join(repoPath, 'a_test.go'), path.join(repoPath, 'b', 'b_test.go')]);
+		await runTest(
+			{ isMod: true, includeSubDirectories: false, testFlags: ['-v'] },
+			[path.join(repoPath, 'a_test.go')]);
+	});
+});
+
+// FakeOutputChannel is a fake output channel used to buffer
+// the output of the tested language client in an in-memory
+// string array until cleared.
+class FakeOutputChannel implements vscode.OutputChannel {
+	public name = 'FakeOutputChannel';
+	public show = sinon.fake(); // no-empty
+	public hide = sinon.fake(); // no-empty
+	public dispose = sinon.fake();  // no-empty
+
+	private buf = [] as string[];
+
+	public append = (v: string) => this.enqueue(v);
+	public appendLine = (v: string) => this.enqueue(v);
+	public clear = () => { this.buf = []; };
+	public toString = () => {
+		return this.buf.join('\n');
+	}
+
+	private enqueue = (v: string) => {
+		if (this.buf.length > 1024) { this.buf.shift(); }
+		this.buf.push(v.trim());
+	}
+}
diff --git a/test/integration/utils.test.ts b/test/integration/utils.test.ts
index 78fa3c3..5e9a8a2 100644
--- a/test/integration/utils.test.ts
+++ b/test/integration/utils.test.ts
@@ -4,7 +4,7 @@
  *--------------------------------------------------------*/
 
 import * as assert from 'assert';
-import { guessPackageNameFromFile, substituteEnv } from '../../src/util';
+import { GoVersion, guessPackageNameFromFile, substituteEnv } from '../../src/util';
 
 suite('utils Tests', () => {
 	test('substituteEnv: default', () => {
@@ -21,6 +21,79 @@
 		// test completed
 		process.env = env;
 	});
+
+	test('build GoVersion', () => {
+		// [input, wantFormat, wantFormatIncludePrerelease, wantIsValid]
+		const testCases: [string|undefined, string, string, boolean][] = [
+			[
+				'go version devel +a295d59d Fri Jun 26 19:00:25 2020 +0000 darwin/amd64',
+				'devel +a295d59d',
+				'devel +a295d59d',
+				true,
+			],
+			[
+				'go version go1.14 darwin/amd64',
+				'1.14.0',
+				'1.14',
+				true,
+			],
+			[
+				'go version go1.14.1 linux/amd64',
+				'1.14.1',
+				'1.14.1',
+				true,
+			],
+			[
+				'go version go1.15rc1 darwin/amd64',
+				'1.15.0',
+				'1.15rc1',
+				true,
+			],
+			[
+				'go version go1.15.1rc2 windows/amd64',
+				'1.15.1',
+				'1.15.1rc2',
+				true,
+			],
+			[
+				'go version go1.15.3-beta.1 darwin/amd64',
+				'1.15.3',
+				'1.15.3-beta.1',
+				true,
+			],
+			[
+				'go version go1.15.3-beta.1.2.3 foobar/amd64',
+				'1.15.3',
+				'1.15.3-beta.1.2.3',
+				true,
+			],
+			[
+				'go version go10.0.1 js/amd64',
+				'unknown',
+				'unknown',
+				false,
+			],
+			[
+				undefined,
+				'unknown',
+				'unknown',
+				false,
+			],
+			[
+				'something wrong',
+				'unknown',
+				'unknown',
+				false,
+			]
+		];
+		for (const [input, wantFormat, wantFormatIncludePrerelease, wantIsValid] of testCases) {
+			const go = new GoVersion('/path/to/go', input);
+
+			assert.equal(go.isValid(), wantIsValid, `GoVersion(${input}) = ${JSON.stringify(go)}`);
+			assert.equal(go.format(), wantFormat, `GoVersion(${input}) = ${JSON.stringify(go)}`);
+			assert.equal(go.format(true), wantFormatIncludePrerelease, `GoVersion(${input}) = ${JSON.stringify(go)}`);
+		}
+	});
 });
 
 suite('GuessPackageNameFromFile Tests', () => {
diff --git a/test/mocks/MockMemento.ts b/test/mocks/MockMemento.ts
new file mode 100644
index 0000000..4c55f16
--- /dev/null
+++ b/test/mocks/MockMemento.ts
@@ -0,0 +1,26 @@
+/*---------------------------------------------------------
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ * Modification copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+import { Memento } from 'vscode';
+
+export class MockMemento implements Memento {
+	// _value must be named this way in order to match vscode's memento
+	private _value: Record<string, {}> = {};
+
+	public get(key: any, defaultValue?: any): any;
+	public get<T>(key: string, defaultValue?: T): T {
+		const exists = this._value.hasOwnProperty(key);
+		return exists ? this._value[key] : (defaultValue! as any);
+	}
+
+	public update(key: string, value: any): Thenable<void> {
+		this._value[key] = value;
+		return Promise.resolve();
+	}
+	public clear() {
+		this._value = {};
+	}
+}
diff --git a/test/runTest.ts b/test/runTest.ts
index d7656e6..edb587e 100644
--- a/test/runTest.ts
+++ b/test/runTest.ts
@@ -1,7 +1,5 @@
-import * as fs from 'fs-extra';
 import * as path from 'path';
 import { runTests } from 'vscode-test';
-import { extensionId } from '../src/const';
 
 async function main() {
 		// The folder containing the Extension Manifest package.json
diff --git a/tools/license.sh b/tools/license.sh
index 9647e1f..8750bca 100755
--- a/tools/license.sh
+++ b/tools/license.sh
@@ -40,6 +40,9 @@
   "Unlicense": 1,
   "0BSD": 1,
   "(Unlicense OR Apache-2.0)": 1,
+  "(MIT OR Apache-2.0)": 1,
+  "(MIT AND Zlib)": 1,
+  "(MIT AND BSD-3-Clause)": 1,
 } as $allowed_licenses |
 {
   "json-schema@0.2.3": 1,
diff --git a/tsconfig.json b/tsconfig.json
index 6045bef..df30337 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -20,4 +20,4 @@
 		"node_modules",
 		"third_party"
 	]
-}
\ No newline at end of file
+}
diff --git a/tslint.json b/tslint.json
index 41739c7..d9108ea 100644
--- a/tslint.json
+++ b/tslint.json
@@ -151,7 +151,8 @@
 			true,
 			"ban-keywords",
 			"check-format",
-			"allow-pascal-case"
+			"allow-pascal-case",
+			"allow-leading-underscore"
 		],
 		"whitespace": [
 			true,
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000..65d2b3f
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,48 @@
+//@ts-check
+
+'use strict';
+
+const path = require('path');
+
+/**@type {import('webpack').Configuration}*/
+const config = {
+	target: 'node',
+	entry: {
+		goMain: './src/goMain.ts',
+		debugAdapter: './src/debugAdapter/goDebug.ts',
+		debugAdapter2: './src/debugAdapter2/goDlvDebugMain.ts',
+	},
+	output: {
+		path: path.resolve(__dirname, 'dist'),
+		filename: '[name].js',
+		libraryTarget: 'commonjs2',
+		devtoolModuleFilenameTemplate: '../[resource-path]',
+		sourceMapFilename: '[name].js.map'
+	},
+	devtool: 'source-map',
+	externals: {
+		// the vscode-module is created on-the-fly and must be excluded.
+		vscode: 'commonjs vscode'
+	},
+	resolve: {
+		extensions: ['.ts', '.js']
+	},
+	module: {
+		rules: [
+			{
+				test: /\.ts$/,
+				exclude: /node_modules/,
+				use: [
+					{
+						loader: 'ts-loader'
+					}
+				]
+			}
+		]
+	},
+	optimization: {
+		// when this is true, the debugger breaks...
+		minimize: false
+	},
+};
+module.exports = config;