[latest] v0.17.0

8b166d9 [release] release: fix CHANGELOG.md
8439353 [release] 0.17.0 CHANGELOG
dfefea0 [release] debugAdapter: fix a bug where we are not sending back configuration done response
6f67a37 [release] src/goDebugConfiguration.ts: add resolveDebugConfiguration back
be02aa1 [release] test/gopls: fix completion middleware test
bbadf55 [release] build/all.bash: build vscode-test-env from the root
47a7452 [release] prepare v0.17.0 release
322e058 0.16.2 release CHANGELOG
368fc43 src/util.ts: allow getGoVersion when there is no active text editor
c23df8f src/goLanguageServer.ts: restart if go.toolsEnvVars changes
f8bce8c src/goBuild: remove misleading error message in modules mode
dcea773 src/goCover.ts: correct windows absolute filepath handling
02869c8 src/goPackages.ts: pass GOROOT to gopkgs
0b32079 docs/switch-version.md: add Go version switching documentation
1080e21 src/util.ts,goLanguageServer.ts: set cwd for cp.execFile
d594eec build: add setup_env to all.bash and update contributing.md
c705adf src/goInstallTools: report `go env` failure
f2fd351 src/debugAdapter: make filepaths in errors absolute
52260e0 src/goCover.ts: provide explicit directory for running go list
859bb8a src/goTools.ts: recognize gofumpt, gofumports formatters
d05379e test/integration: increase extension test timeout
43d6d04 package.json: let some commands activate extension
5a7752c src/debugAdapter: add delve 'call' command support
575abde src/goEnvironmentStatus: fix PATH mutation logic in osx
77bda0a test/gopls: print gopls traces when test fails
2c287db src/goDebugConfiguration: expand '~' in cwd attribute
bd77a6f src/testUtils.ts: always run test in package list mode
a7b1705 test/integration: add extra tests for env var combining
3ffb96e src/goCover: remove obsolete go.coverageDecorator support
da7328b package.json: disable debug config's showGlobalVariables by default
4b52e43 package.json: disable go.installDependenciesWhenBuilding by default
c7c4188 src/goDebugConfiguration: combine envFile and env
cd41bd1 .github/workflows, build: install dlv in containers
c169d13 src/utils/envUtils.ts: add parseEnvFiles
eeb2512 src/utils: move env var utilities to its own module
95570ec goLanguageServer: attach gopls version to issue reports
e15a8a2 docs: link to more VS Code docs, add alternative ways to start
8f16fe4 tools/generate.go: add defaults and enums to settings.md
9167ad2 docs: add stdlib.md
7f493bf src/goEnvironmentStatus.ts: notify user of available Go updates
1e4dbe2 src/testUtils.ts: fix parsing of the compiler error file expansion
47e2496 docs: fix out-of-sync documentation
139fd7d src/goCover.go: add go.coverMode to display coverage data and counts
d41272c src/util.ts: log `go version` output
6aa134d src/goInstallTools.ts: fix the installation failure message
e1603dd package.json: allow additional properties for alternateTools
56f2f9e src/goLanguageServer.ts: update middleware arguments to match gopls
5089f49 build,.github/workflows: use go1.15
2bd6cd6 docs: expand debugging instructions
f4f147c build: add line breaks to build/Dockerfile
116a0a0 package.json: prepare for 0.17.0 dev
bc9db1e CHANGELOG.md: cherry-pick v0.16.1 CHANGELOG update
aabbc51 src/goLanguageServer.ts: add config to overwrite vscode-go codelens
bec9cf3 src/testUtil.ts: switch to -json mode only if -v is set
9bdb768 build,.github/workflows: install all tools in modules mode
f9c0454 src/debugAdapter2: launch as an external process, and fix config
c3f97ff goLanguageServer: change survey prompt probability to 2.75%
d1404a0 src/goLanguageServer.ts: handle missing filterText in completion items
6a84918 src/goEnv.ts: readd go.toolsEnvVars variable substitution
c6695aa src/goMain.ts: reinstate the goroot var interpolation
c22bbe5 CHANGELOG.md: v0.16.0 release note
9523e4b src/goInstallTools.ts: avoid type check error
18eaf7e src/goEnvironmentStatus.ts: ignore uninstalled Go on network failure
fe3c6b5 package.json: require vscode 1.46 or up
9d1620b src/goLanguageServer.ts: add "debug test" and "debug benchmark" codelens
e3aa3a2 src: npm run fix-lint
d8f9560 src/goEnvironmentStatus.ts: handle failed getGoVersion call
dc9de1c src/util.ts: attempt to fix version parsing again
bd41c5e src/goLanguageServer.ts: fix broken event forwarding in middleware

Change-Id: Iac7f79836f317689a482d952136ed7c03215e30f
diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml
index 0df894b..bb2fc21 100644
--- a/.github/workflows/release-nightly.yml
+++ b/.github/workflows/release-nightly.yml
@@ -29,7 +29,7 @@
       - name: Setup Go
         uses: actions/setup-go@v1
         with:
-         go-version: '1.14'
+         go-version: '1.15'
 
       - name: Install dependencies
         run: npm ci
@@ -55,18 +55,12 @@
             go get golang.org/x/lint/golint
             go get golang.org/x/tools/cmd/gorename
             go get golang.org/x/tools/gopls
+            go get github.com/cweill/gotests/...
+            go get github.com/rogpeppe/godef
+            go get github.com/ramya-rao-a/go-outline
+            go get github.com/go-delve/delve/cmd/dlv
         env:
           GO111MODULE: on   
-          
-      - name: Install Go tools (GOPATH mode)
-        run: |
-          go version
-          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
diff --git a/.github/workflows/test-long.yml b/.github/workflows/test-long.yml
index 6fcbbd7..ca0bcd5 100644
--- a/.github/workflows/test-long.yml
+++ b/.github/workflows/test-long.yml
@@ -33,7 +33,7 @@
       - name: Setup Go
         uses: actions/setup-go@v1
         with:
-         go-version: '1.14'
+         go-version: '1.15'
 
       - name: Install dependencies
         run: npm ci
@@ -54,19 +54,13 @@
             go get golang.org/x/lint/golint
             go get golang.org/x/tools/cmd/gorename
             go get golang.org/x/tools/gopls
+            go get github.com/cweill/gotests/...
+            go get github.com/rogpeppe/godef
+            go get github.com/ramya-rao-a/go-outline
+            go get github.com/go-delve/delve/cmd/dlv
         env:
           GO111MODULE: on   
           
-      - name: Install Go tools (GOPATH mode)
-        run: |
-          go version
-          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
         
diff --git a/.github/workflows/test-smoke.yml b/.github/workflows/test-smoke.yml
index 150b21a..fb12a33 100644
--- a/.github/workflows/test-smoke.yml
+++ b/.github/workflows/test-smoke.yml
@@ -29,7 +29,7 @@
       - name: Setup Go
         uses: actions/setup-go@v1
         with:
-         go-version: '1.14'
+         go-version: '1.15'
 
       - name: Install dependencies
         run: npm ci
@@ -50,18 +50,12 @@
             go get golang.org/x/lint/golint
             go get golang.org/x/tools/cmd/gorename
             go get golang.org/x/tools/gopls
+            go get github.com/cweill/gotests/...
+            go get github.com/rogpeppe/godef
+            go get github.com/ramya-rao-a/go-outline
+            go get github.com/go-delve/delve/cmd/dlv
         env:
-          GO111MODULE: on   
-          
-      - name: Install Go tools (GOPATH mode)
-        run: |
-          go version
-          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
+          GO111MODULE: on             
       
       - name: Run unit tests
         run: npm run unit-test
@@ -75,4 +69,4 @@
 
       - name: Lint check
         run: npm run lint
-        if: ${{ matrix.os }} == 'ubuntu-latest'
\ No newline at end of file
+        if: ${{ matrix.os }} == 'ubuntu-latest'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7f311a..cce39ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,107 @@
+## v0.17.0 - 18th Sep, 2020
+
+Go code debugging and code coverage support is getting better.
+
+The extension will help you stay updated with the new Go releases.
+
+### New Features
+
+- Delve's [call](https://github.com/go-delve/delve/tree/master/Documentation/cli#call) feature is now accessible.
+To use this feature, explicitly specify the `call` command. E.g. `call myAwesomeFunc()`.
+It is an experimental feature in Delve.
+Please see [the current limitations](https://github.com/go-delve/delve/tree/master/Documentation/cli#call).
+([Issue 100](https://github.com/golang/vscode-go/issues/100))
+- The extension checks the go official download site and notifies users of
+newly available Go versions. When a newer version is available,
+`Go Update Available` status bar item will appear.
+This feature is available only if `go.useGoProxyToCheckForToolUpdates`
+is set true. ([Issue 483](https://github.com/golang/vscode-go/issues/483))
+- The new `go.coverMode` setting allows to use different coverage modes
+(`atomic`, `count`, `set (default)`). `go.coverShowCounts`,
+`go.coverageDecorator.{coveredBorderColor, uncoveredBorderColor}`
+were newly added. We are still investigating better ways to
+visualize the `count` coverage data; feedback and contribution is welcome!
+(Issue [256](https://github.com/golang/vscode-go/issues/256),
+[594](https://github.com/golang/vscode-go/issues/594))
+
+### Enhancement
+
+- Expands `'~'` in the `cwd` attribute of the launch configuration.
+([Issue 116](https://github.com/golang/vscode-go/issues/116))
+- Debug config's `showGlobalVariables` is disabled by default, and
+this change improves speed. You can still inspect the global
+variables by registering them in the `WATCH` section, or by
+configuring `showGlobalVariables` in `launch.json`.
+([Issue 138](https://github.com/golang/vscode-go/issues/138))
+- `gofumpt`, `gofumports` is added to recognized formatters list.
+([Issue 587](https://github.com/golang/vscode-go/issues/587))
+- Automatically restarts the language server if `go.toolsEnvVars` configuration is changed.
+([CL 254370](https://go-review.googlesource.com/c/vscode-go/+/254370))
+- Reports `go env` failures.
+([Issue 555](https://github.com/golang/vscode-go/issues/555))
+
+### Fixes
+- Fixed to use absolute file paths in error messages appearing in the DEBUG OUTPUT.
+This allows VS Code to locate the correct files.
+([Issue 456](https://github.com/golang/vscode-go/issues/456))
+- Fixed handling of absolute file paths in coverage profile, on windows.
+([Issue 553](https://github.com/golang/vscode-go/issues/553))
+- Changed to pass `GOROOT` when invoking the `gopkgs` tool so `gopkgs`
+continues to work with different go versions without being recompiled.
+([CL 254137]( https://go-review.googlesource.com/c/vscode-go/+/254137))
+- Fixed to provide explicit directory for running go list and go version.
+([Issue 610](https://github.com/golang/vscode-go/issues/610),
+CL [253600]( https://go-review.googlesource.com/c/vscode-go/+/253600),
+[253602]( https://go-review.googlesource.com/c/vscode-go/+/253602))
+- Fixed to trigger extension activation when commands for diagnostics,
+such as `Go: Locate Configured Go Tools` are invoked.
+([Issue 457](https://github.com/golang/vscode-go/issues/457))
+- Fixed to prepend `GOROOT/bin` to integrated terminal's PATH
+environment variable when `go.goroot` is set on OS X.
+([Issue 544](https://github.com/golang/vscode-go/issues/544))
+- Fixed to correctly apply environment variables setting read from `envFile`
+in the launch configuration. We reworked how the environment variables
+configuration is processed during this cycle. Now the extension processes
+the `envFile` attribute instead of asking the debug adapter process to
+read the specified `envFile`.
+([Issue 452](https://github.com/golang/vscode-go/issues/452))
+- Disabled `go.installDependenciesWhenBuilding` by default. When this is
+enabled, the extension runs `go` commands with `-i`, which is no longer
+recommended with recent versions of Go.
+([Issue 568](https://github.com/golang/vscode-go/issues/568))
+- Fixed a bug where we are not sending back 'configuration done' response.
+([Issue eclipse-theia/theia#8455](https://github.com/eclipse-theia/theia/issues/8455),
+[CL 254959](https://go-review.googlesource.com/c/vscode-go/+/254959))
+
+### Documentation
+
+- Added new documentation about
+[switching go versions](https://github.com/golang/vscode-go/blob/master/docs/go-version.md),
+and settings for [standard library development](https://github.com/golang/vscode-go/blob/master/docs/stdlib.md).
+- Improved debugging instruction and contribution guide. Enhanced automated settings documentation generation.
+
+### Code Health
+
+- Removed the obsolete string-type coverageDecorator support.
+([Issue 519](https://github.com/golang/vscode-go/issues/519))
+- When gopls integration tests fail, tests print the observed gopls traces
+to help debugging.
+
+### Experimental Features
+
+- We plan to delegate computation of various `run test` CodeLenses to `gopls`.
+This experimental feature can be enabled with the following setting:
+```
+"go.useLanguageServer": true,
+"gopls": {
+	"codelens": { "test": true }
+}
+```
+
+### Thanks
+
+Thank you for your contribution, @suzmue, @pjweinbgo, @ekulabuhov, @stamblerre, @tpbg, @FiloSottile, @findleyr, @quoctruong, @polinasok, @hyangah!
+
 ## v0.16.2 - 2nd Sep, 2020
 
 ### Fixed
@@ -6,7 +110,7 @@
 - Fixed the regression that caused to run tests in the local directory mode and
   result in more verbose output than the package list mode. ([Issue 528](https://github.com/golang/vscode-go/issues/528)).
 - Fixed `"go.alternateTools"` settings to accept any tool names without
-  settings.json diagnostics warning. ([Issue 526](https://github.com/golang/vscode-go/issues/526)
+  settings.json diagnostics warning. ([Issue 526](https://github.com/golang/vscode-go/issues/526))
 
 
 ## v0.16.1 - 5th Aug, 2020
@@ -94,7 +198,6 @@
 
 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/build/Dockerfile b/build/Dockerfile
index 99e79f1..026e667 100644
--- a/build/Dockerfile
+++ b/build/Dockerfile
@@ -1,11 +1,14 @@
 # This Docker container is used for testing on GCB.
 
-FROM golang:1.14 AS gobuilder
+FROM golang:1.15 AS gobuilder
 
 ENV GO111MODULE on
 ENV GOBIN /gobin
-ENV GOPROXY https://proxy.golang.org
-RUN cd $(mktemp -d) && go get golang.org/x/tools/gopls@latest
+
+# Install other Go tools tests depend on
+RUN mkdir -p /scratch/build
+ADD build/all.bash /scratch/build/all.bash
+RUN /scratch/build/all.bash setup_env
 
 FROM node:latest
 
@@ -14,28 +17,11 @@
 COPY --from=gobuilder /gobin /go/bin
 COPY --from=gobuilder /usr/local/go /usr/local/go
 
-# TODO(hyangah): some tests fail if GOPATH is not set. Fix them.
-ENV GOPATH=/go
-ENV PATH=${GOPATH}/bin:/usr/local/go/bin:${PATH}
+ENV GOPATH /go
+ENV PATH ${GOPATH}/bin:/usr/local/go/bin:${PATH}
 ENV DEBIAN_FRONTEND noninteractive
 
 RUN apt-get update && apt-get install -y libnss3 libgtk-3-dev libxss1 libasound2 xvfb libsecret-1-0
 
-# Install other Go tools tests depend on
-RUN go get -u -v \
-	github.com/acroca/go-symbols \
-	github.com/cweill/gotests/... \
-  	github.com/davidrjenni/reftools/cmd/fillstruct \
-  	github.com/haya14busa/goplay/cmd/goplay \
-  	github.com/mdempsky/gocode \
-  	github.com/ramya-rao-a/go-outline \
-  	github.com/rogpeppe/godef \
-  	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
-
-
 WORKDIR /workspace
 ENTRYPOINT ["build/all.bash"]
diff --git a/build/all.bash b/build/all.bash
index 10c3110..29fc76d 100755
--- a/build/all.bash
+++ b/build/all.bash
@@ -11,6 +11,7 @@
   help      - display this help message.
   test      - build and test locally. Some tests may fail if vscode is already in use.
   testlocal - build and test in a locally built container.
+  setup_env - setup environment for test. This installs tools under GOPATH/bin.
   ci        - build and test with headless vscode. Requires Xvfb.
 EOUSAGE
 }
@@ -55,7 +56,7 @@
 
 run_test_in_docker() {
   echo "**** Building the docker image ***"
-  docker build -t vscode-test-env ./build
+  docker build -t vscode-test-env -f ./build/Dockerfile .
   docker run --workdir=/workspace -v "$(pwd):/workspace" vscode-test-env ci
 }
 
@@ -88,6 +89,24 @@
   cp build/nightly/const.ts src/const.ts
 }
 
+# setup dependencies required for tests.
+install_dependencies() {
+	GO111MODULE=on go get -x -v golang.org/x/tools/gopls
+	GO111MODULE=on go get -x -v github.com/acroca/go-symbols
+	GO111MODULE=on go get -x -v github.com/cweill/gotests/...
+	GO111MODULE=on go get -x -v github.com/davidrjenni/reftools/cmd/fillstruct
+	GO111MODULE=on go get -x -v github.com/haya14busa/goplay/cmd/goplay
+	GO111MODULE=on go get -x -v github.com/mdempsky/gocode
+	GO111MODULE=on go get -x -v github.com/ramya-rao-a/go-outline
+	GO111MODULE=on go get -x -v github.com/rogpeppe/godef
+	GO111MODULE=on go get -x -v github.com/sqs/goreturns
+	GO111MODULE=on go get -x -v github.com/uudashr/gopkgs/v2/cmd/gopkgs
+	GO111MODULE=on go get -x -v github.com/zmb3/gogetdoc
+	GO111MODULE=on go get -x -v golang.org/x/lint/golint
+	GO111MODULE=on go get -x -v golang.org/x/tools/cmd/gorename
+	GO111MODULE=on go get -x -v github.com/go-delve/delve/cmd/dlv
+}
+
 main() {
   cd "$(root_dir)"  # always run from the script root.
   case "$1" in
@@ -110,6 +129,9 @@
     "prepare_nightly")
       prepare_nightly
       ;;
+    "setup_env")
+      install_dependencies
+      ;;
     *)
       usage
       exit 2
diff --git a/docs/contributing.md b/docs/contributing.md
index 752b32d..5fe1cad 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -62,6 +62,15 @@
 
 ## Test
 
+Simple unit tests that do not require interaction with VS Code are located in `test/unit`. 
+Tests in `test/integration` and `test/gopls` directories are integration tests. They involve invocation of the VS Code API and 
+require external Go tools installed in `GOPATH`. The command `setup_env` in [`build/all.bash`](https://github.com/golang/vscode-go/blob/master/build/all.bash)
+installs all the tool dependencies in `GOPATH`. 
+
+1. `export GOPATH=/path/to/gopath/for/test`
+1. `build/all.bash setup_env`
+1. Unfortunately, VS Code test framework inherits your user settings when running tests [Issue 43](https://github.com/golang/vscode-go/issues/43). Make sure VS Code user settings do not contain any go related configuration, except `go.gopath` or `go.toolsGopath` in case you installed the tools for testing in a different `GOPATH`.
+
 There are currently three test launch configurations: (1) `Launch Extension Tests`, (2) `Launch Extension Tests with Gopls`, and (3) `Launch Unit Tests`. To run the tests locally, open the Run view (`Ctrl+Shift+D`), select the relevant launch configuration, and hit the Play button (`F5`).
 
 ## Sideload
diff --git a/docs/debugging.md b/docs/debugging.md
index e5b3f47..51e754e 100644
--- a/docs/debugging.md
+++ b/docs/debugging.md
@@ -28,13 +28,29 @@
 
 [Delve] should be installed by default when you install this extension.
 
+You may need to update `dlv` to the latest version to support the latest version
+of Go—see [Installation](#installation) below.
+
 ### Installation
 
-You can also install it manually in one of two ways:
+You can also install Delve manually in one of two ways:
 
-1. Open the Command Palette (Ctrl+Shift+P), select [`Go: Install/Update Tools`](settings.md#go-installupdate-tools), and select [`dlv`](tools.md#dlv).
+1. Open the [Command Palette][] (Windows/Linux: Ctrl+Shift+P; OSX: Shift+Command+P), select [`Go: Install/Update Tools`](settings.md#go-installupdate-tools), and select [`dlv`](tools.md#dlv).
 2. Follow the [Delve installation instructions](https://github.com/go-delve/delve/tree/master/Documentation/installation).
 
+### Start debugging
+
+1. Open the `package main` source file or the test file you want to debug.
+2. Start debugging using one of the following options:
+   * Open the [Command Palette][], select
+     `Debug: Start Debugging`, then select `Go`.
+   * Open the debug window (Windows/Linux: Ctrl+Shift+D; OSX: Shift+Command+D) and click
+     `Run and Debug`, then select `Go`.
+   * Select **Run > Start Debugging** from the main menu.
+
+   See [the VS Code Debugging documentation](https://code.visualstudio.com/docs/editor/debugging)
+   for more information.
+
 ### Configuration
 
 You may not need to configure any settings to start debugging your programs, but you should be aware that the debugger looks at the following settings.
@@ -50,7 +66,7 @@
     * `maxStructFields`: Maximum number of fields read from a struct. A setting of `-1` indicates that all fields should be read (default: `-1`).
     * `maxVariableRecurse`: How far to recurse when evaluating nested types (default: `1`).
     * `followPointers`: Automatically dereference pointers (default: `true`).
-  * `showGlobalVariables`: Show global variables in the Debug view (default: `true`).
+  * `showGlobalVariables`: Show global variables in the Debug view (default: `false`).
 
 There are some common cases when you might want to tweak the Delve configurations.
 
@@ -362,3 +378,4 @@
 [Delve]: https://github.com/go-delve/delve
 [VS Code variables]: https://code.visualstudio.com/docs/editor/variables-reference
 [snippets]: https://code.visualstudio.com/docs/editor/userdefinedsnippets
+[Command Palette]: https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette
\ No newline at end of file
diff --git a/docs/go-version.md b/docs/go-version.md
new file mode 100644
index 0000000..d35c14b
--- /dev/null
+++ b/docs/go-version.md
@@ -0,0 +1,17 @@
+# Managing Your Go Version
+
+## Using The Go Status Bar
+
+You can view the current Go version by looking at the status bar item in the bottom left corner of VS Code. Clicking this button will present you with a menu from which you can select any version of Go that exists in your $HOME/sdk directory or on <https://golang.org/dl>.
+
+Previously, the `go.goroot` and `go.alternateTools` settings controlled the Go version used by VS Code Go. If you have configured these settings, they are no longer needed and should be deleted.
+
+[](https://i.imgur.com/8qh2Tu2.png)
+
+The "Clear Selection" option resets your Go version to the one found first in either `go.alternateTools`, `go.goroot` or your PATH.
+
+## Installing a New Go Version
+
+After selecting any Go version that has not yet been installed (such as Go 1.14.6 in the screenshot above), the binary will be automatically installed in $HOME/sdk and put to use in your environment.
+
+Once the download completes, VS Code Go will make use of this new Go version.
diff --git a/docs/settings.md b/docs/settings.md
index 591b180..7634e3f 100644
--- a/docs/settings.md
+++ b/docs/settings.md
@@ -25,6 +25,14 @@
 
 Tags and options configured here will be used by the Add Tags command to add tags to struct fields. If promptForTags is true, then user will be prompted for tags and options. By default, json tags are added.
 
+Default:{<br/>
+&nbsp;&nbsp;`"options": "json=omitempty"`,<br/>
+&nbsp;&nbsp;`"promptForTags": false`,<br/>
+&nbsp;&nbsp;`"tags": "json"`,<br/>
+&nbsp;&nbsp;`"transform": "snakecase"`,<br/>
+    }
+
+
 ### `go.alternateTools`
 
 Alternate tools or alternate paths for the same tools used by the Go extension. Provide either absolute path or the name of the binary in GOPATH/bin, GOROOT/bin or PATH. Useful when you want to use wrapper script for the Go tools or versioned tools from https://gopkg.in.
@@ -33,6 +41,8 @@
 
 Include unimported packages in auto-complete suggestions.
 
+Default: `false`
+
 ### `go.buildFlags`
 
 Flags to `go build`/`go test` used during build-on-save or running tests. (e.g. ["-ldflags='-s'"])
@@ -41,57 +51,138 @@
 
 Compiles code on file save using 'go build -i' or 'go test -c -i'. Options are 'workspace', 'package', or 'off'.
 
+Allowed Values:`[package workspace off]`
+
+Default: `package`
+
 ### `go.buildTags`
 
 The Go build tags to use for all commands, that support a `-tags '...'` argument. When running tests, go.testTags will be used instead if it was set.
 
+Default: ``
+
+### `go.coverMode`
+
+When generating code coverage, the value for -covermode
+
+Allowed Values:`[set count atomic]`
+
+Default: `set`
+
 ### `go.coverOnSave`
 
 If true, runs 'go test -coverprofile' on save and shows test coverage.
 
+Default: `false`
+
 ### `go.coverOnSingleTest`
 
 If true, shows test coverage when Go: Test Function at cursor command is run.
 
+Default: `false`
+
 ### `go.coverOnSingleTestFile`
 
 If true, shows test coverage when Go: Test Single File command is run.
 
+Default: `false`
+
 ### `go.coverOnTestPackage`
 
 If true, shows test coverage when Go: Test Package command is run.
 
+Default: `true`
+
+### `go.coverShowCounts`
+
+When generating code coverage, should counts be shown as --374--
+
+Default: `false`
+
 ### `go.coverageDecorator`
 
-This option lets you choose the way to display code coverage. Choose either to highlight the complete line or to show a decorator in the gutter. You can customize the color for the former and the style for the latter.
+This option lets you choose the way to display code coverage. Choose either to highlight the complete line or to show a decorator in the gutter. You can customize the colors and borders for the former and the style for the latter.
+
+Default:{<br/>
+&nbsp;&nbsp;`"coveredBorderColor": "rgba(64,128,128,0.5)"`,<br/>
+&nbsp;&nbsp;`"coveredGutterStyle": "blockblue"`,<br/>
+&nbsp;&nbsp;`"coveredHighlightColor": "rgba(64,128,128,0.5)"`,<br/>
+&nbsp;&nbsp;`"type": "highlight"`,<br/>
+&nbsp;&nbsp;`"uncoveredBorderColor": "rgba(128,64,64,0.25)"`,<br/>
+&nbsp;&nbsp;`"uncoveredGutterStyle": "slashyellow"`,<br/>
+&nbsp;&nbsp;`"uncoveredHighlightColor": "rgba(128,64,64,0.25)"`,<br/>
+    }
+
 
 ### `go.coverageOptions`
 
 Use these options to control whether only covered or only uncovered code or both should be highlighted after running test coverage
 
+Allowed Values:`[showCoveredCodeOnly showUncoveredCodeOnly showBothCoveredAndUncoveredCode]`
+
+Default: `showBothCoveredAndUncoveredCode`
+
 ### `go.delveConfig`
 
 Delve settings that applies to all debugging sessions. Debug configuration in the launch.json file will override these values.
 
+Default:{<br/>
+&nbsp;&nbsp;`"apiVersion": 2`,<br/>
+&nbsp;&nbsp;`"dlvLoadConfig": map[followPointers:true maxArrayValues:64 maxStringLen:64 maxStructFields:-1 maxVariableRecurse:1]`,<br/>
+&nbsp;&nbsp;`"showGlobalVariables": false`,<br/>
+    }
+
+
 ### `go.docsTool`
 
 Pick 'godoc' or 'gogetdoc' to get documentation. Not applicable when using the language server.
 
+Allowed Values:`[godoc gogetdoc guru]`
+
+Default: `godoc`
+
 ### `go.editorContextMenuCommands`
 
 Experimental Feature: Enable/Disable entries from the context menu in the editor.
 
+Default:{<br/>
+&nbsp;&nbsp;`"addImport": true`,<br/>
+&nbsp;&nbsp;`"addTags": true`,<br/>
+&nbsp;&nbsp;`"debugTestAtCursor": true`,<br/>
+&nbsp;&nbsp;`"generateTestForFile": false`,<br/>
+&nbsp;&nbsp;`"generateTestForFunction": true`,<br/>
+&nbsp;&nbsp;`"generateTestForPackage": false`,<br/>
+&nbsp;&nbsp;`"playground": true`,<br/>
+&nbsp;&nbsp;`"removeTags": false`,<br/>
+&nbsp;&nbsp;`"testAtCursor": true`,<br/>
+&nbsp;&nbsp;`"testCoverage": true`,<br/>
+&nbsp;&nbsp;`"testFile": false`,<br/>
+&nbsp;&nbsp;`"testPackage": false`,<br/>
+&nbsp;&nbsp;`"toggleTestFile": true`,<br/>
+    }
+
+
 ### `go.enableCodeLens`
 
 Feature level setting to enable/disable code lens for references and run/debug tests
 
+Default:{<br/>
+&nbsp;&nbsp;`"references": false`,<br/>
+&nbsp;&nbsp;`"runtest": true`,<br/>
+    }
+
+
 ### `go.formatFlags`
 
 Flags to pass to format tool (e.g. ["-s"])
 
 ### `go.formatTool`
 
-Pick 'gofmt', 'goimports', 'goreturns' or 'goformat' to run on format. Not applicable when using the language server. Choosing 'goimports' or 'goreturns' will add missing imports and remove unused imports.
+Not applicable when using the language server. Choosing 'goimports', 'goreturns', or 'gofumports' will add missing imports and remove unused imports.
+
+Allowed Values:`[gofmt goimports goreturns goformat gofumpt gofumports]`
+
+Default: `goreturns`
 
 ### `go.generateTestsFlags`
 
@@ -101,22 +192,34 @@
 
 Enable gocode's autobuild feature. Not applicable when using the language server.
 
+Default: `false`
+
 ### `go.gocodeFlags`
 
 Additional flags to pass to gocode. Not applicable when using the language server.
 
+Default: `[-builtin -ignore-case -unimported-packages]`
+
 ### `go.gocodePackageLookupMode`
 
 Used to determine the Go package lookup rules for completions by gocode. Only applies when using nsf/gocode. Latest versions of the Go extension uses mdempsky/gocode by default. Not applicable when using the language server.
 
+Allowed Values:`[go gb bzl]`
+
+Default: `go`
+
 ### `go.gopath`
 
 Specify GOPATH here to override the one that is set as environment variable. The inferred GOPATH from workspace root overrides this, if go.inferGopath is set to true.
 
+efault: `<nil>`
+
 ### `go.goroot`
 
 Specifies the GOROOT to use when no environment variable is set.
 
+efault: `<nil>`
+
 ### `go.gotoSymbol.ignoreFolders`
 
 Folder names (not paths) to ignore while using Go to Symbol in Workspace feature
@@ -125,22 +228,36 @@
 
 If false, the standard library located at $GOROOT will be excluded while using the Go to Symbol in File feature
 
+Default: `false`
+
 ### `go.gotoSymbol.includeImports`
 
 If false, the import statements will be excluded while using the Go to Symbol in File feature
 
+Default: `false`
+
 ### `go.inferGopath`
 
 Infer GOPATH from the workspace root.
 
+Default: `false`
+
 ### `go.installDependenciesWhenBuilding`
 
-If true, then `-i` flag will be passed to `go build` everytime the code is compiled.
+If true, then `-i` flag will be passed to `go build` everytime the code is compiled. Since Go 1.10, setting this may be unnecessary unless you are in GOPATH mode and do not use the language server.
+
+Default: `false`
 
 ### `go.languageServerExperimentalFeatures`
 
 Use this setting to enable/disable experimental features from the language server.
 
+Default:{<br/>
+&nbsp;&nbsp;`"diagnostics": true`,<br/>
+&nbsp;&nbsp;`"documentLink": true`,<br/>
+    }
+
+
 ### `go.languageServerFlags`
 
 Flags like -rpc.trace and -logfile to be used while running the language server.
@@ -153,26 +270,60 @@
 
 Lints code on file save using the configured Lint tool. Options are 'file', 'package', 'workspace' or 'off'.
 
+Allowed Values:`[file package workspace off]`
+
+Default: `package`
+
 ### `go.lintTool`
 
 Specifies Lint tool name.
 
+Allowed Values:`[golint golangci-lint revive staticcheck]`
+
+Default: `golint`
+
 ### `go.liveErrors`
 
 Use gotype on the file currently being edited and report any semantic or syntactic errors found after configured delay.
 
+Default:{<br/>
+&nbsp;&nbsp;`"delay": 500`,<br/>
+&nbsp;&nbsp;`"enabled": false`,<br/>
+    }
+
+
+### `go.overwriteGoplsMiddleware`
+
+This option provides a set of flags which determine if vscode-go should intercept certain commands from gopls. These flags assume the `gopls` settings, which enable codelens from gopls, are also present.
+
 ### `go.playground`
 
+The flags configured here will be passed through to command `goplay`
+
+Default:{<br/>
+&nbsp;&nbsp;`"openbrowser": true`,<br/>
+&nbsp;&nbsp;`"run": true`,<br/>
+&nbsp;&nbsp;`"share": true`,<br/>
+    }
 
 
 ### `go.removeTags`
 
 Tags and options configured here will be used by the Remove Tags command to remove tags to struct fields. If promptForTags is true, then user will be prompted for tags and options. By default, all tags and options will be removed.
 
+Default:{<br/>
+&nbsp;&nbsp;`"options": ""`,<br/>
+&nbsp;&nbsp;`"promptForTags": false`,<br/>
+&nbsp;&nbsp;`"tags": ""`,<br/>
+    }
+
+
 ### `go.testEnvFile`
 
 Absolute path to a file containing environment variables definitions. File contents should be of the form key=value.
 
+Default: `<nil>`
+
 ### `go.testEnvVars`
 
 Environment variables that will passed to the process that runs the Go tests
@@ -181,18 +332,26 @@
 
 Flags to pass to `go test`. If null, then buildFlags will be used.
 
+efault: `<nil>`
+
 ### `go.testOnSave`
 
 Run 'go test' on save for current package. It is not advised to set this to `true` when you have Auto Save enabled.
 
+Default: `false`
+
 ### `go.testTags`
 
 The Go build tags to use for when running tests. If null, then buildTags will be used.
 
+efault: `<nil>`
+
 ### `go.testTimeout`
 
 Specifies the timeout for go test in ParseDuration format.
 
+Default: `30s`
+
 ### `go.toolsEnvVars`
 
 Environment variables that will passed to the processes that run the Go tools (e.g. CGO_CFLAGS)
@@ -201,30 +360,48 @@
 
 Location to install the Go tools that the extension depends on if you don't want them in your GOPATH.
 
+Default: ``
+
 ### `go.trace.server`
 
 Trace the communication between VS Code and the Go language server.
 
+Allowed Values:`[off messages verbose]`
+
+Default: `off`
+
 ### `go.useCodeSnippetsOnFunctionSuggest`
 
 Complete functions with their parameter signature, including the variable types
 
+Default: `false`
+
 ### `go.useCodeSnippetsOnFunctionSuggestWithoutType`
 
 Complete functions with their parameter signature, excluding the variable types
 
+Default: `false`
+
 ### `go.useGoProxyToCheckForToolUpdates`
 
-When enabled, the extension automatically checks the Go proxy if there are updates available for the Go tools (at present, only gopls) it depends on and prompts the user accordingly
+When enabled, the extension automatically checks the Go proxy if there are updates available for Go and the Go tools (at present, only gopls) it depends on and prompts the user accordingly
+
+Default: `true`
 
 ### `go.useLanguageServer`
 
 Use the Go language server "gopls" from Google for powering language features like code navigation, completion, formatting & diagnostics.
 
+Default: `false`
+
 ### `go.vetFlags`
 
 Flags to pass to `go tool vet` (e.g. ["-all", "-shadow"])
 
 ### `go.vetOnSave`
 
-Vets code on file save using 'go tool vet'. Options are 'workspace', 'package or 'off'.
+Vets code on file save using 'go tool vet'.
+
+Allowed Values:`[package workspace off]`
+
+Default: `package`
diff --git a/docs/stdlib.md b/docs/stdlib.md
new file mode 100644
index 0000000..746fc4c
--- /dev/null
+++ b/docs/stdlib.md
@@ -0,0 +1,31 @@
+# Standard library development
+
+vscode-go and gopls can be used for developing the standard library, but require configuration.
+
+First, you **must open the `src/` folder in VS Code**, not the Go tree root.
+(See [golang/go#32394](https://github.com/golang/go/issues/32394).)
+
+Then, you need to configure the workspace, by placing the following in `src/.vscode/settings.json`.
+
+```json5
+{
+    // Use the local go tool. This needs to be built with make.bash.
+    "go.alternateTools": {
+        "go": "~/godev/bin/go"
+    },
+    // Build a separate set of tools. For golang/vscode-go#294.
+    "go.toolsGopath": "~/.vscode/godev",
+    // Don't reformat HTML files since we have a custom style.
+    "html.format.enable": false,
+}
+```
+
+The above assumes the Go tree is checked out at `~/godev`. If your Go tree is somewhere else, modify
+`go.alternateTools.go` accordingly.
+
+You can add `.vscode` to `.git/info/exclude` to avoid risking checking `settings.json` into git.
+
+If you see an "inconsistent vendoring" error, please report it at
+[golang/go#40250](https://github.com/golang/go/issues/40250).
+
+See also [golang/go#38603](https://github.com/golang/go/issues/38603).
diff --git a/package-lock.json b/package-lock.json
index 1afb504..93079f4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "go",
-  "version": "0.16.2",
+  "version": "0.17.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index db480b5..344eee9 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "go",
   "displayName": "Go",
-  "version": "0.16.2",
+  "version": "0.17.0",
   "publisher": "golang",
   "description": "Rich Go language support for Visual Studio Code",
   "author": {
@@ -90,6 +90,8 @@
     "onLanguage:go",
     "onCommand:go.gopath",
     "onCommand:go.tools.install",
+    "onCommand:go.locate.tools",
+    "onCommand:go.show.commands",
     "onDebugResolve:go"
   ],
   "main": "./dist/goMain.js",
@@ -620,7 +622,7 @@
               },
               "showGlobalVariables": {
                 "type": "boolean",
-                "default": true,
+                "default": false,
                 "description": "Boolean value to indicate whether global package variables should be shown in the variables pane or not."
               }
             }
@@ -750,7 +752,7 @@
               },
               "showGlobalVariables": {
                 "type": "boolean",
-                "default": true,
+                "default": false,
                 "description": "Boolean value to indicate whether global package variables should be shown in the variables pane or not."
               }
             }
@@ -1003,7 +1005,7 @@
               },
               "showGlobalVariables": {
                 "type": "boolean",
-                "default": true,
+                "default": false,
                 "description": "Boolean value to indicate whether global package variables should be shown in the variables pane or not."
               }
             }
@@ -1125,7 +1127,7 @@
               },
               "showGlobalVariables": {
                 "type": "boolean",
-                "default": true,
+                "default": false,
                 "description": "Boolean value to indicate whether global package variables should be shown in the variables pane or not."
               }
             }
@@ -1174,8 +1176,8 @@
         },
         "go.installDependenciesWhenBuilding": {
           "type": "boolean",
-          "default": true,
-          "description": "If true, then `-i` flag will be passed to `go build` everytime the code is compiled.",
+          "default": false,
+          "description": "If true, then `-i` flag will be passed to `go build` everytime the code is compiled. Since Go 1.10, setting this may be unnecessary unless you are in GOPATH mode and do not use the language server.",
           "scope": "resource"
         },
         "go.lintOnSave": {
@@ -1219,7 +1221,7 @@
             "off"
           ],
           "default": "package",
-          "description": "Vets code on file save using 'go tool vet'. Options are 'workspace', 'package or 'off'.",
+          "description": "Vets code on file save using 'go tool vet'.",
           "scope": "resource"
         },
         "go.vetFlags": {
@@ -1234,13 +1236,15 @@
         "go.formatTool": {
           "type": "string",
           "default": "goreturns",
-          "description": "Pick 'gofmt', 'goimports', 'goreturns' or 'goformat' to run on format. Not applicable when using the language server. Choosing 'goimports' or 'goreturns' will add missing imports and remove unused imports.",
+          "description": "Not applicable when using the language server. Choosing 'goimports', 'goreturns', or 'gofumports' will add missing imports and remove unused imports.",
           "scope": "resource",
           "enum": [
             "gofmt",
             "goimports",
             "goreturns",
-            "goformat"
+            "goformat",
+            "gofumpt",
+            "gofumports"
           ]
         },
         "go.formatFlags": {
@@ -1309,6 +1313,23 @@
           "default": false,
           "description": "If true, shows test coverage when Go: Test Single File command is run."
         },
+        "go.coverMode": {
+          "type": "string",
+          "enum": [
+            "set",
+            "count",
+            "atomic"
+          ],
+          "default": "set",
+          "description": "When generating code coverage, the value for -covermode",
+          "scope": "resource"
+        },
+        "go.coverShowCounts": {
+          "type": "boolean",
+          "default": false,
+          "description": "When generating code coverage, should counts be shown as --374--",
+          "scope": "resource"
+        },
         "go.coverageOptions": {
           "type": "string",
           "enum": [
@@ -1325,7 +1346,6 @@
           "properties": {
             "type": {
               "type": "string",
-              "default": "highlight",
               "enum": [
                 "highlight",
                 "gutter"
@@ -1333,17 +1353,22 @@
             },
             "coveredHighlightColor": {
               "type": "string",
-              "default": "rgba(64,128,128,0.5)",
               "description": "Color in the rgba format to use to highlight covered code."
             },
             "uncoveredHighlightColor": {
               "type": "string",
-              "default": "rgba(128,64,64,0.25)",
               "description": "Color in the rgba format to use to highlight uncovered code."
             },
+            "coveredBorderColor": {
+              "type": "string",
+              "description": "Color to use for the border of covered code."
+            },
+            "uncoveredBorderColor": {
+              "type": "string",
+              "description": "Color to use for the border of uncovered code."
+            },
             "coveredGutterStyle": {
               "type": "string",
-              "default": "blockblue",
               "enum": [
                 "blockblue",
                 "blockred",
@@ -1362,7 +1387,6 @@
             },
             "uncoveredGutterStyle": {
               "type": "string",
-              "default": "blockblue",
               "enum": [
                 "blockblue",
                 "blockred",
@@ -1385,10 +1409,12 @@
             "type": "highlight",
             "coveredHighlightColor": "rgba(64,128,128,0.5)",
             "uncoveredHighlightColor": "rgba(128,64,64,0.25)",
+            "coveredBorderColor": "rgba(64,128,128,0.5)",
+            "uncoveredBorderColor": "rgba(128,64,64,0.25)",
             "coveredGutterStyle": "blockblue",
             "uncoveredGutterStyle": "slashyellow"
           },
-          "description": "This option lets you choose the way to display code coverage. Choose either to highlight the complete line or to show a decorator in the gutter. You can customize the color for the former and the style for the latter.",
+          "description": "This option lets you choose the way to display code coverage. Choose either to highlight the complete line or to show a decorator in the gutter. You can customize the colors and borders for the former and the style for the latter.",
           "scope": "resource"
         },
         "go.testTimeout": {
@@ -1539,7 +1565,7 @@
         "go.useGoProxyToCheckForToolUpdates": {
           "type": "boolean",
           "default": true,
-          "description": "When enabled, the extension automatically checks the Go proxy if there are updates available for the Go tools (at present, only gopls) it depends on and prompts the user accordingly"
+          "description": "When enabled, the extension automatically checks the Go proxy if there are updates available for Go and the Go tools (at present, only gopls) it depends on and prompts the user accordingly"
         },
         "go.gotoSymbol.includeImports": {
           "type": "boolean",
@@ -1575,6 +1601,34 @@
           "description": "Feature level setting to enable/disable code lens for references and run/debug tests",
           "scope": "resource"
         },
+        "go.overwriteGoplsMiddleware": {
+          "type": "object",
+          "properties": {
+            "codelens": {
+              "type": "object",
+              "properties": {
+                "test": {
+                  "type": "boolean",
+                  "default": false,
+                  "description": "'test' codelens will be handled by gopls if true"
+                },
+                "bench": {
+                  "type": "boolean",
+                  "default": false,
+                  "description": "'benchmark' codelens will be handled by gopls if true"
+                }
+              }
+            },
+            "default": {
+              "codelens": {
+                "test": false,
+                "bench": false
+              }
+            }
+          },
+          "scope": "resource",
+          "description": "This option provides a set of flags which determine if vscode-go should intercept certain commands from gopls. These flags assume the `gopls` settings, which enable codelens from gopls, are also present."
+        },
         "go.addTags": {
           "type": "object",
           "properties": {
@@ -1680,9 +1734,9 @@
               "type": "boolean",
               "default": true,
               "description": "Whether to run the created Go Playground after creation"
-            },
-            "description": "The flags configured here will be passed through to command `goplay`"
+            }
           },
+          "description": "The flags configured here will be passed through to command `goplay`",
           "additionalProperties": false,
           "default": {
             "openbrowser": true,
@@ -1845,7 +1899,7 @@
             "showGlobalVariables": {
               "type": "boolean",
               "description": "Boolean value to indicate whether global package variables should be shown in the variables pane or not.",
-              "default": true
+              "default": false
             }
           },
           "default": {
@@ -1857,7 +1911,7 @@
               "maxStructFields": -1
             },
             "apiVersion": 2,
-            "showGlobalVariables": true
+            "showGlobalVariables": false
           },
           "description": "Delve settings that applies to all debugging sessions. Debug configuration in the launch.json file will override these values.",
           "scope": "resource"
@@ -1983,4 +2037,4 @@
       ]
     }
   }
-}
+}
\ No newline at end of file
diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts
index b784148..66a53a0 100644
--- a/src/debugAdapter/goDebug.ts
+++ b/src/debugAdapter/goDebug.ts
@@ -29,14 +29,15 @@
 	Thread
 } from 'vscode-debugadapter';
 import { DebugProtocol } from 'vscode-debugprotocol';
+import { parseEnvFiles } from '../utils/envUtils';
 import {
 	envPath,
+	expandFilePathInOutput,
 	fixDriveCasingInWindows,
 	getBinPathWithPreferredGopathGoroot,
 	getCurrentGoWorkspaceFromGOPATH,
 	getInferredGopath,
-	parseEnvFile
-} from '../utils/goPath';
+} from '../utils/pathUtils';
 import {killProcessTree} from '../utils/processUtils';
 
 const fsAccess = util.promisify(fs.access);
@@ -150,6 +151,7 @@
 	pc: number;
 	goroutineID: number;
 	function?: DebugFunction;
+	ReturnValues: DebugVariable[];
 }
 
 interface StacktraceOut {
@@ -190,10 +192,13 @@
 	VariableShadowed = 2,
 	VariableConstant = 4,
 	VariableArgument = 8,
-	VariableReturnArgument = 16
+	VariableReturnArgument = 16,
+	VariableFakeAddress = 32
 }
 
 interface DebugVariable {
+	// DebugVariable corresponds to api.Variable in Delve API.
+	// https://github.com/go-delve/delve/blob/328cf87808822693dc611591519689dcd42696a3/service/api/types.go#L239-L284
 	name: string;
 	addr: number;
 	type: string;
@@ -259,8 +264,6 @@
 	buildFlags?: string;
 	init?: string;
 	trace?: 'verbose' | 'log' | 'error';
-	/** Optional path to .env file. */
-	envFile?: string | string[];
 	backend?: string;
 	output?: string;
 	/** Delve LoadConfig parameters */
@@ -273,6 +276,12 @@
 
 	showGlobalVariables?: boolean;
 	packagePathToGoModPathMap: { [key: string]: string };
+
+	/** Optional path to .env file. */
+	// TODO: deprecate .env file processing from DA.
+	// We expect the extension processes .env files
+	// and send the information to DA using the 'env' property.
+	envFile?: string | string[];
 }
 
 interface AttachRequestArguments extends DebugProtocol.AttachRequestArguments {
@@ -424,23 +433,14 @@
 				}
 
 				// read env from disk and merge into env variables
-				const fileEnvs = [];
 				try {
-					if (typeof launchArgs.envFile === 'string') {
-						fileEnvs.push(parseEnvFile(launchArgs.envFile));
-					}
-					if (Array.isArray(launchArgs.envFile)) {
-						launchArgs.envFile.forEach((envFile) => {
-							fileEnvs.push(parseEnvFile(envFile));
-						});
-					}
+					const fileEnvs = parseEnvFiles(launchArgs.envFile);
+					const launchArgsEnv = launchArgs.env || {};
+					env = Object.assign({}, process.env, fileEnvs, launchArgsEnv);
 				} catch (e) {
-					return reject(e);
+					return reject(`failed to process 'envFile' and 'env' settings: ${e}`);
 				}
 
-				const launchArgsEnv = launchArgs.env || {};
-				env = Object.assign({}, process.env, ...fileEnvs, launchArgsEnv);
-
 				const dirname = isProgramDirectory ? program : path.dirname(program);
 				if (!env['GOPATH'] && (mode === 'debug' || mode === 'test')) {
 					// If no GOPATH is set, then infer it from the file/package path
@@ -872,13 +872,15 @@
 		if (this.stopOnEntry) {
 			this.sendEvent(new StoppedEvent('entry', 1));
 			log('StoppedEvent("entry")');
-			this.sendResponse(response);
 		} else {
 			this.debugState = await this.delve.getDebugState();
 			if (!this.debugState.Running) {
-				this.continueRequest(<DebugProtocol.ContinueResponse>response);
+				log('Changing DebugState from Halted to Running');
+				this.continue();
 			}
 		}
+		this.sendResponse(response);
+		log('ConfigurationDoneResponse', response);
 	}
 
 	/**
@@ -1281,6 +1283,10 @@
 
 	protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void {
 		log('ScopesRequest');
+		// TODO(polinasok): this.stackFrameHandles.get should succeed as long as DA
+		// clients behaves well. Find the documentation around stack frame management
+		// and in case of a failure caused by misbehavior, consider to indicate it
+		// in the error response.
 		const [goroutineId, frameId] = this.stackFrameHandles.get(args.frameId);
 		const listLocalVarsIn = { goroutineID: goroutineId, frame: frameId };
 		this.delve.call<DebugVariable[] | ListVarsOut>(
@@ -1594,8 +1600,47 @@
 		log('PauseResponse');
 	}
 
+	// evaluateRequest is used both for the traditional expression evaluation
+	// (https://github.com/go-delve/delve/blob/master/Documentation/cli/expr.md) and
+	// for the 'call' command support.
+	// If the args.expression starts with the 'call' keyword followed by an expression that looks
+	// like a function call, the request is interpreted as a 'call' command request,
+	// and otherwise, interpreted as `print` command equivalent with RPCServer.Eval.
 	protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void {
 		log('EvaluateRequest');
+		// Captures pattern that looks like the expression that starts with `call<space>`
+		// command call. This is supported only with APIv2.
+		const isCallCommand = args.expression.match(/^\s*call\s+\S+/);
+		if (!this.delve.isApiV1 && isCallCommand) {
+			this.evaluateCallImpl(args).then((out) => {
+				const state = (<CommandOut>out).State;
+				const returnValues = state?.currentThread?.ReturnValues ?? [];
+				switch (returnValues.length) {
+					case 0:
+						response.body = { result: '', variablesReference: 0 };
+						break;
+					case 1:
+						response.body = this.convertDebugVariableToProtocolVariable(returnValues[0]);
+						break;
+					default:
+						// Go function can return multiple return values while
+						// DAP EvaluateResponse assumes a single result with possibly
+						// multiple children. So, create a fake DebugVariable
+						// that has all the results as children.
+						const returnResults = this.wrapReturnVars(returnValues);
+						response.body = this.convertDebugVariableToProtocolVariable(returnResults);
+						break;
+				}
+				this.sendResponse(response);
+				log('EvaluateCallResponse');
+			}, (err) => {
+				this.sendErrorResponse(response, 2009, 'Unable to complete call: "{e}"', {
+					e: err.toString()
+				}, args.context === 'watch' ? null : ErrorDestination.User);
+			});
+			return;
+		}
+		// Now handle it as a conventional evaluateRequest.
 		this.evaluateRequestImpl(args).then(
 			(out) => {
 				const variable = this.delve.isApiV1 ? <DebugVariable>out : (<EvalOut>out).Variable;
@@ -1606,20 +1651,15 @@
 				log('EvaluateResponse');
 			},
 			(err) => {
-				let dest: ErrorDestination;
 				// No need to repeatedly show the error pop-up when expressions
 				// are continiously reevaluated in the Watch panel, which
 				// already displays errors.
-				if (args.context === 'watch') {
-					dest = null;
-				} else {
-					dest = ErrorDestination.User;
-				}
 				this.sendErrorResponse(response, 2009, 'Unable to eval expression: "{e}"', {
 					e: err.toString()
-				}, dest);
+				}, args.context === 'watch' ? null : ErrorDestination.User);
 			}
 		);
+
 	}
 
 	protected setVariableRequest(
@@ -1726,6 +1766,9 @@
 			this.sendEvent(new OutputEvent(str, 'stdout'));
 		};
 		this.delve.onstderr = (str: string) => {
+			if (localPath.length > 0) {
+				str = expandFilePathInOutput(str, localPath);
+			}
 			this.sendEvent(new OutputEvent(str, 'stderr'));
 		};
 		this.delve.onclose = (code) => {
@@ -1955,6 +1998,41 @@
 		});
 	}
 
+	// Go might return more than one result while DAP and VS Code do not support
+	// such scenario but assume one single result. So, wrap all return variables
+	// in one made-up, nameless, invalid variable. This is similar to how scopes
+	// are represented. This assumes the vars are the ordered list of return
+	// values from a function call.
+	private wrapReturnVars(vars: DebugVariable[]): DebugVariable {
+		// VS Code uses the value property of the DebugVariable
+		// when displaying it. So let's formulate it in a user friendly way
+		// as if they look like a list of multiple values.
+		// Note: we use only convertDebugVariableToProtocolVariable's result,
+		// which means we will leak the variable references until the handle
+		// map is cleared. Assuming the number of return parameters is handful,
+		// this waste shouldn't be significant.
+		const values = vars.map((v) => this.convertDebugVariableToProtocolVariable(v).result) || [];
+		return {
+			value: values.join(', '),
+			kind: GoReflectKind.Invalid,
+			flags: GoVariableFlags.VariableFakeAddress | GoVariableFlags.VariableReturnArgument,
+			children: vars,
+
+			// DebugVariable requires the following fields.
+			name: '',
+			addr: 0,
+			type: '',
+			realType: '',
+			onlyAddr: false,
+			DeclLine: 0,
+			len: 0,
+			cap: 0,
+			unreadable: '',
+			base: 0,
+			fullyQualifiedName: ''
+		};
+	}
+
 	private convertDebugVariableToProtocolVariable(v: DebugVariable): { result: string; variablesReference: number } {
 		if (v.kind === GoReflectKind.UnsafePointer) {
 			return {
@@ -2022,6 +2100,35 @@
 				result: v.unreadable ? '<' + v.unreadable + '>' : '"' + val + '"',
 				variablesReference: 0
 			};
+		} else if (v.kind === GoReflectKind.Interface) {
+			if (v.addr === 0) {
+				// an escaped interface variable that points to nil, this shouldn't
+				// happen in normal code but can happen if the variable is out of scope.
+				return {
+					result: 'nil',
+					variablesReference: 0
+				};
+			}
+
+			if (v.children.length === 0) { // Shouldn't happen, but to be safe.
+				return {
+					result: 'nil',
+					variablesReference: 0
+				};
+			}
+			const child = v.children[0];
+			if (child.kind === GoReflectKind.Invalid && child.addr === 0) {
+				return {
+					result: `nil <${v.type}>`,
+					variablesReference: 0
+				};
+			}
+			return {
+				// TODO(hyangah): v.value will be useless. consider displaying more info from the child.
+				// https://github.com/go-delve/delve/blob/930fa3b/service/api/prettyprint.go#L106-L124
+				result: v.value || `<${v.type}(${child.type})>)`,
+				variablesReference: v.children?.length > 0 ? this.variableHandles.create(v) : 0
+			};
 		} else {
 			// Default case - structs
 			if (v.children.length > 0) {
@@ -2108,13 +2215,51 @@
 		return this.delve.callPromise('Command', [{ name: 'continue' }]).then(callback, errorCallback);
 	}
 
+	// evaluateCallImpl expects args.expression starts with the 'call ' command.
+	private evaluateCallImpl(args: DebugProtocol.EvaluateArguments)
+		: Thenable<DebuggerState | CommandOut> {
+		const callExpr = args.expression.trimLeft().slice(`call `.length);
+		// if args.frameID is 'not specified', expression is evaluated in the global scope, according to DAP.
+		// default to the topmost stack frame of the current goroutine
+		let goroutineId = -1;
+		let frameId = 0;
+		if (args.frameId) {
+			[goroutineId, frameId] = this.stackFrameHandles.get(args.frameId, [goroutineId, frameId]);
+		}
+		// See https://github.com/go-delve/delve/blob/328cf87808822693dc611591519689dcd42696a3/service/api/types.go#L321-L350
+		// for the command args for function call.
+		const returnValue = this.delve
+			.callPromise<DebuggerState | CommandOut>('Command', [
+				{
+					name: 'call',
+					goroutineID: goroutineId,
+					returnInfoLoadConfig: this.delve.loadConfig,
+					expr: callExpr,
+					unsafe: false,
+				}
+			])
+			.then(
+				(val) => val,
+				(err) => {
+					logError(
+						'Failed to call function: ',
+						JSON.stringify(callExpr, null, ' '),
+						'\n\rCall error:',
+						err.toString()
+					);
+					return Promise.reject(err);
+				}
+			);
+		return returnValue;
+	}
+
 	private evaluateRequestImpl(args: DebugProtocol.EvaluateArguments): Thenable<EvalOut | DebugVariable> {
 		// default to the topmost stack frame of the current goroutine
 		let goroutineId = -1;
 		let frameId = 0;
 		// args.frameId won't be specified when evaluating global vars
 		if (args.frameId) {
-			[goroutineId, frameId] = this.stackFrameHandles.get(args.frameId);
+			[goroutineId, frameId] = this.stackFrameHandles.get(args.frameId, [goroutineId, frameId]);
 		}
 		const scope = {
 			goroutineID: goroutineId,
diff --git a/src/debugAdapter2/goDlvDebug.ts b/src/debugAdapter2/goDlvDebug.ts
index e1c5b2f..c397050 100644
--- a/src/debugAdapter2/goDlvDebug.ts
+++ b/src/debugAdapter2/goDlvDebug.ts
@@ -20,13 +20,7 @@
 	TerminatedEvent
 } from 'vscode-debugadapter';
 import { DebugProtocol } from 'vscode-debugprotocol';
-
-import {
-	envPath,
-	getBinPathWithPreferredGopathGoroot,
-	parseEnvFile
-} from '../utils/goPath';
-
+import { envPath, expandFilePathInOutput, getBinPathWithPreferredGopathGoroot } from '../utils/pathUtils';
 import { killProcessTree } from '../utils/processUtils';
 
 import { DAPClient } from './dapClient';
@@ -62,8 +56,6 @@
 	buildFlags?: string;
 	init?: string;
 	trace?: 'verbose' | 'log' | 'error';
-	/** Optional path to .env file. */
-	envFile?: string | string[];
 	backend?: string;
 	output?: string;
 	/** Delve LoadConfig parameters */
@@ -615,19 +607,11 @@
 			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));
-			});
-		}
-
+		// launchArgs.env includes all the environment variables
+		// including vscode-go's toolsExecutionEnvironment (PATH, GOPATH, ...),
+		// and those read from .env files.
 		const launchArgsEnv = launchArgs.env || {};
-		const programEnv = Object.assign({}, process.env, ...fileEnvs, launchArgsEnv);
+		const programEnv = Object.assign({}, process.env, launchArgsEnv);
 
 		log(`Current working directory: ${dirname}`);
 		const goExe = getBinPathWithPreferredGopathGoroot('go', []);
@@ -700,13 +684,15 @@
 
 		log(`Running: ${dlvPath} ${dlvArgs.join(' ')}`);
 
+		const dir = parseProgramArgSync(launchArgs).dirname;
 		this.debugProcess = spawn(dlvPath, dlvArgs, {
-			cwd: parseProgramArgSync(launchArgs).dirname,
+			cwd: dir,
 			env
 		});
 
 		this.debugProcess.stderr.on('data', (chunk) => {
-			const str = chunk.toString();
+			let str = chunk.toString();
+			str = expandFilePathInOutput(str, dir);
 			this.emit('stderr', str);
 		});
 
diff --git a/src/diffUtils.ts b/src/diffUtils.ts
index e0895a1..e147668 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 './utils/goPath';
+import { getBinPathFromEnvVar } from './utils/pathUtils';
 
 let diffToolAvailable: boolean | null = null;
 
diff --git a/src/goBrowsePackage.ts b/src/goBrowsePackage.ts
index 79097a3..f52bf79 100644
--- a/src/goBrowsePackage.ts
+++ b/src/goBrowsePackage.ts
@@ -10,7 +10,7 @@
 import vscode = require('vscode');
 import { getAllPackages } from './goPackages';
 import { getBinPath, getCurrentGoPath, getImportPath } from './util';
-import { envPath, getCurrentGoRoot } from './utils/goPath';
+import { envPath, getCurrentGoRoot } from './utils/pathUtils';
 
 export function browsePackages() {
 	let workDir = '';
diff --git a/src/goBuild.ts b/src/goBuild.ts
index a265e54..66ffb5e 100644
--- a/src/goBuild.ts
+++ b/src/goBuild.ts
@@ -21,7 +21,7 @@
 	ICheckResult,
 	runTool
 } from './util';
-import { getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
+import { getCurrentGoWorkspaceFromGOPATH } from './utils/pathUtils';
 
 /**
  * Builds current package or workspace.
@@ -146,15 +146,17 @@
 
 	outputChannel.appendLine(`Starting building the current package at ${cwd}`);
 
-	// Find the right importPath instead of directly using `.`. Fixes https://github.com/Microsoft/vscode-go/issues/846
 	const currentGoWorkspace = getCurrentGoWorkspaceFromGOPATH(getCurrentGoPath(), cwd);
 	let importPath = '.';
-	if (currentGoWorkspace && !isMod) {
-		importPath = cwd.substr(currentGoWorkspace.length + 1);
-	} else {
-		outputChannel.appendLine(
-			`Not able to determine import path of current package by using cwd: ${cwd} and Go workspace: ${currentGoWorkspace}`
-		);
+	if (!isMod) {
+		// Find the right importPath instead of directly using `.`. Fixes https://github.com/Microsoft/vscode-go/issues/846
+		if (currentGoWorkspace && !isMod) {
+			importPath = cwd.substr(currentGoWorkspace.length + 1);
+		} else {
+			outputChannel.appendLine(
+				`Not able to determine import path of current package by using cwd: ${cwd} and Go workspace: ${currentGoWorkspace}`
+			);
+		}
 	}
 
 	running = true;
diff --git a/src/goCover.ts b/src/goCover.ts
index b1d3994..f1e96a5 100644
--- a/src/goCover.ts
+++ b/src/goCover.ts
@@ -12,20 +12,32 @@
 import { getImportPathToFolder } from './goPackages';
 import { getTestFlags, goTest, showTestOutput, TestConfig } from './testUtils';
 import { getGoConfig } from './util';
+import { fixDriveCasingInWindows } from './utils/pathUtils';
 
-let gutterSvgs: { [key: string]: string };
+let gutterSvgs: { [key: string]: string; };
+
+interface Highlight {
+	top: vscode.TextEditorDecorationType;
+	mid: vscode.TextEditorDecorationType;
+	bot: vscode.TextEditorDecorationType;
+	all: vscode.TextEditorDecorationType;
+}
+
 let decorators: {
-	type: string;
-	coveredGutterDecorator: vscode.TextEditorDecorationType;
-	uncoveredGutterDecorator: vscode.TextEditorDecorationType;
-	coveredHighlightDecorator: vscode.TextEditorDecorationType;
-	uncoveredHighlightDecorator: vscode.TextEditorDecorationType;
+	type: 'highlight' | 'gutter';
+	coveredGutter: vscode.TextEditorDecorationType;
+	uncoveredGutter: vscode.TextEditorDecorationType;
+	coveredHighlight: Highlight;
+	uncoveredHighlight: Highlight;
 };
+
 let decoratorConfig: {
 	[key: string]: any;
-	type: string;
+	type: 'highlight' | 'gutter';
 	coveredHighlightColor: string;
 	uncoveredHighlightColor: string;
+	coveredBorderColor: string;
+	uncoveredBorderColor: string;
 	coveredGutterStyle: string;
 	uncoveredGutterStyle: string;
 };
@@ -56,34 +68,7 @@
 		verticalyellow: ctx.asAbsolutePath('images/gutter-vertyellow.svg')
 	};
 
-	// Update the coverageDecorator in User config, if they are using the old style.
 	const goConfig = getGoConfig();
-	const inspectResult = goConfig.inspect('coverageDecorator');
-	if (inspectResult) {
-		if (typeof inspectResult.globalValue === 'string') {
-			goConfig.update(
-				'coverageDecorator',
-				{ type: inspectResult.globalValue },
-				vscode.ConfigurationTarget.Global
-			);
-		}
-		if (typeof inspectResult.workspaceValue === 'string') {
-			goConfig.update(
-				'coverageDecorator',
-				{ type: inspectResult.workspaceValue },
-				vscode.ConfigurationTarget.Workspace
-			);
-		}
-		if (typeof inspectResult.workspaceFolderValue === 'string') {
-			goConfig.update(
-				'coverageDecorator',
-				{ type: inspectResult.workspaceValue },
-				vscode.ConfigurationTarget.WorkspaceFolder
-			);
-		}
-	}
-
-	// Update the decorators
 	updateCodeCoverageDecorators(goConfig.get('coverageDecorator'));
 }
 
@@ -94,23 +79,28 @@
 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)
+	// It appears that the contributions in package.json are only used to check what users
+	// put in settings.json, while the defaults come from the defaults section of
+	// go.coverageDecorator in package.json.
 	decoratorConfig = {
 		type: 'highlight',
 		coveredHighlightColor: 'rgba(64,128,128,0.5)',
+		coveredBorderColor: 'rgba(64,128,128,1.0)',
 		uncoveredHighlightColor: 'rgba(128,64,64,0.25)',
+		uncoveredBorderColor: 'rgba(128,64,64,1.0)',
 		coveredGutterStyle: 'blockblue',
 		uncoveredGutterStyle: 'slashyellow'
 	};
 
-	// Update from configuration
-	if (typeof coverageDecoratorConfig === 'string') {
-		decoratorConfig.type = coverageDecoratorConfig;
+	// Update from configuration.
+	if (typeof coverageDecoratorConfig !== 'object') {
+		vscode.window.showWarningMessage(`invalid go.coverageDecorator type, expected an 'object'`);
 	} else {
 		for (const k in coverageDecoratorConfig) {
 			if (coverageDecoratorConfig.hasOwnProperty(k)) {
 				decoratorConfig[k] = coverageDecoratorConfig[k];
+			} else {
+				vscode.window.showWarningMessage(`invalid coverage parameter ${k}`);
 			}
 		}
 	}
@@ -120,20 +110,53 @@
 
 function setDecorators() {
 	disposeDecorators();
+	if (!decorators) { initForTest(); } // only happens in tests
+	const f = (x: { overviewRulerColor: string, backgroundColor: string; }, arg: string) => {
+		const y = {
+			overviewRulerLane: 2,
+			borderStyle: arg,
+			borderWidth: '2px',
+		};
+		return Object.assign(y, x);
+	};
+	const cov = {
+		overviewRulerColor: 'green',
+		backgroundColor: decoratorConfig.coveredHighlightColor,
+		borderColor: decoratorConfig.coveredBorderColor
+	};
+	const uncov = {
+		overviewRulerColor: 'red',
+		backgroundColor: decoratorConfig.uncoveredHighlightColor,
+		borderColor: decoratorConfig.uncoveredBorderColor
+	};
+	const ctop = f(cov, 'solid solid none solid');
+	const cmid = f(cov, 'none solid none solid');
+	const cbot = f(cov, 'none solid solid solid');
+	const cone = f(cov, 'solid solid solid solid');
+	const utop = f(uncov, 'solid solid none solid');
+	const umid = f(uncov, 'none solid none solid');
+	const ubot = f(uncov, 'none solid solid solid');
+	const uone = f(uncov, 'solid solid solid solid');
 	decorators = {
 		type: decoratorConfig.type,
-		coveredGutterDecorator: vscode.window.createTextEditorDecorationType({
+		coveredGutter: vscode.window.createTextEditorDecorationType({
 			gutterIconPath: gutterSvgs[decoratorConfig.coveredGutterStyle]
 		}),
-		uncoveredGutterDecorator: vscode.window.createTextEditorDecorationType({
+		uncoveredGutter: vscode.window.createTextEditorDecorationType({
 			gutterIconPath: gutterSvgs[decoratorConfig.uncoveredGutterStyle]
 		}),
-		coveredHighlightDecorator: vscode.window.createTextEditorDecorationType({
-			backgroundColor: decoratorConfig.coveredHighlightColor
-		}),
-		uncoveredHighlightDecorator: vscode.window.createTextEditorDecorationType({
-			backgroundColor: decoratorConfig.uncoveredHighlightColor
-		})
+		coveredHighlight: {
+			all: vscode.window.createTextEditorDecorationType(cone),
+			top: vscode.window.createTextEditorDecorationType(ctop),
+			mid: vscode.window.createTextEditorDecorationType(cmid),
+			bot: vscode.window.createTextEditorDecorationType(cbot),
+		},
+		uncoveredHighlight: {
+			all: vscode.window.createTextEditorDecorationType(uone),
+			top: vscode.window.createTextEditorDecorationType(utop),
+			mid: vscode.window.createTextEditorDecorationType(umid),
+			bot: vscode.window.createTextEditorDecorationType(ubot)
+		},
 	};
 }
 
@@ -142,21 +165,34 @@
  */
 function disposeDecorators() {
 	if (decorators) {
-		decorators.coveredGutterDecorator.dispose();
-		decorators.uncoveredGutterDecorator.dispose();
-		decorators.coveredHighlightDecorator.dispose();
-		decorators.uncoveredHighlightDecorator.dispose();
+		decorators.coveredGutter.dispose();
+		decorators.uncoveredGutter.dispose();
+		decorators.coveredHighlight.all.dispose();
+		decorators.coveredHighlight.top.dispose();
+		decorators.coveredHighlight.mid.dispose();
+		decorators.coveredHighlight.bot.dispose();
+		decorators.uncoveredHighlight.all.dispose();
+		decorators.uncoveredHighlight.top.dispose();
+		decorators.uncoveredHighlight.mid.dispose();
+		decorators.uncoveredHighlight.bot.dispose();
 	}
 }
 
 interface CoverageData {
-	uncoveredRange: vscode.Range[];
-	coveredRange: vscode.Range[];
+	uncoveredOptions: vscode.DecorationOptions[];
+	coveredOptions: vscode.DecorationOptions[];
 }
 
-let coverageData: { [key: string]: CoverageData } = {};  // actual file path to the coverage data.
+let coverageData: { [key: string]: CoverageData; } = {};  // actual file path to the coverage data.
 let isCoverageApplied: boolean = false;
 
+function emptyCoverageData(): CoverageData {
+	return {
+		uncoveredOptions: [],
+		coveredOptions: []
+	};
+}
+
 /**
  * Clear the coverage on all files
  */
@@ -170,11 +206,12 @@
  * 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
+ * @param dir Directory to execute go list in
  */
-export function applyCodeCoverageToAllEditors(coverProfilePath: string, testDir?: string): Promise<void> {
+export function applyCodeCoverageToAllEditors(coverProfilePath: string, dir: string): Promise<void> {
 	const v = new Promise<void>((resolve, reject) => {
 		try {
+			const showCounts = getGoConfig().get('coverShowCounts') as boolean;
 			const coveragePath = new Map<string, CoverageData>();  // <filename> from the cover profile to the coverage data.
 
 			// Clear existing coverage files
@@ -192,41 +229,55 @@
 				// 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]+)/);
+				// TODO: port https://golang.org/cl/179377 for faster parsing.
+
+				const parse = line.match(/^(\S+)\:(\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));
+
+				let filename = parse[1];
+				if (filename.startsWith('.' + path.sep)) {
+					// If it's a relative file path, convert it to an absolute path.
+					// From now on, we can assume that it's a real file name if it is
+					// an absolute path.
+					filename = path.resolve(filename);
+				}
+				// If this is not a real file name, that's package_path + file name,
+				// Record it in seenPaths for `go list` call to resolve package path ->
+				// directory mapping.
+				if (!path.isAbsolute(filename)) {
+					const lastSlash = filename.lastIndexOf('/');
+					if (lastSlash !== -1) {
+						seenPaths.add(filename.slice(0, lastSlash));
+					}
 				}
 
 				// and fill in coveragePath
-				const coverage = coveragePath.get(parse[1]) || { coveredRange: [], uncoveredRange: [] };
+				const coverage = coveragePath.get(parse[1]) || emptyCoverageData();
 				const range = new vscode.Range(
-					// Start Line converted to zero based
+					// Convert lines and columns to 0-based
 					parseInt(parse[2], 10) - 1,
-					// Start Column converted to zero based
 					parseInt(parse[3], 10) - 1,
-					// End Line converted to zero based
 					parseInt(parse[4], 10) - 1,
-					// End Column converted to zero based
 					parseInt(parse[5], 10) - 1
 				);
+				const counts = parseInt(parse[7], 10);
 				// If is Covered (CoverCount > 0)
-				if (parseInt(parse[7], 10) > 0) {
-					coverage.coveredRange.push(range);
+				if (counts > 0) {
+					coverage.coveredOptions.push(...elaborate(range, counts, showCounts));
 				} else {
-					coverage.uncoveredRange.push(range);
+					coverage.uncoveredOptions.push(...elaborate(range, counts, showCounts));
 				}
-				coveragePath.set(parse[1], coverage);
+
+				coveragePath.set(filename, coverage);
 			});
 
-			getImportPathToFolder([...seenPaths], testDir)
+			getImportPathToFolder([...seenPaths], dir)
 				.then((pathsToDirs) => {
-				createCoverageData(pathsToDirs, coveragePath);
-				setDecorators();
-				vscode.window.visibleTextEditors.forEach(applyCodeCoverage);
-				resolve();
-			});
+					createCoverageData(pathsToDirs, coveragePath);
+					setDecorators();
+					vscode.window.visibleTextEditors.forEach(applyCodeCoverage);
+					resolve();
+				});
 		} catch (e) {
 			vscode.window.showInformationMessage(e.msg);
 			reject(e);
@@ -235,27 +286,46 @@
 	return v;
 }
 
+// add decorations to the range
+function elaborate(r: vscode.Range, count: number, showCounts: boolean): vscode.DecorationOptions[] {
+	// irrelevant for "gutter"
+	if (!decorators || decorators.type === 'gutter') { return [{ range: r }]; }
+	const ans: vscode.DecorationOptions[] = [];
+	const dc = decoratorConfig;
+	const backgroundColor = [dc.uncoveredHighlightColor, dc.coveredHighlightColor];
+	const txt: vscode.ThemableDecorationAttachmentRenderOptions = {
+		contentText: count > 0 && showCounts ? `--${count}--` : '',
+		backgroundColor: backgroundColor[count === 0 ? 0 : 1]
+	};
+	const v: vscode.DecorationOptions = {
+		range: r,
+		hoverMessage: `${count} executions`,
+		renderOptions: {
+			before: txt,
+		}
+	};
+	ans.push(v);
+	return ans;
+}
+
 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}`);
+		if (path.isAbsolute(ip)) {
+			setCoverageDataByFilePath(ip, cd);
 			return;
 		}
-		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 lastSlash = ip.lastIndexOf('/');
+		if (lastSlash === -1) {
+			setCoverageDataByFilePath(ip, cd);
+			return;
 		}
+
+		const maybePkgPath = ip.slice(0, lastSlash);
+		const fileDir = pathsToDirs.get(maybePkgPath) || path.resolve(maybePkgPath);
 		const file = fileDir + path.sep + ip.slice(lastSlash + 1);
 		setCoverageDataByFilePath(file, cd);
 	});
@@ -287,34 +357,79 @@
 	if (!editor || editor.document.languageId !== 'go' || editor.document.fileName.endsWith('_test.go')) {
 		return;
 	}
+	let doc = editor.document.fileName;
+	if (path.isAbsolute(doc)) {
+		doc = fixDriveCasingInWindows(doc);
+	}
 
 	const cfg = getGoConfig(editor.document.uri);
 	const coverageOptions = cfg['coverageOptions'];
 	for (const filename in coverageData) {
-		if (editor.document.uri.fsPath.endsWith(filename)) {
-			isCoverageApplied = true;
-			const cd = coverageData[filename];
-			if (coverageOptions === 'showCoveredCodeOnly' || coverageOptions === 'showBothCoveredAndUncoveredCode') {
-				editor.setDecorations(
-					decorators.type === 'gutter'
-						? decorators.coveredGutterDecorator
-						: decorators.coveredHighlightDecorator,
-					cd.coveredRange
-				);
+		if (doc !== fixDriveCasingInWindows(filename)) {
+			continue;
+		}
+		isCoverageApplied = true;
+		const cd = coverageData[filename];
+		if (coverageOptions === 'showCoveredCodeOnly' || coverageOptions === 'showBothCoveredAndUncoveredCode') {
+			if (decorators.type === 'gutter') {
+				editor.setDecorations(decorators.coveredGutter, cd.coveredOptions);
+			} else {
+				detailed(editor, decorators.coveredHighlight, cd.coveredOptions);
 			}
+		}
 
-			if (coverageOptions === 'showUncoveredCodeOnly' || coverageOptions === 'showBothCoveredAndUncoveredCode') {
-				editor.setDecorations(
-					decorators.type === 'gutter'
-						? decorators.uncoveredGutterDecorator
-						: decorators.uncoveredHighlightDecorator,
-					cd.uncoveredRange
-				);
+		if (coverageOptions === 'showUncoveredCodeOnly' || coverageOptions === 'showBothCoveredAndUncoveredCode') {
+			if (decorators.type === 'gutter') {
+				editor.setDecorations(decorators.uncoveredGutter, cd.uncoveredOptions);
+			} else {
+				detailed(editor, decorators.uncoveredHighlight, cd.uncoveredOptions);
 			}
 		}
 	}
 }
 
+function detailed(editor: vscode.TextEditor, h: Highlight, opts: vscode.DecorationOptions[]) {
+	const tops: vscode.DecorationOptions[] = [];
+	const mids: vscode.DecorationOptions[] = [];
+	const bots: vscode.DecorationOptions[] = [];
+	const alls: vscode.DecorationOptions[] = [];
+	opts.forEach((opt) => {
+		const r = opt.range;
+		if (r.start.line === r.end.line) {
+			alls.push(opt);
+			return;
+		}
+		for (let line = r.start.line; line <= r.end.line; line++) {
+			if (line === r.start.line) {
+				const use: vscode.DecorationOptions = {
+					range: editor.document.validateRange(
+						new vscode.Range(line, r.start.character, line, Number.MAX_SAFE_INTEGER)),
+					hoverMessage: opt.hoverMessage,
+					renderOptions: opt.renderOptions
+				};
+				tops.push(use);
+			} else if (line < r.end.line) {
+				const use = {
+					range: editor.document.validateRange(
+						new vscode.Range(line, 0, line, Number.MAX_SAFE_INTEGER)),
+					hoverMessage: opt.hoverMessage
+				};
+				mids.push(use);
+			} else {
+				const use = {
+					range: new vscode.Range(line, 0, line, r.end.character),
+					hoverMessage: opt.hoverMessage
+				};
+				bots.push(use);
+			}
+		}
+	});
+	if (tops.length > 0) { editor.setDecorations(h.top, tops); }
+	if (mids.length > 0) { editor.setDecorations(h.mid, mids); }
+	if (bots.length > 0) { editor.setDecorations(h.bot, bots); }
+	if (alls.length > 0) { editor.setDecorations(h.all, alls); }
+}
+
 /**
  * Listener for file save that clears potential stale coverage data.
  * Local cache tracks files with changes outside of comments to determine
@@ -410,7 +525,7 @@
 
 // These routines enable testing without starting an editing session.
 
-export function coverageFilesForTest():  { [key: string]: CoverageData; } {
+export function coverageFilesForTest(): { [key: string]: CoverageData; } {
 	return coverageData;
 }
 
@@ -426,6 +541,8 @@
 			type: 'highlight',
 			coveredHighlightColor: x,
 			uncoveredHighlightColor: x,
+			coveredBorderColor: x,
+			uncoveredBorderColor: x,
 			coveredGutterStyle: x,
 			uncoveredGutterStyle: x
 		};
diff --git a/src/goDebugConfiguration.ts b/src/goDebugConfiguration.ts
index b65b47b..1e3d4e4 100644
--- a/src/goDebugConfiguration.ts
+++ b/src/goDebugConfiguration.ts
@@ -11,7 +11,8 @@
 import { promptForMissingTool } from './goInstallTools';
 import { packagePathToGoModPathMap } from './goModules';
 import { getFromGlobalState, updateGlobalState } from './stateUtils';
-import { getBinPath, getCurrentGoPath, getGoConfig } from './util';
+import { getBinPath, getGoConfig, resolvePath } from './util';
+import { parseEnvFiles } from './utils/envUtils';
 
 export class GoDebugConfigurationProvider implements vscode.DebugConfigurationProvider {
 	constructor(private defaultDebugAdapterType: string = 'go') { }
@@ -33,7 +34,7 @@
 		];
 	}
 
-	public resolveDebugConfiguration?(
+	public resolveDebugConfiguration(
 		folder: vscode.WorkspaceFolder | undefined,
 		debugConfiguration: vscode.DebugConfiguration,
 		token?: vscode.CancellationToken
@@ -60,21 +61,7 @@
 
 		debugConfiguration['packagePathToGoModPathMap'] = packagePathToGoModPathMap;
 
-		const gopath = getCurrentGoPath(folder ? folder.uri : undefined);
-		if (!debugConfiguration['env']) {
-			debugConfiguration['env'] = { GOPATH: gopath };
-		} else if (!debugConfiguration['env']['GOPATH']) {
-			debugConfiguration['env']['GOPATH'] = gopath;
-		}
-
 		const goConfig = getGoConfig(folder && folder.uri);
-		const goToolsEnvVars = toolExecutionEnvironment();
-		Object.keys(goToolsEnvVars).forEach((key) => {
-			if (!debugConfiguration['env'].hasOwnProperty(key)) {
-				debugConfiguration['env'][key] = goToolsEnvVars[key];
-			}
-		});
-
 		const dlvConfig = goConfig.get<any>('delveConfig');
 		let useApiV1 = false;
 		if (debugConfiguration.hasOwnProperty('useApiV1')) {
@@ -100,6 +87,10 @@
 		if (debugConfiguration.request === 'attach' && !debugConfiguration['cwd']) {
 			debugConfiguration['cwd'] = '${workspaceFolder}';
 		}
+		if (debugConfiguration['cwd']) {
+			// expand 'cwd' folder path containing '~', which would cause dlv to fail
+			debugConfiguration['cwd'] = resolvePath(debugConfiguration['cwd']);
+		}
 
 		debugConfiguration['dlvToolPath'] = getBinPath('dlv');
 		if (!path.isAbsolute(debugConfiguration['dlvToolPath'])) {
@@ -132,6 +123,26 @@
 		return debugConfiguration;
 	}
 
+	public resolveDebugConfigurationWithSubstitutedVariables(
+		folder: vscode.WorkspaceFolder | undefined,
+		debugConfiguration: vscode.DebugConfiguration,
+		token?: vscode.CancellationToken
+	): vscode.DebugConfiguration {
+		// Reads debugConfiguration.envFile and
+		// combines the environment variables from all the env files and
+		// debugConfiguration.env, on top of the tools execution environment variables.
+		// It also unsets 'envFile' from the user-suppled debugConfiguration
+		// because it is already applied.
+		const goToolsEnvVars = toolExecutionEnvironment(folder?.uri); // also includes GOPATH: getCurrentGoPath().
+		const fileEnvs = parseEnvFiles(debugConfiguration['envFile']);
+		const env = debugConfiguration['env'] || {};
+
+		debugConfiguration['env'] = Object.assign(goToolsEnvVars, fileEnvs, env);
+		debugConfiguration['envFile'] = undefined;  // unset, since we already processed.
+
+		return debugConfiguration;
+	}
+
 	private showWarning(ignoreWarningKey: string, warningMessage: string) {
 		const ignoreWarning = getFromGlobalState(ignoreWarningKey);
 		if (ignoreWarning) {
diff --git a/src/goDeclaration.ts b/src/goDeclaration.ts
index 0d13500..034413c 100644
--- a/src/goDeclaration.ts
+++ b/src/goDeclaration.ts
@@ -22,7 +22,7 @@
 	isPositionInString,
 	runGodoc
 } from './util';
-import { getCurrentGoRoot } from './utils/goPath';
+import { getCurrentGoRoot } from './utils/pathUtils';
 import { killProcessTree } from './utils/processUtils';
 
 const missingToolMsg = 'Missing tool: ';
diff --git a/src/goEnv.ts b/src/goEnv.ts
index 0372895..556686a 100644
--- a/src/goEnv.ts
+++ b/src/goEnv.ts
@@ -44,9 +44,9 @@
 
 // toolExecutionEnvironment returns the environment in which tools should
 // be executed. It always returns a new object.
-export function toolExecutionEnvironment(): NodeJS.Dict<string> {
+export function toolExecutionEnvironment(uri?: vscode.Uri): NodeJS.Dict<string> {
 	const env = newEnvironment();
-	const gopath = getCurrentGoPath();
+	const gopath = getCurrentGoPath(uri);
 	if (gopath) {
 		env['GOPATH'] = gopath;
 	}
diff --git a/src/goEnvironmentStatus.ts b/src/goEnvironmentStatus.ts
index 513b243..554fa0f 100644
--- a/src/goEnvironmentStatus.ts
+++ b/src/goEnvironmentStatus.ts
@@ -7,16 +7,17 @@
 
 import cp = require('child_process');
 import fs = require('fs');
+import moment = require('moment');
 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 { hideGoStatus, outputChannel, showGoStatus } from './goStatus';
+import { getFromGlobalState, getFromWorkspaceState, updateGlobalState, updateWorkspaceState } from './stateUtils';
+import { getBinPath, getGoConfig, getGoVersion, getTempFilePath, GoVersion, rmdirRecursive } from './util';
+import { correctBinname, getBinPathFromEnvVar, getCurrentGoRoot, pathExists } from './utils/pathUtils';
 
 export class GoEnvironmentOption {
 	public static fromQuickPickItem({ description, label }: vscode.QuickPickItem): GoEnvironmentOption {
@@ -241,7 +242,7 @@
 		const goXExecutable = getBinPath(newExecutableName);
 		outputChannel.appendLine(`Running: ${goXExecutable} download`);
 		try {
-			await execFile(goXExecutable, ['download'], { env });
+			await execFile(goXExecutable, ['download'], { env, cwd: toolsTmpDir });
 		} catch (downloadErr) {
 			outputChannel.appendLine(`Error finishing installation: ${downloadErr}`);
 			throw new Error('Could not download Go version.');
@@ -301,20 +302,26 @@
 	// 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
+	} else {
+		// When '-l' or '--login' flags are set, the terminal will invoke a login
+		// shell again and the paths from the user's login shell will be prepended
+		// again in front of the path mutated by environmentVariableCollection API.
+		// That causes the mutated path to be ignored which we don't want.
+		// So, let's not use the API if those flags are set, but go with the old way
+		// -- i.e. send the export shell command.
+		// See the open issue and the discussion here:
 		// 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')) {
+		vscode.workspace.getConfiguration('terminal.integrated.shellArgs').get('osx') || []);
+		if (terminalShellArgs.includes('-l') || terminalShellArgs.includes('--login')) {
 			for (const term of vscode.window.terminals) {
 				updateIntegratedTerminal(term);
 			}
-			terminalCreationListener = vscode.window.onDidOpenTerminal(updateIntegratedTerminal);
+			if (!terminalCreationListener) {
+				terminalCreationListener = vscode.window.onDidOpenTerminal(updateIntegratedTerminal);
+			}
+		} else {
+			environmentVariableCollection?.prepend(pathEnvVar, newGoRuntimeBase + path.delimiter);
 		}
 	}
 
@@ -451,3 +458,110 @@
 		return [...opts, new GoEnvironmentOption(dlPath, label)];
 	}, []);
 }
+
+export const latestGoVersionKey = 'latestGoVersions';
+const oneday = 60 * 60 * 24 * 1000; // 24 hours in milliseconds
+
+export async function getLatestGoVersions(): Promise<GoEnvironmentOption[]> {
+	const timeout = oneday;
+	const now = moment.now();
+
+	let results: GoEnvironmentOption[];
+
+	// Check if we can use cached results
+	const cachedResults = getFromGlobalState(latestGoVersionKey);
+	if (cachedResults && now - cachedResults.timestamp < timeout) {
+		results = cachedResults.goVersions;
+	} else {
+		// fetch the latest supported Go versions
+		try {
+			// fetch the latest Go versions and cache the results
+			results = await fetchDownloadableGoVersions();
+			await updateGlobalState(latestGoVersionKey, {
+				timestamp: now,
+				goVersions: results,
+			});
+		} catch (e) {
+			// hardcode the latest versions of Go in case golang.dl is unavailable
+			results = [
+				new GoEnvironmentOption('go get golang.org/dl/go1.15', 'Go 1.15'),
+				new GoEnvironmentOption('go get golang.org/dl/go1.14.7', 'Go 1.14.7'),
+			];
+		}
+	}
+
+	return results;
+}
+
+const dismissedGoVersionUpdatesKey = 'dismissedGoVersionUpdates';
+
+export async function offerToInstallLatestGoVersion() {
+	const goConfig = getGoConfig();
+	if (!goConfig['useGoProxyToCheckForToolUpdates']) {
+		return;
+	}
+
+	let options = await getLatestGoVersions();
+
+	// filter out Go versions the user has already dismissed
+	let dismissedOptions: GoEnvironmentOption[];
+	dismissedOptions = await getFromGlobalState(dismissedGoVersionUpdatesKey);
+	if (!!dismissedOptions) {
+		options = options.filter((version) => !dismissedOptions.find((x) => x.label === version.label));
+	}
+
+	// compare to current go version.
+	const currentVersion = await getGoVersion();
+	if (!!currentVersion) {
+		options = options.filter((version) => currentVersion.lt(version.label));
+	}
+
+	// notify user that there is a newer version of Go available
+	if (options.length > 0) {
+		showGoStatus('Go Update Available', 'go.promptforgoinstall', 'A newer version of Go is available');
+		vscode.commands.registerCommand('go.promptforgoinstall', () => {
+			const download = {
+				title: 'Download',
+				async command() {
+					await vscode.env.openExternal(vscode.Uri.parse(`https://golang.org/dl/`));
+				}
+			};
+
+			const neverAgain = {
+				title: `Don't Show Again`,
+				async command() {
+					// mark these versions as seen
+					dismissedOptions = await getFromGlobalState(dismissedGoVersionUpdatesKey);
+					if (!dismissedOptions) {
+						dismissedOptions = [];
+					}
+					options.forEach((version) => {
+						dismissedOptions.push(version);
+					});
+					await updateGlobalState(dismissedGoVersionUpdatesKey, dismissedOptions);
+				}
+			};
+
+			let versionsText: string;
+			if (options.length > 1) {
+				versionsText = `${options.map((x) => x.label)
+					.reduce((prev, next) => {
+						return prev + ' and ' + next;
+					})} are available`;
+			} else {
+				versionsText = `${options[0].label} is available`;
+			}
+
+			vscode.window
+				.showInformationMessage(
+					`${versionsText}. You are currently using ${formatGoVersion(currentVersion)}.`,
+					download,
+					neverAgain
+				)
+				.then((selection) => {
+					hideGoStatus();
+					selection.command();
+				});
+		});
+	}
+}
diff --git a/src/goFormat.ts b/src/goFormat.ts
index 8ad78d7..7810c04 100644
--- a/src/goFormat.ts
+++ b/src/goFormat.ts
@@ -34,7 +34,7 @@
 		}
 
 		// Fix for https://github.com/Microsoft/vscode-go/issues/613 and https://github.com/Microsoft/vscode-go/issues/630
-		if (formatTool === 'goimports' || formatTool === 'goreturns') {
+		if (formatTool === 'goimports' || formatTool === 'goreturns' || formatTool === 'gofumports') {
 			formatFlags.push('-srcdir', filename);
 		}
 
diff --git a/src/goGetPackage.ts b/src/goGetPackage.ts
index bffefeb..86e5dc9 100644
--- a/src/goGetPackage.ts
+++ b/src/goGetPackage.ts
@@ -10,7 +10,7 @@
 import { buildCode } from './goBuild';
 import { outputChannel } from './goStatus';
 import { getBinPath, getCurrentGoPath, getImportPath } from './util';
-import { envPath, getCurrentGoRoot } from './utils/goPath';
+import { envPath, getCurrentGoRoot } from './utils/pathUtils';
 
 export function goGetPackage() {
 	const editor = vscode.window.activeTextEditor;
diff --git a/src/goImplementations.ts b/src/goImplementations.ts
index 05e44bc..36f9e36 100644
--- a/src/goImplementations.ts
+++ b/src/goImplementations.ts
@@ -17,7 +17,7 @@
 	getGoConfig,
 	getWorkspaceFolderPath
 } from './util';
-import { envPath, getCurrentGoRoot } from './utils/goPath';
+import { envPath, getCurrentGoRoot } from './utils/pathUtils';
 import {killProcessTree} from './utils/processUtils';
 
 interface GoListOutput {
diff --git a/src/goImport.ts b/src/goImport.ts
index 82fa2a9..b4db3a5 100644
--- a/src/goImport.ts
+++ b/src/goImport.ts
@@ -12,7 +12,7 @@
 import { documentSymbols, GoOutlineImportsOptions } from './goOutline';
 import { getImportablePackages } from './goPackages';
 import { getBinPath, getImportPath, parseFilePrelude } from './util';
-import { envPath, getCurrentGoRoot } from './utils/goPath';
+import { envPath, getCurrentGoRoot } from './utils/pathUtils';
 
 const missingToolMsg = 'Missing tool: ';
 
diff --git a/src/goInstall.ts b/src/goInstall.ts
index d2131ac..52b0223 100644
--- a/src/goInstall.ts
+++ b/src/goInstall.ts
@@ -10,7 +10,7 @@
 import { isModSupported } from './goModules';
 import { outputChannel } from './goStatus';
 import { getBinPath, getCurrentGoPath, getGoConfig, getModuleCache } from './util';
-import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
+import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './utils/pathUtils';
 
 export async function installCurrentPackage(): Promise<void> {
 	const editor = vscode.window.activeTextEditor;
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index 7f2527d..218b58e 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -11,7 +11,7 @@
 import { SemVer } from 'semver';
 import util = require('util');
 import vscode = require('vscode');
-import { toolInstallationEnvironment } from './goEnv';
+import { toolExecutionEnvironment, toolInstallationEnvironment } from './goEnv';
 import { addGoRuntimeBaseToPATH, initGoStatusBar } from './goEnvironmentStatus';
 import { getLanguageServerToolPath } from './goLanguageServer';
 import { restartLanguageServer } from './goMain';
@@ -32,10 +32,11 @@
 	getGoConfig,
 	getGoVersion,
 	getTempFilePath,
+	getWorkspaceFolderPath,
 	GoVersion,
 	rmdirRecursive,
 } from './util';
-import { envPath, getCurrentGoRoot, getToolFromToolPath, setCurrentGoRoot } from './utils/goPath';
+import { envPath, getCurrentGoRoot, getToolFromToolPath, setCurrentGoRoot } from './utils/pathUtils';
 
 // declinedUpdates tracks the tools that the user has declined to update.
 const declinedUpdates: Tool[] = [];
@@ -217,6 +218,8 @@
 	}
 	args.push(importPath);
 
+	const toolImportPath = tool.version ? importPath + '@' + tool.version : importPath;
+
 	let output: string;
 	let result: string = '';
 	try {
@@ -240,12 +243,11 @@
 			const outputFile = path.join(destDir, 'bin', process.platform === 'win32' ? `${tool.name}.exe` : tool.name);
 			await execFile(goVersion.binaryPath, ['build', '-o', outputFile, importPath], opts);
 		}
-		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} `;
+		outputChannel.appendLine(`Installing ${toolImportPath} FAILED`);
+		result = `failed to install ${tool.name}(${toolImportPath}): ${e} ${output} `;
 	}
 
 	// Delete the temporary installation directory.
@@ -349,8 +351,15 @@
 	}
 
 	return new Promise<void>((resolve, reject) => {
-		cp.execFile(goRuntimePath, ['env', 'GOPATH', 'GOROOT', 'GOPROXY', 'GOBIN', 'GOMODCACHE'], (err, stdout, stderr) => {
-			if (err) {
+		cp.execFile(goRuntimePath,
+			['env', 'GOPATH', 'GOROOT', 'GOPROXY', 'GOBIN', 'GOMODCACHE'],
+			{ env: toolExecutionEnvironment(), cwd: getWorkspaceFolderPath() },
+			(err, stdout, stderr) => {
+			if (err || stderr) {
+				outputChannel.append(`Failed to run '${goRuntimePath} env: ${err}\n${stderr}`);
+				outputChannel.show();
+
+				vscode.window.showErrorMessage(`Failed to run '${goRuntimePath} env. The config change may not be applied correctly.`);
 				return reject();
 			}
 			const envOutput = stdout.split('\n');
diff --git a/src/goLanguageServer.ts b/src/goLanguageServer.ts
index 0ab98aa..943cdfa 100644
--- a/src/goLanguageServer.ts
+++ b/src/goLanguageServer.ts
@@ -18,11 +18,11 @@
 	CloseAction,
 	CompletionItemKind,
 	ErrorAction,
-	ExecuteCommandSignature,
 	HandleDiagnosticsSignature,
 	InitializeError,
 	LanguageClient,
 	Message,
+	ProvideCodeLensesSignature,
 	ProvideCompletionItemsSignature,
 	ProvideDocumentLinksSignature,
 	RevealOutputChannelOn,
@@ -48,8 +48,8 @@
 import { getTool, Tool } from './goTools';
 import { GoTypeDefinitionProvider } from './goTypeDefinition';
 import { getFromGlobalState, updateGlobalState } from './stateUtils';
-import { getBinPath, getCurrentGoPath, getGoConfig } from './util';
-import { getToolFromToolPath } from './utils/goPath';
+import { getBinPath, getCurrentGoPath, getGoConfig, getWorkspaceFolderPath } from './util';
+import { getToolFromToolPath } from './utils/pathUtils';
 
 interface LanguageServerConfig {
 	serverName: string;
@@ -258,34 +258,35 @@
 				},
 			},
 			middleware: {
-				provideCodeLenses: async (doc, token, next): Promise<vscode.CodeLens[]> => {
+				provideCodeLenses: async (
+					doc: vscode.TextDocument,
+					token: vscode.CancellationToken,
+					next: ProvideCodeLensesSignature
+				): Promise<vscode.CodeLens[]> => {
 					const codeLens = await next(doc, token);
 					if (!codeLens || codeLens.length === 0) {
 						return codeLens;
 					}
-					return codeLens.map((lens: vscode.CodeLens) => {
+					const goplsEnabledLens = (getGoConfig().get('overwriteGoplsMiddleware') as any)?.codelens ?? {};
+					return codeLens.reduce((lenses: vscode.CodeLens[], 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] }],
-								});
+								if (goplsEnabledLens.test) {
+									return [...lenses, lens];
+								}
+								return [...lenses, ...createTestCodeLens(lens)];
 							}
 							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] }],
-								});
+								if (goplsEnabledLens.bench) {
+									return [...lenses, lens];
+								}
+								return [...lenses, ...createBenchmarkCodeLens(lens)];
 							}
 							default: {
-								return lens;
+								return [...lenses, lens];
 							}
 						}
-					});
+					}, []);
 				},
 				handleDiagnostics: (
 					uri: vscode.Uri,
@@ -330,7 +331,16 @@
 					if (!Array.isArray(list) && list.isIncomplete && list.items.length > 1) {
 						let hardcodedFilterText = items[0].filterText;
 						if (!hardcodedFilterText) {
-							hardcodedFilterText = '';
+							// tslint:disable:max-line-length
+							// According to LSP spec,
+							// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
+							// if filterText is falsy, the `label` should be used.
+							// But we observed that's not the case.
+							// Even if vscode picked the label value, that would
+							// cause to reorder candiates, which is not ideal.
+							// Force to use non-empty `label`.
+							// https://github.com/golang/vscode-go/issues/441
+							hardcodedFilterText = items[0].label;
 						}
 						for (const item of items) {
 							item.filterText = hardcodedFilterText;
@@ -390,6 +400,49 @@
 	return c;
 }
 
+// createTestCodeLens adds the go.test.cursor and go.debug.cursor code lens
+function createTestCodeLens(lens: vscode.CodeLens): vscode.CodeLens[] {
+	// CodeLens argument signature in gopls is [fileName: string, testFunctions: string[], benchFunctions: string[]],
+	// so this needs to be deconstructured here
+	// Note that there will always only be one test function name in this context
+	if (lens.command.arguments.length < 2 || lens.command.arguments[1].length < 1) {
+		return [lens];
+	}
+	return [
+		new vscode.CodeLens(lens.range, {
+			...lens.command,
+			command: 'go.test.cursor',
+			arguments: [{ functionName: lens.command.arguments[1][0] }],
+		}),
+		new vscode.CodeLens(lens.range, {
+			title: 'debug test',
+			command: 'go.debug.cursor',
+			arguments: [{ functionName: lens.command.arguments[1][0] }],
+		}),
+	];
+}
+
+function createBenchmarkCodeLens(lens: vscode.CodeLens): vscode.CodeLens[] {
+	// CodeLens argument signature in gopls is [fileName: string, testFunctions: string[], benchFunctions: string[]],
+	// so this needs to be deconstructured here
+	// Note that there will always only be one benchmark function name in this context
+	if (lens.command.arguments.length < 3 || lens.command.arguments[2].length < 1) {
+		return [lens];
+	}
+	return [
+		new vscode.CodeLens(lens.range, {
+			...lens.command,
+			command: 'go.benchmark.cursor',
+			arguments: [{ functionName: lens.command.arguments[2][0] }],
+		}),
+		new vscode.CodeLens(lens.range, {
+			title: 'debug benchmark',
+			command: 'go.debug.cursor',
+			arguments: [{ functionName: lens.command.arguments[2][0] }],
+		}),
+	];
+}
+
 // registerUsualProviders registers the language feature providers if the language server is not enabled.
 function registerDefaultProviders(ctx: vscode.ExtensionContext) {
 	const completionProvider = new GoCompletionItemProvider(ctx.globalState);
@@ -439,7 +492,9 @@
 		e.affectsConfiguration('go.useLanguageServer') ||
 		e.affectsConfiguration('go.languageServerFlags') ||
 		e.affectsConfiguration('go.languageServerExperimentalFeatures') ||
-		e.affectsConfiguration('go.alternateTools')
+		e.affectsConfiguration('go.alternateTools') ||
+		e.affectsConfiguration('go.toolsEnvVars')
+		// TODO: Should we check http.proxy too? That affects toolExecutionEnvironment too.
 	) {
 		restartLanguageServer();
 	}
@@ -692,7 +747,9 @@
 	const execFile = util.promisify(cp.execFile);
 	let output: any;
 	try {
-		const { stdout } = await execFile(cfg.path, ['version'], { env: toolExecutionEnvironment() });
+		const env = toolExecutionEnvironment();
+		const cwd = getWorkspaceFolderPath();
+		const { stdout } = await execFile(cfg.path, ['version'], { env, cwd });
 		output = stdout;
 	} catch (e) {
 		// The "gopls version" command is not supported, or something else went wrong.
@@ -860,10 +917,10 @@
 	}
 	// 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.
+	// the range [0, 1) and checking if it is < 0.0275, for a 2.75% 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;
+	cfg.promptThisMonth = Math.random() < 0.0275;
 	if (cfg.promptThisMonth) {
 		// end is the last day of the month, day is the random day of the
 		// month on which to prompt.
diff --git a/src/goMain.ts b/src/goMain.ts
index a5abd27..4bc8a79 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -19,7 +19,7 @@
 import { GoDebugConfigurationProvider } from './goDebugConfiguration';
 import { extractFunction, extractVariable } from './goDoctor';
 import { toolExecutionEnvironment } from './goEnv';
-import { chooseGoEnvironment, disposeGoStatusBar, setEnvironmentVariableCollection } from './goEnvironmentStatus';
+import { chooseGoEnvironment, disposeGoStatusBar, offerToInstallLatestGoVersion, setEnvironmentVariableCollection } from './goEnvironmentStatus';
 import { runFillStruct } from './goFillStruct';
 import * as goGenerateTests from './goGenerateTests';
 import { goGetPackage } from './goGetPackage';
@@ -61,7 +61,7 @@
 	isGoPathSet,
 	resolvePath,
 } from './util';
-import { clearCacheForTools, envPath, fileExists, getCurrentGoRoot, setCurrentGoRoot } from './utils/goPath';
+import { clearCacheForTools, envPath, fileExists, getCurrentGoRoot, setCurrentGoRoot } from './utils/pathUtils';
 
 export let buildDiagnosticCollection: vscode.DiagnosticCollection;
 export let lintDiagnosticCollection: vscode.DiagnosticCollection;
@@ -84,6 +84,7 @@
 
 	updateGoVarsFromConfig().then(async () => {
 		suggestUpdates(ctx);
+		offerToInstallLatestGoVersion();
 		offerToInstallTools();
 		configureLanguageServer(ctx);
 
@@ -460,7 +461,7 @@
 						updateWorkspaceState(lastCoverProfilePathKey, coverProfilePath);
 					}
 					applyCodeCoverageToAllEditors(
-						coverProfilePath
+						coverProfilePath, getWorkspaceFolderPath(vscode.window.activeTextEditor.document.uri)
 					);
 				});
 		})
diff --git a/src/goModules.ts b/src/goModules.ts
index 82077ed..0fa9d81 100644
--- a/src/goModules.ts
+++ b/src/goModules.ts
@@ -11,7 +11,7 @@
 import { getTool } from './goTools';
 import { getFromGlobalState, updateGlobalState } from './stateUtils';
 import { getBinPath, getGoConfig, getGoVersion, getModuleCache } from './util';
-import { envPath, fixDriveCasingInWindows, getCurrentGoRoot } from './utils/goPath';
+import { envPath, fixDriveCasingInWindows, getCurrentGoRoot } from './utils/pathUtils';
 
 export let GO111MODULE: string;
 
diff --git a/src/goPackages.ts b/src/goPackages.ts
index 20eefef..b6fc42f 100644
--- a/src/goPackages.ts
+++ b/src/goPackages.ts
@@ -9,7 +9,7 @@
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
 import { getBinPath, getCurrentGoPath, getGoVersion, isVendorSupported } from './util';
-import { envPath, fixDriveCasingInWindows, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
+import { envPath, fixDriveCasingInWindows, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './utils/pathUtils';
 
 type GopkgsDone = (res: Map<string, PackageInfo>) => void;
 interface Cache {
@@ -46,7 +46,9 @@
 			args.push('-workDir', workDir);
 		}
 
-		const cmd = cp.spawn(gopkgsBinPath, args, { env: toolExecutionEnvironment() });
+		const env = toolExecutionEnvironment();
+		env['GOROOT'] = getCurrentGoRoot();  // https://github.com/golang/vscode-go/issues/294
+		const cmd = cp.spawn(gopkgsBinPath, args, { env, cwd: workDir });
 		const chunks: any[] = [];
 		const errchunks: any[] = [];
 		let err: any;
diff --git a/src/goSuggest.ts b/src/goSuggest.ts
index 80f3278..20ea2cb 100644
--- a/src/goSuggest.ts
+++ b/src/goSuggest.ts
@@ -27,7 +27,7 @@
 	parseFilePrelude,
 	runGodoc
 } from './util';
-import { getCurrentGoWorkspaceFromGOPATH } from './utils/goPath';
+import { getCurrentGoWorkspaceFromGOPATH } from './utils/pathUtils';
 
 function vscodeKindFromGoCodeClass(kind: string, type: string): vscode.CompletionItemKind {
 	switch (kind) {
diff --git a/src/goSymbol.ts b/src/goSymbol.ts
index 9c3bb15..4e4948d 100644
--- a/src/goSymbol.ts
+++ b/src/goSymbol.ts
@@ -10,7 +10,7 @@
 import { toolExecutionEnvironment } from './goEnv';
 import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
 import { getBinPath, getGoConfig, getWorkspaceFolderPath} from './util';
-import { getCurrentGoRoot } from './utils/goPath';
+import { getCurrentGoRoot } from './utils/pathUtils';
 import {killProcessTree} from './utils/processUtils';
 
 // Keep in sync with github.com/acroca/go-symbols'
diff --git a/src/goTools.ts b/src/goTools.ts
index 0153fe3..0e1941a 100644
--- a/src/goTools.ts
+++ b/src/goTools.ts
@@ -273,6 +273,18 @@
 		isImportant: true,
 		description: 'Go to definition & text shown on hover'
 	},
+	'gofumports': {
+		name: 'gofumports',
+		importPath: 'mvdan.cc/gofumpt/gofumports',
+		isImportant: false,
+		description: 'Formatter'
+	},
+	'gofumpt': {
+		name: 'gofumpt',
+		importPath: 'mvdan.cc/gofumpt',
+		isImportant: false,
+		description: 'Formatter'
+	},
 	'goimports': {
 		name: 'goimports',
 		importPath: 'golang.org/x/tools/cmd/goimports',
diff --git a/src/stateUtils.ts b/src/stateUtils.ts
index 7a83832..cb57157 100644
--- a/src/stateUtils.ts
+++ b/src/stateUtils.ts
@@ -26,6 +26,10 @@
 	globalState = state;
 }
 
+export function getGlobalState() {
+	return globalState;
+}
+
 export function getFromWorkspaceState(key: string, defaultValue?: any) {
 	if (!workspaceState) {
 		return defaultValue;
diff --git a/src/testUtils.ts b/src/testUtils.ts
index 99f82fd..90adc56 100644
--- a/src/testUtils.ts
+++ b/src/testUtils.ts
@@ -20,7 +20,8 @@
 	LineBuffer,
 	resolvePath
 } from './util';
-import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH, parseEnvFile } from './utils/goPath';
+import { parseEnvFile } from './utils/envUtils';
+import { envPath, expandFilePathInOutput, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH } from './utils/pathUtils';
 import { killProcessTree } from './utils/processUtils';
 
 const testOutputChannel = vscode.window.createOutputChannel('Go Tests');
@@ -269,7 +270,17 @@
 		} else {
 			args.push('-timeout', testconfig.goConfig['testTimeout']);
 			if (testconfig.applyCodeCoverage) {
+				let coverMode = testconfig.goConfig['coverMode'];
+				switch (coverMode) {
+					case 'set': case 'count': case 'atomic': break;
+					default:
+						vscode.window.showWarningMessage(
+							`go.coverMode=${coverMode} is illegal. Use 'set', 'count', atomic'`
+						);
+						coverMode = 'set';
+				}
 				args.push('-coverprofile=' + tmpCoverPath);
+				args.push('-covermode', coverMode);
 			}
 		}
 		if (testTags && testconfig.flags.indexOf('-tags') === -1) {
@@ -483,17 +494,6 @@
 	});
 }
 
-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*(\S+\.go):(\d+):/);
-		if (matches && matches[1] && !path.isAbsolute(matches[1])) {
-			lines[i] = lines[i].replace(matches[1], path.join(cwd, matches[1]));
-		}
-	}
-	return lines.join('\n');
-}
-
 /**
  * Get the test target arguments.
  *
diff --git a/src/util.ts b/src/util.ts
index 23b7f59..fa94f7b 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -24,7 +24,7 @@
 	getCurrentGoRoot,
 	getInferredGopath,
 	resolveHomeDir,
-} from './utils/goPath';
+} from './utils/pathUtils';
 import { killProcessTree } from './utils/processUtils';
 
 let userNameHash: number = 0;
@@ -340,14 +340,20 @@
 		warn(`cached Go version (${JSON.stringify(cachedGoVersion)}) is invalid, recomputing`);
 	}
 	try {
+		const env = toolExecutionEnvironment();
+		const docUri = vscode.window.activeTextEditor?.document.uri;
+		const cwd = getWorkspaceFolderPath(docUri && docUri.fsPath.endsWith('.go') ? docUri : undefined);
 		const execFile = util.promisify(cp.execFile);
-		const { stdout, stderr } = await execFile(goRuntimePath, ['version']);
+		const { stdout, stderr } = await execFile(goRuntimePath, ['version'], {env, cwd});
 		if (stderr) {
 			warn(`failed to run "${goRuntimePath} version": stdout: ${stdout}, stderr: ${stderr}`);
 			return;
 		}
 		cachedGoBinPath = goRuntimePath;
 		cachedGoVersion = new GoVersion(goRuntimePath, stdout);
+		if (!cachedGoVersion.isValid()) {
+			warn (`unable to determine version from the output of "${goRuntimePath} version": "${stdout}"`);
+		}
 	} catch (err) {
 		warn(`failed to run "${goRuntimePath} version": ${err}`);
 		return;
@@ -890,7 +896,7 @@
 	}
 }
 
-export function getWorkspaceFolderPath(fileUri?: vscode.Uri): string {
+export function getWorkspaceFolderPath(fileUri?: vscode.Uri): string|undefined {
 	if (fileUri) {
 		const workspace = vscode.workspace.getWorkspaceFolder(fileUri);
 		if (workspace) {
@@ -903,6 +909,7 @@
 	if (folders && folders.length) {
 		return fixDriveCasingInWindows(folders[0].uri.fsPath);
 	}
+	return undefined;
 }
 
 export function makeMemoizedByteOffsetConverter(buffer: Buffer): (byteOffset: number) => number {
diff --git a/src/utils/envUtils.ts b/src/utils/envUtils.ts
new file mode 100644
index 0000000..bdb8cf4
--- /dev/null
+++ b/src/utils/envUtils.ts
@@ -0,0 +1,56 @@
+/*---------------------------------------------------------
+ * 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.
+ *--------------------------------------------------------*/
+
+'use strict';
+
+import fs = require('fs');
+
+function stripBOM(s: string): string {
+	if (s && s[0] === '\uFEFF') {
+		s = s.substr(1);
+	}
+	return s;
+}
+
+/**
+ * returns the environment variable collection created by parsing the given .env file.
+ */
+export function parseEnvFile(envFilePath: string): { [key: string]: string } {
+	const env: { [key: string]: string } = {};
+	if (!envFilePath) {
+		return env;
+	}
+
+	try {
+		const buffer = stripBOM(fs.readFileSync(envFilePath, 'utf8'));
+		buffer.split('\n').forEach((line) => {
+			const r = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
+			if (r !== null) {
+				let value = r[2] || '';
+				if (value.length > 0 && value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
+					value = value.replace(/\\n/gm, '\n');
+				}
+				env[r[1]] = value.replace(/(^['"]|['"]$)/g, '');
+			}
+		});
+		return env;
+	} catch (e) {
+		throw new Error(`Cannot load environment variables from file ${envFilePath}`);
+	}
+}
+
+export function parseEnvFiles(envFiles: string[]|string): { [key: string]: string } {
+	const fileEnvs = [];
+	if (typeof envFiles === 'string') {
+		fileEnvs.push(parseEnvFile(envFiles));
+	}
+	if (Array.isArray(envFiles)) {
+		envFiles.forEach((envFile) => {
+			fileEnvs.push(parseEnvFile(envFile));
+		});
+	}
+	return Object.assign({}, ...fileEnvs);
+}
diff --git a/src/utils/goPath.ts b/src/utils/pathUtils.ts
similarity index 89%
rename from src/utils/goPath.ts
rename to src/utils/pathUtils.ts
index 6ad1b1a..ab3be8f 100644
--- a/src/utils/goPath.ts
+++ b/src/utils/pathUtils.ts
@@ -158,37 +158,6 @@
 	return inputPath.startsWith('~') ? path.join(os.homedir(), inputPath.substr(1)) : inputPath;
 }
 
-export function stripBOM(s: string): string {
-	if (s && s[0] === '\uFEFF') {
-		s = s.substr(1);
-	}
-	return s;
-}
-
-export function parseEnvFile(envFilePath: string): { [key: string]: string } {
-	const env: { [key: string]: any } = {};
-	if (!envFilePath) {
-		return env;
-	}
-
-	try {
-		const buffer = stripBOM(fs.readFileSync(envFilePath, 'utf8'));
-		buffer.split('\n').forEach((line) => {
-			const r = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
-			if (r !== null) {
-				let value = r[2] || '';
-				if (value.length > 0 && value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
-					value = value.replace(/\\n/gm, '\n');
-				}
-				env[r[1]] = value.replace(/(^['"]|['"]$)/g, '');
-			}
-		});
-		return env;
-	} catch (e) {
-		throw new Error(`Cannot load environment variables from file ${envFilePath}`);
-	}
-}
-
 // Walks up given folder path to return the closest ancestor that has `src` as a child
 export function getInferredGopath(folderPath: string): string {
 	if (!folderPath) {
@@ -258,3 +227,19 @@
 	}
 	return tool;
 }
+
+/**
+ * Returns output with relative filepaths expanded using the provided directory
+ * @param output
+ * @param cwd
+ */
+export 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*(\S+\.go):(\d+):/);
+		if (matches && matches[1] && !path.isAbsolute(matches[1])) {
+			lines[i] = lines[i].replace(matches[1], path.join(cwd, matches[1]));
+		}
+	}
+	return lines.join('\n');
+}
diff --git a/test/gopls/extension.test.ts b/test/gopls/extension.test.ts
index 7f5104c..25d82bf 100644
--- a/test/gopls/extension.test.ts
+++ b/test/gopls/extension.test.ts
@@ -6,9 +6,34 @@
 import cp = require('child_process');
 import * as fs from 'fs-extra';
 import * as path from 'path';
+import sinon = require('sinon');
 import * as vscode from 'vscode';
 import { extensionId } from '../../src/const';
 
+// 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());
+	}
+}
+
 // Env is a collection of test related variables
 // that define the test environment such as vscode workspace.
 class Env {
@@ -28,6 +53,8 @@
 
 	public extension: vscode.Extension<any>;
 
+	private fakeOutputChannel: FakeOutputChannel;
+
 	constructor(projectDir: string) {
 		if (!projectDir) {
 			assert.fail('project directory cannot be determined');
@@ -35,6 +62,7 @@
 		this.workspaceDir = path.resolve(projectDir, 'test/gopls/testfixtures/src/workspace');
 		this.fixturesRoot = path.resolve(projectDir, 'test/fixtures');
 		this.extension = vscode.extensions.getExtension(extensionId);
+		this.fakeOutputChannel = new FakeOutputChannel();
 
 		// Ensure the vscode extension host is configured as expected.
 		const workspaceFolder = path.resolve(vscode.workspace.workspaceFolders[0].uri.fsPath);
@@ -43,7 +71,18 @@
 		}
 	}
 
+	public flushTrace(print: boolean) {
+		if (print) {
+			console.log(this.fakeOutputChannel.toString());
+			this.fakeOutputChannel.clear();
+		}
+	}
+
 	public async setup() {
+		// stub the language server's output channel to intercept the trace.
+		sinon.stub(vscode.window, 'createOutputChannel')
+			.callThrough().withArgs('gopls (server)').returns(this.fakeOutputChannel);
+
 		await this.reset();
 		await this.extension.activate();
 		await sleep(2000);  // allow the language server to start.
@@ -52,6 +91,10 @@
 		// but couldn't make it working yet.
 	}
 
+	public teardown() {
+		sinon.restore();
+	}
+
 	public async reset(fixtureDirName?: string) {  // name of the fixtures subdirectory to use.
 		try {
 			// clean everything except the .gitignore file
@@ -97,6 +140,13 @@
 	});
 	suiteTeardown(async () => { await env.reset(); });
 
+	this.afterEach(function () {
+		// Note: this shouldn't use () => {...}. Arrow functions do not have 'this'.
+		// I don't know why but this.currentTest.state does not have the expected value when
+		// used with teardown.
+		env.flushTrace(this.currentTest.state === 'failed');
+	});
+
 	test('HoverProvider', async () => {
 		await env.reset('gogetdocTestData');
 		const { uri, doc } = await env.openDoc('test.go');
@@ -139,7 +189,7 @@
 		await env.reset('gogetdocTestData');
 		const { uri } = await env.openDoc('test.go');
 		const testCases: [string, vscode.Position, string][] = [
-			['fmt.<>', new vscode.Position(19, 5), 'Formatter'],
+			['fmt.P<>', new vscode.Position(19, 6), 'Print'],
 		];
 		for (const [name, position, wantFilterText] of testCases) {
 			let list: vscode.CompletionList<vscode.CompletionItem>;
diff --git a/test/integration/extension.test.ts b/test/integration/extension.test.ts
index d16d35b..1b42970 100644
--- a/test/integration/extension.test.ts
+++ b/test/integration/extension.test.ts
@@ -40,7 +40,7 @@
 } from '../../src/util';
 
 suite('Go Extension Tests', function () {
-	this.timeout(10000);
+	this.timeout(15000);
 
 	const dummyCancellationSource = new vscode.CancellationTokenSource();
 
diff --git a/test/integration/goDebugConfiguration.test.ts b/test/integration/goDebugConfiguration.test.ts
new file mode 100644
index 0000000..3d363fa
--- /dev/null
+++ b/test/integration/goDebugConfiguration.test.ts
@@ -0,0 +1,130 @@
+import assert = require('assert');
+import fs = require('fs');
+import os = require('os');
+import path = require('path');
+import sinon = require('sinon');
+import vscode = require('vscode');
+import { GoDebugConfigurationProvider } from '../../src/goDebugConfiguration';
+import goEnv = require('../../src/goEnv');
+import { updateGoVarsFromConfig } from '../../src/goInstallTools';
+import { getCurrentGoPath, rmdirRecursive } from '../../src/util';
+
+suite('Debug Environment Variable Merge Test', () => {
+	const debugConfigProvider = new GoDebugConfigurationProvider();
+
+	suiteSetup(async () => {
+		await updateGoVarsFromConfig();
+
+		// Set up the test fixtures.
+		const fixtureSourcePath = path.join(__dirname, '..', '..', '..', 'test', 'fixtures');
+		const filePath = path.join(fixtureSourcePath, 'baseTest', 'test.go');
+		await vscode.workspace.openTextDocument(vscode.Uri.file(filePath));
+	});
+
+	suiteTeardown(() => {
+		vscode.commands.executeCommand('workbench.action.closeActiveEditor');
+	});
+
+	let sandbox: sinon.SinonSandbox;
+	let tmpDir = '';
+	const toolExecutionEnv: NodeJS.Dict<string> = {};
+	setup(() => {
+		tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'godebugconfig_test'));
+		sandbox = sinon.createSandbox();
+
+	});
+
+	teardown(() => {
+		sandbox.restore();
+		rmdirRecursive(tmpDir);
+	});
+
+	interface Input {
+		env?: { [key: string]: any };
+		envFile?: string|string[];
+		toolsEnv?: { [key: string]: any};
+	}
+
+	function runTest(input: Input,	expected: { [key: string]: any}) {
+		sandbox.stub(goEnv, 'toolExecutionEnvironment').returns(input.toolsEnv || {});
+		const config = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(undefined, {
+			type: 'go',
+			name: 'Launch',
+			request: 'launch',
+			env: input.env,
+			envFile: input.envFile,
+		});
+
+		const actual = config.env;
+		assert.deepStrictEqual(actual, expected);
+	}
+
+	test('works with empty launchArgs', () => {
+		runTest({}, {});
+	});
+
+	test('toolsEnvVars is propagated', () => {
+		const toolsEnv = {
+			GOPATH: '/gopath',
+			GOOS: 'valueFromToolsEnv'};
+
+		runTest({toolsEnv}, {
+			GOPATH: '/gopath',
+			GOOS: 'valueFromToolsEnv'});
+	});
+
+	test('preserves settings from launchArgs.env', () => {
+		const env = {GOPATH: 'valueFromEnv', GOOS: 'valueFromEnv2'};
+		runTest({env}, {
+			GOPATH: 'valueFromEnv',
+			GOOS: 'valueFromEnv2'});
+	});
+
+	test('preserves settings from launchArgs.envFile', () => {
+		const envFile = path.join(tmpDir, 'env');
+		fs.writeFileSync(envFile, 'GOPATH=valueFromEnvFile');
+		runTest({envFile}, {GOPATH: 'valueFromEnvFile'});
+	});
+
+	test('launchArgs.env overwrites launchArgs.envFile', () => {
+		const env = {SOMEVAR1: 'valueFromEnv'};
+		const envFile = path.join(tmpDir, 'env');
+		fs.writeFileSync(envFile, [
+			'SOMEVAR1=valueFromEnvFile1',
+			'SOMEVAR2=valueFromEnvFile2'].join('\n'));
+
+		runTest({ env, envFile }, {
+			SOMEVAR1: 'valueFromEnv',
+			SOMEVAR2: 'valueFromEnvFile2'});
+	});
+
+	test('launchArgs.env overwrites toolsEnvVar', () => {
+		const toolsEnv = {
+			GOPATH: '/gopath',
+			SOMEVAR1: 'valueFromToolsEnvVar1',
+			SOMEVAR2: 'valueFromToolsEnvVar2'
+		};
+
+		const env = {SOMEVAR1: 'valueFromEnv'};
+		runTest({ env, toolsEnv }, {
+			GOPATH: '/gopath',
+			SOMEVAR1: 'valueFromEnv',
+			SOMEVAR2: 'valueFromToolsEnvVar2'});
+	});
+
+	test('launchArgs.envFile overwrites toolsEnvVar', () => {
+		const toolsEnv = {
+			GOPATH: '/gopath',
+			SOMEVAR1: 'valueFromToolsEnvVar1',
+			SOMEVAR2: 'valueFromToolsEnvVar2'
+		};
+		const envFile = path.join(tmpDir, 'env');
+		fs.writeFileSync(envFile, [
+			'SOMEVAR2=valueFromEnvFile2'].join('\n'));
+
+		runTest({ toolsEnv, envFile }, {
+			GOPATH: '/gopath',
+			SOMEVAR1: 'valueFromToolsEnvVar1',
+			SOMEVAR2: 'valueFromEnvFile2'});
+	});
+});
diff --git a/test/integration/goversion.test.ts b/test/integration/goversion.test.ts
new file mode 100644
index 0000000..758f3a1
--- /dev/null
+++ b/test/integration/goversion.test.ts
@@ -0,0 +1,132 @@
+/*---------------------------------------------------------
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+import * as assert from 'assert';
+import { describe, it } from 'mocha';
+import * as sinon from 'sinon';
+import * as vscode from 'vscode';
+
+import moment = require('moment');
+import semver = require('semver');
+import WebRequest = require('web-request');
+
+import {
+	getLatestGoVersions,
+	GoEnvironmentOption,
+	latestGoVersionKey,
+} from '../../src/goEnvironmentStatus';
+import {
+	getGlobalState,
+	setGlobalState,
+	updateGlobalState,
+} from '../../src/stateUtils';
+import { MockMemento } from '../mocks/MockMemento';
+
+describe('#getLatestGoVersion()', function () {
+	this.timeout(40000);
+	let sandbox: sinon.SinonSandbox | undefined;
+	let defaultMemento: vscode.Memento;
+	const webrequest = sinon.mock(WebRequest);
+	const mmnt = sinon.mock(moment);
+
+	const now = 100000000;
+	const oneday = 60 * 60 * 24 * 1000; // 24 hours in milliseconds
+
+	this.beforeAll(async () => {
+		defaultMemento = getGlobalState();
+	});
+	this.afterAll(async () => {
+		setGlobalState(defaultMemento);
+	});
+
+	this.beforeEach(() => {
+		sandbox = sinon.createSandbox();
+		setGlobalState(new MockMemento());
+
+		webrequest.expects('json')
+			.withArgs('https://golang.org/dl/?mode=json')
+			.returns([
+				{
+					version: 'go1.15.1',
+					stable: true,
+				},
+				{
+					version: 'go1.14.2',
+					stable: true,
+				},
+			]);
+
+		mmnt.expects('now')
+			.returns(now);
+
+	});
+
+	this.afterEach(async () => {
+		sandbox.restore();
+	});
+
+	it('should get latest go versions from golang.org/dl with empty cache', async () => {
+		const results = await getLatestGoVersions();
+		const want = [
+				{label: 'Go 1.15.1', binpath: 'go get golang.org/dl/go1.15.1'},
+				{label: 'Go 1.14.2', binpath: 'go get golang.org/dl/go1.14.2'},
+		];
+
+		assert(results.length === want.length);
+		for (let i = 0; i < results.length; i ++) {
+			assert(results[i].label === want[i].label);
+			assert(results[i].binpath === want[i].binpath);
+		}
+	});
+
+	const cacheVersions = [
+		new GoEnvironmentOption('go get golang.org/dl/go1.14.7', 'Go 1.14.7'),
+		new GoEnvironmentOption('go get golang.org/dl/go1.13.2', 'Go 1.13.2'),
+	];
+
+	it('should get latest go versions from golang.org/dl with timed out cache', async () => {
+		// add a timed out cache entry
+		await updateGlobalState(latestGoVersionKey, {
+			timestamp: now - (oneday + 1), // more than one day ago
+			goVersions: cacheVersions,
+		});
+
+		// run test
+		const results = await getLatestGoVersions();
+		const want = [
+				{label: 'Go 1.15.1', binpath: 'go get golang.org/dl/go1.15.1'},
+				{label: 'Go 1.14.2', binpath: 'go get golang.org/dl/go1.14.2'},
+		];
+
+		// check results
+		assert(results.length === want.length);
+		for (let i = 0; i < results.length; i ++) {
+			assert(results[i].label === want[i].label);
+			assert(results[i].binpath === want[i].binpath);
+		}
+	});
+
+	it('should get latest go versions from cache', async () => {
+		// add a valid cache entry
+		await updateGlobalState(latestGoVersionKey, {
+			timestamp: now - (oneday - 100), // less than one day ago
+			goVersions: cacheVersions,
+		});
+
+		// run test
+		const results = await getLatestGoVersions();
+		const want = [
+				{label: 'Go 1.14.7', binpath: 'go get golang.org/dl/go1.14.7'},
+				{label: 'Go 1.13.2', binpath: 'go get golang.org/dl/go1.13.2'},
+		];
+
+		// check results
+		assert(results.length === want.length);
+		for (let i = 0; i < results.length; i ++) {
+			assert(results[i].label === want[i].label);
+			assert(results[i].binpath === want[i].binpath);
+		}
+	});
+});
diff --git a/test/integration/install.test.ts b/test/integration/install.test.ts
index e61f606..9a3732e 100644
--- a/test/integration/install.test.ts
+++ b/test/integration/install.test.ts
@@ -17,7 +17,7 @@
 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';
+import { correctBinname } from '../../src/utils/pathUtils';
 
 suite('Installation Tests', function () {
 	// Disable timeout when we are running slow tests.
diff --git a/test/integration/statusbar.test.ts b/test/integration/statusbar.test.ts
index 8396db6..10d1dcf 100644
--- a/test/integration/statusbar.test.ts
+++ b/test/integration/statusbar.test.ts
@@ -25,7 +25,7 @@
 import { updateGoVarsFromConfig } from '../../src/goInstallTools';
 import { getWorkspaceState, setWorkspaceState } from '../../src/stateUtils';
 import ourutil = require('../../src/util');
-import { getCurrentGoRoot } from '../../src/utils/goPath';
+import { getCurrentGoRoot } from '../../src/utils/pathUtils';
 import { MockMemento } from '../mocks/MockMemento';
 
 describe('#initGoStatusBar()', function () {
diff --git a/tools/generate.go b/tools/generate.go
index f93ce88..4afaca6 100644
--- a/tools/generate.go
+++ b/tools/generate.go
@@ -43,6 +43,7 @@
 	Default     interface{} `json:"default,omitempty"`
 	Description string      `json:"description,omitempty"`
 	Type        interface{} `json:"type,omitempty"`
+	Enum        []string    `json:"enum,omitempty"`
 }
 
 func main() {
@@ -116,13 +117,56 @@
 			Default:     p.Default,
 			Description: p.Description,
 			Type:        p.Type,
+			Enum:        p.Enum,
 		})
 	}
 	sort.Slice(properties, func(i, j int) bool {
 		return properties[i].Name < properties[j].Name
 	})
+	indent := "&nbsp;&nbsp;"
 	for i, p := range properties {
 		b.WriteString(fmt.Sprintf("### `%s`\n\n%s", p.Name, p.Description))
+		if p.Enum != nil {
+			b.WriteString(fmt.Sprintf("\n\nAllowed Values:`%v`", p.Enum))
+		}
+		switch p.Type {
+		case "object":
+			x, ok := p.Default.(map[string]interface{})
+			// do nothing if it is nil
+			if ok && len(x) > 0 {
+				keys := []string{}
+				for k := range x {
+					keys = append(keys, k)
+				}
+				sort.Strings(keys)
+				b.WriteString(fmt.Sprintf("\n\nDefault:{<br/>\n"))
+				for _, k := range keys {
+					v := x[k]
+					output := fmt.Sprintf("%v", v)
+					if str, ok := v.(string); ok {
+						output = fmt.Sprintf("%q", str)
+					}
+					// if v is an empty string, nothing gets printed
+					// if v is a map/object, it is printed on one line
+					// this could be improved at the cost of more code
+					b.WriteString(fmt.Sprintf("%s`\"%s\": %s`,<br/>\n", indent, k, output))
+				}
+				b.WriteString("    }\n")
+			}
+		case "boolean", "string", "number":
+			b.WriteString(fmt.Sprintf("\n\nDefault: `%v`", p.Default))
+		case "array":
+			x := p.Default.([]interface{})
+			if len(x) > 0 {
+				b.WriteString(fmt.Sprintf("\n\nDefault: `%v`", p.Default))
+			}
+		default:
+			if _, ok := p.Type.([]interface{}); ok {
+				b.WriteString(fmt.Sprintf("\n\nefault: `%v`", p.Default))
+				break
+			}
+			log.Fatalf("implement default when p.Type is %q in %#v %T", p.Type, p, p.Default)
+		}
 		if i != len(properties)-1 {
 			b.WriteString("\n\n")
 		}