[release] prepare v0.35.2 release

073136db3 CHANGELOG.md: update for v0.35.2
8e5969fe0 src/goToolsInformation: pick up gopls release
55683f5fd src/goToolsInformation: update hardcoded gopls version
886decb92 tools: generate inlay hints settings from gopls settings
7467f2672 README: edit Quickstart and Features section for clarity
e4a94d253 .github/workflows: fix wiki.yml
84fe4e7da .github/workflows: add go1.19rc2 to long/smoke tests
d11476774 commands: add go.goroot command
484a3ba45 test/gopls/vulncheck: add logging for viewer test failure
5bf723727 test/integration/extension: disable all "Test Completion Snippets *"
f4fcd7ad6 test/integration/goDebug: make invalid flag test faster
cbecbf8a2 test/integration/goExplorer: fix 'env tree items' test
e91d0e84f test/integration/install: stub languageserver restart command
a6729ef68 test/integration/goDebug: speed up setUpRemoteProgram
78c2fac41 Revert "src/goInstallTools: show error if go.languageserver.restart fails"
aa3de7f87 test/integration: catch failed await in lint test
b90e57e68 .vscode/launch.json: remove outFiles and deprecated attributes
d2afd7d70 src/goTest/resolve: fix nested packageDisplayMode handling on win32
47f6dfae8 test/integration/goTest: fix populateModulePathCache
1adebbbee test/integration/goTest.run: increase discover&run timeout
ffae00196 test/integration/goDebug: skip redundant tests in withConsole mode
c90973864 test/integration/goDebug: skip legacy da testing on windows
a39ef240a package.json: remove tslint
1dfac1444 .github/workflows: drop 1.15 from long test
944b1d477 .github/workflows: remove 'stable' unnecessary in setup-go@v3
21bbd7be8 test: skip flaky debug test
305bea73a .github/workflows: upgrade setup-go to v3 and enable caching
b6aad3e65 .github/workflows: upgrade checkout/node workflows to v3
9bb57d8ac test/integration: skip tests broken on windows
b012df443 src/goInstallTools: show error if go.languageserver.restart fails
c8598b13c test/integration/goDebug: catch any error while cleaning up
8f6cb5dee goGenerateTests: resolve config file path
aba30790d CHANGELOG.md: add v0.35.1 description
bfdb91c89 package.json: update dev version
4bd0f3323 docs/debugging.md: fix missing "" in example

Change-Id: I7504ae5e6d9c40009ad0feb6317f7f1000987012
diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml
index 18af3bf..1da361c 100644
--- a/.github/workflows/release-nightly.yml
+++ b/.github/workflows/release-nightly.yml
@@ -18,17 +18,20 @@
 
     steps:
       - name: Clone repository
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
 
       - name: Setup Node
-        uses: actions/setup-node@v1
+        uses: actions/setup-node@v3
         with:
-          node-version: '14.x'
+         node-version: '16'
+         cache: 'npm'
 
       - name: Setup Go
-        uses: actions/setup-go@v2
+        uses: actions/setup-go@v3
         with:
-         go-version: '1.18'
+         go-version: '1.19'
+         check-latest: true
+         cache: true
 
       - name: Install dependencies
         run: npm ci
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f2156ad..46bba60 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -37,8 +37,14 @@
     if: github.repository == 'golang/vscode-go'
 
     steps:
-      - name: checkout code
-        uses: actions/checkout@v2
+      - name: Clone repository
+        uses: actions/checkout@v3
+
+      - name: Setup Node
+        uses: actions/setup-node@v3
+        with:
+          node-version: '16'
+          cache: 'npm'
 
       - name: get release version
         id: release_version
diff --git a/.github/workflows/test-long-all.yml b/.github/workflows/test-long-all.yml
index 611f636..0a39a63 100644
--- a/.github/workflows/test-long-all.yml
+++ b/.github/workflows/test-long-all.yml
@@ -17,22 +17,24 @@
       matrix:
         os: [ubuntu-latest, windows-latest, macos-latest]
         version: ['stable', 'insiders']
-        go: ['1.15', '1.16', '1.17', '1.18']
+        go: ['1.16', '1.17', '1.18', '1.19']
 
     steps:
       - name: Clone repository
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
 
       - name: Setup Node
-        uses: actions/setup-node@v1
+        uses: actions/setup-node@v3
         with:
-          node-version: '14.x'
+         node-version: '16'
+         cache: 'npm'
 
       - name: Setup Go
-        uses: actions/setup-go@v2
+        uses: actions/setup-go@v3
         with:
          go-version: ${{ matrix.go }}
-         stable: '!contains(${{ matrix.go }}, "beta") && !contains(${{ matrix.go }}, "rc")'
+         check-latest: true
+         cache: true
 
       - name: Install dependencies
         run: npm ci
diff --git a/.github/workflows/test-long.yml b/.github/workflows/test-long.yml
index aee3b90..79b783d 100644
--- a/.github/workflows/test-long.yml
+++ b/.github/workflows/test-long.yml
@@ -16,22 +16,24 @@
       matrix:
         os: [ubuntu-latest, windows-latest] # TODO: reenable macos-latest
         version: ['stable']
-        go: ['1.15', '1.16', '1.17', '1.18']
+        go: ['1.16', '1.17', '1.18', '1.19']
 
     steps:
       - name: Clone repository
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
 
       - name: Setup Node
-        uses: actions/setup-node@v1
+        uses: actions/setup-node@v3
         with:
-          node-version: '14.x'
+         node-version: '16'
+         cache: 'npm'
 
       - name: Setup Go
-        uses: actions/setup-go@v2
+        uses: actions/setup-go@v3
         with:
          go-version: ${{ matrix.go }}
-         stable: '!contains(${{ matrix.go }}, "beta") && !contains(${{ matrix.go }}, "rc")'
+         check-latest: true
+         cache: true
 
       - name: Install dependencies
         run: npm ci
diff --git a/.github/workflows/test-smoke.yml b/.github/workflows/test-smoke.yml
index 1bfc8ed..2c24d20 100644
--- a/.github/workflows/test-smoke.yml
+++ b/.github/workflows/test-smoke.yml
@@ -14,22 +14,25 @@
     strategy:
       fail-fast: false
       matrix:
-        os: [ubuntu-latest]
+        os: [ubuntu-latest, windows-latest]
         version: ['stable']
 
     steps:
       - name: Clone repository
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
 
       - name: Setup Node
-        uses: actions/setup-node@v1
+        uses: actions/setup-node@v3
         with:
-          node-version: '14.x'
+         node-version: '16'
+         cache: 'npm'
 
       - name: Setup Go
-        uses: actions/setup-go@v2
+        uses: actions/setup-go@v3
         with:
-         go-version: '1.18'
+         go-version: '1.19.0'
+         check-latest: true
+         cache: true
 
       - name: Install dependencies
         run: npm ci
diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml
index d4fc608..45ed20d 100644
--- a/.github/workflows/wiki.yml
+++ b/.github/workflows/wiki.yml
@@ -6,6 +6,7 @@
     branches: [ master ]
     paths:
       - 'docs/**'
+      - '.github/workflows/wiki.yml'
 
 # A workflow run is made up of one or more jobs that can run sequentially or in parallel
 permissions:
@@ -32,7 +33,13 @@
           repository: ${{github.repository}}.wiki
           path: wiki
       - name: Setup Go
-        uses: actions/setup-go@v2
+        uses: actions/setup-go@v3
+        with:
+          go-version: '1.19'
+          check-latest: true
+          cache: true
+          cache-dependency-path: '**/go.sum'
+
       - name: Push to wiki
         run: |
           cd vscode-go
diff --git a/.vscode/launch.json b/.vscode/launch.json
index ab3634d..3411a6f 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -22,7 +22,6 @@
 			"outFiles": [
                 "${workspaceFolder}/dist/**/*.js"
             ],
-			"stopOnEntry": false,
 			"sourceMaps": true,
 			"smartStep": true,
 			"preLaunchTask": "npm: bundle-dev",
@@ -33,7 +32,6 @@
 		{
 			"name": "Launch as server",
 			"type": "node",
-			"protocol": "inspector",
 			"request": "launch",
 			"program": "${workspaceFolder}/dist/debugAdapter.js",
 			"args": [
@@ -64,14 +62,9 @@
 				"VSCODE_GO_IN_TEST": "1",  // Disable code that shouldn't be used in test
 				"MOCHA_TIMEOUT": "999999",
 			},
-			"stopOnEntry": false,
 			"sourceMaps": true,
 			"smartStep": true,
-			"outFiles": [
-				"${workspaceFolder}/out/**/*.js",
-				"${workspaceFolder}/out/test/**/*.js"
-			],
-			"preLaunchTask": "npm: watch"
+			"preLaunchTask": "npm: watch",
 		},
 		{
 			"name": "Launch Extension Tests with Gopls",
@@ -89,12 +82,7 @@
 			"env": {
 				"VSCODE_GO_IN_TEST": "1"  // Disable code that shouldn't be used in test
 			},
-			"stopOnEntry": false,
 			"sourceMaps": true,
-			"outFiles": [
-				"${workspaceFolder}/out/**/*.js",
-				"${workspaceFolder}/out/test/**/*.js"
-			],
 			"preLaunchTask": "npm: watch",
 		},
 		{
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea5e763..7d29819 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,14 @@
+## v0.35.2 - 15 Aug, 2022
+A list of all issues and changes can be found in the [v0.35.2 milestone](https://github.com/golang/vscode-go/milestone/51) and [commit history](https://github.com/golang/vscode-go/compare/v0.35.1...v0.35.2).
+
+### Changes
+
+This release includes a new [go.goroot command](https://github.com/golang/vscode-go/issues/2379), [fixes](https://github.com/golang/vscode-go/issues/2342) to the `Generate Tests` commands, and improvements for windows users.
+
+### Thanks
+
+Thank you for your contribution, @OrBin, @Ras96, @hyangah, @jamalcarvalho, and @suzmue!
+
 ## v0.35.1 - 19 July, 2022
 
 A list of all issues and changes can be found in the [v0.35.1 milestone](https://github.com/golang/vscode-go/milestone/50) and [commit history](https://github.com/golang/vscode-go/compare/v0.35.0...v0.35.1).
diff --git a/README.md b/README.md
index a96896f..358dfbd 100644
--- a/README.md
+++ b/README.md
@@ -24,17 +24,22 @@
 Whether you are new to Go or an experienced Go developer, we hope this
 extension fits your needs and enhances your development experience.
 
-* **Step 1.** If you haven't done so already, install [Go](https://golang.org)
-  and the [VS Code Go extension].
-  * [Go installation guide]. This extension works best with Go 1.14+.
-  * [Managing extensions in VS Code].
-* **Step 2.** To activate the extension, open any directory or workspace
-  containing Go code. Once activated, the [Go status bar](https://github.com/golang/vscode-go/wiki/ui) will
-  appear in the bottom left corner of the window and show the recognized Go
-  version.
-* **Step 3.** The extension depends on [a set of extra command-line tools](#tools).
-  If they are missing, the extension will show the "⚠️ Analysis Tools Missing"
-  warning. Click the notification to complete the installation.
+1.  Install [Go](https://golang.org) 1.14 or newer if you haven't already.
+
+1.  Install the [VS Code Go extension].
+
+1.  Open any directory or workspace containing Go code to automatically activate
+    the extension. The
+    [Go status bar](https://github.com/golang/vscode-go/wiki/ui) appears in the
+    bottom left corner of the window and displays your Go version.
+
+1.  The extension depends on `go`, `gopls`, `dlv` and other optional tools. If
+    any of the dependencies are missing, the ⚠️ `Analysis Tools Missing` warning
+    is displayed. Click on the warning to download dependencies.
+
+    See the
+    [tools documentation](https://github.com/golang/vscode-go/wiki/tools) for a
+    complete list of tools the extension depends on.
 
 <p align="center">
 <img src="docs/images/installtools.gif" width=75%>
@@ -44,23 +49,32 @@
 
 You are ready to Go :-) &nbsp;&nbsp; πŸŽ‰πŸŽ‰πŸŽ‰
 
-Please be sure to learn more about the many [features](#features) of this
-extension, as well as how to [customize](#customization) them. Take a look at
-[Troubleshooting](https://github.com/golang/vscode-go/wiki/troubleshooting) and [Help](#ask-for-help) for further
-guidance.
+## What's next
+
+* Explore more [features](#features) of the VS Code Go extension.
+* Learn how to [customize](#customization) your settings.
+* Solve issues with
+  [Troubleshooting](https://github.com/golang/vscode-go/wiki/troubleshooting).
+* [file an issue](https://github.com/golang/vscode-go/issues/new/choose) for
+  problems with the extension.
+* Start a [GitHub discussion](https://github.com/golang/vscode-go/discussions)
+  or get help on [Stack Overflow].
 
 If you are new to Go, [this article](https://golang.org/doc/code.html) provides
 the overview on Go code organization and basic `go` commands. Watch ["Getting
 started with VS Code Go"] for an explanation of how to build your first Go
 application using VS Code Go.
 
-## Features
+## Feature highlights
 
-This extension provides many features, including [IntelliSense],
-[code navigation], and [code editing] support. It also shows [diagnostics] as
-you work and provides enhanced support for [testing] and [debugging] your
-programs. See the [full feature breakdown] for more details and to learn how to
-tune its behavior.
+* [IntelliSense] - Results appear for symbols as you type.
+* [Code navigation] - Jump to or peek at a symbol's declaration.
+* [Code editing] - Support for saved snippets, formatting and code organization,
+  and automatic organization of imports.
+* [Diagnostics] -  Build, vet, and lint errors shown as you type or on save.
+* Enhanced support for [testing] and [debugging]
+
+See the [full feature breakdown] for more details.
 
 <p align=center>
 <img src="docs/images/completion-signature-help.gif" width=75%>
@@ -182,8 +196,8 @@
 [Go installation guide]: https://golang.org/doc/install
 ["Getting started with VS Code Go"]: https://youtu.be/1MXIGYrMk80
 [IntelliSense]: https://github.com/golang/vscode-go/wiki/features#intellisense
-[code navigation]: https://github.com/golang/vscode-go/wiki/features#code-navigation
-[code editing]: https://github.com/golang/vscode-go/wiki/features#code-editing
+[Code navigation]: https://github.com/golang/vscode-go/wiki/features#code-navigation
+[Code editing]: https://github.com/golang/vscode-go/wiki/features#code-editing
 [diagnostics]: https://github.com/golang/vscode-go/wiki/features#diagnostics
 [testing]: https://github.com/golang/vscode-go/wiki/features#run-and-test-in-the-editor
 [debugging]: https://github.com/golang/vscode-go/wiki/debugging#features
diff --git a/docs/commands.md b/docs/commands.md
index fede59f..b525b85 100644
--- a/docs/commands.md
+++ b/docs/commands.md
@@ -27,6 +27,10 @@
 
 See the currently set GOPATH.
 
+### `Go: Current GOROOT`
+
+See the currently set GOROOT.
+
 ### `Go: Locate Configured Go Tools`
 
 List all the Go tools being used by this extension along with their locations.
diff --git a/docs/debugging-legacy.md b/docs/debugging-legacy.md
index f196221..6af77db 100644
--- a/docs/debugging-legacy.md
+++ b/docs/debugging-legacy.md
@@ -143,7 +143,7 @@
 
 ### Specifying other build flags
 
-The flags specified in `buildFlags` and `env.GOFLAGS` are passed to the Go compiler when building your program for debugging. Delve adds `-gcflags='all=-N -l'` to the list of build flags to disable optimizations. User specified buildFlags conflict with this setting, so the extension removes them ([Issue #117](https://github.com/golang/vscode-go/issues/117)). If you wish to debug a program using custom `-gcflags`, build the program using `go build` and launch using `exec` mode:
+The flags specified in `buildFlags` and `env.GOFLAGS` are passed to the Go compiler when building your program for debugging. Delve adds `-gcflags=all="-N -l"` to the list of build flags to disable optimizations. User specified buildFlags conflict with this setting, so the extension removes them ([Issue #117](https://github.com/golang/vscode-go/issues/117)). If you wish to debug a program using custom `-gcflags`, build the program using `go build` and launch using `exec` mode:
 
 ```json
 {
diff --git a/docs/debugging.md b/docs/debugging.md
index bd53164..37f5b42 100644
--- a/docs/debugging.md
+++ b/docs/debugging.md
@@ -568,7 +568,7 @@
 $ dlv dap --listen=:12345
 ```
 
-Use the following `launch` configuration to tell `dlv` to execute a binary precompiled with `go build -gcflags='all=-N -l'`:
+Use the following `launch` configuration to tell `dlv` to execute a binary precompiled with `go build -gcflags=all="-N -l"`:
 
 ```json5
 {
@@ -581,7 +581,7 @@
   "mode": "exec",
   "program": "/absolute/path/to/remote/workspace/program/executable",
   "substitutePath": [
-      { "from": ${workspaceFolder}, "to": "/path/to/remote/workspace" },
+      { "from": "${workspaceFolder}", "to": "/path/to/remote/workspace" },
       ...
   ]
 }
@@ -655,7 +655,7 @@
 
 ### Starting a debug session fails with `decoding dwarf section info at offset 0x0: too short` or `could not open debug info` error.
 
-These errors indicate that your binary was built with linker flags that stripped the symbol table (`-s`) or the DWARF debug information (`-w`), making debugging impossible. If the binary is built while launching the session, make sure your `launch.json` configuration does not contain `"buildFlags": "--ldflags '-s -w'"`. If you use `debug test` or Test Explorer, check `go.buildFlags` in `settings.json`. If the binary is built externally, check the command-line flags and do not use `go run`. Unlike `go build`, `go run` passes `-s -w` to the linker under the hood. If you try to attach to such a binary with a debugger, it will fail with one of the above errors (see Go Issue [24833](https://github.com/golang/go/issues/24833)). Instead let dlv build the binary for you or use `go build -gcflags='all=-N -l'`.
+These errors indicate that your binary was built with linker flags that stripped the symbol table (`-s`) or the DWARF debug information (`-w`), making debugging impossible. If the binary is built while launching the session, make sure your `launch.json` configuration does not contain `"buildFlags": "--ldflags '-s -w'"`. If you use `debug test` or Test Explorer, check `go.buildFlags` in `settings.json`. If the binary is built externally, check the command-line flags and do not use `go run`. Unlike `go build`, `go run` passes `-s -w` to the linker under the hood. If you try to attach to such a binary with a debugger, it will fail with one of the above errors (see Go Issue [24833](https://github.com/golang/go/issues/24833)). Instead let dlv build the binary for you or use `go build -gcflags=all="-N -l"`.
 
 ## Reporting Issues
 
diff --git a/docs/settings.md b/docs/settings.md
index 0b0299e..c6f9975 100644
--- a/docs/settings.md
+++ b/docs/settings.md
@@ -272,85 +272,68 @@
 Default: `false`
 ### `go.inlayHints.assignVariableTypes`
 
-Enable/disable inlay hints for variable types in assign statements.
+Enable/disable inlay hints for variable types in assign statements:
 ```go
-
-i /*int*/, j /*int*/ := 0, len(r)-1
+	i/* int*/, j/* int*/ := 0, len(r)-1
 ```
 
 Default: `false`
 ### `go.inlayHints.compositeLiteralFields`
 
-Enable/disable inlay hints for composite literal field names.
+Enable/disable inlay hints for composite literal field names:
 ```go
-
-for _, c := range []struct {in, want string}{
-	{/*in:*/ "Hello, world", /*want:*/ "dlrow ,olleH"},
-	{/*in:*/ "Hello, δΈ–η•Œ", /*want:*/ "η•ŒδΈ– ,olleH"},
-	{/*in:*/ "", /*want:*/ ""},
-} {
-	...
-}
+	{/*in: */"Hello, world", /*want: */"dlrow ,olleH"}
 ```
 
 Default: `false`
 ### `go.inlayHints.compositeLiteralTypes`
 
-Enable/disable inlay hints for composite literal types.
+Enable/disable inlay hints for composite literal types:
 ```go
-
-for _, c := range []struct {in, want string}{
-	/*struct{ in, want string }*/{"Hello, world", "dlrow ,olleH"},
-	/*struct{ in, want string }*/{"Hello, δΈ–η•Œ", "η•ŒδΈ– ,olleH"},
-	/*struct{ in, want string }*/{"", ""},
-} {
-	...
-}
+	for _, c := range []struct {
+		in, want string
+	}{
+		/*struct{ in string; want string }*/{"Hello, world", "dlrow ,olleH"},
+	}
 ```
 
 Default: `false`
 ### `go.inlayHints.constantValues`
 
-Enable/disable inlay hints for constant values.
+Enable/disable inlay hints for constant values:
 ```go
-
-const (
-	KindNone   = iota	/*= 0*/
-	KindPrint	/*= 1*/
-	KindPrintf	/*= 2*/
-	KindErrorf	/*= 3*/
-)
+	const (
+		KindNone   Kind = iota/* = 0*/
+		KindPrint/*  = 1*/
+		KindPrintf/* = 2*/
+		KindErrorf/* = 3*/
+	)
 ```
 
 Default: `false`
 ### `go.inlayHints.functionTypeParameters`
 
-Enable/disable inlay hints for implicit type parameters on generic functions.
+Enable/disable inlay hints for implicit type parameters on generic functions:
 ```go
-
-func myFunc[T any](a T) { ... }
-
-func main() {
-	myFunc/*[int]*/(1)
-}
+	myFoo/*[int, string]*/(1, "hello")
 ```
 
 Default: `false`
 ### `go.inlayHints.parameterNames`
 
-Enable/disable inlay hints for parameter names.
+Enable/disable inlay hints for parameter names:
 ```go
-
-http.HandleFunc(/*pattern:*/ "/", /*handler:*/ indexHandler)
+	parseInt(/* str: */ "123", /* radix: */ 8)
 ```
 
 Default: `false`
 ### `go.inlayHints.rangeVariableTypes`
 
-Enable/disable inlay hints for variable types in range statements.
+Enable/disable inlay hints for variable types in range statements:
 ```go
-
-for k /*int*/, v /*string*/ := range []string{} { ... }
+	for k/* int*/, v/* string*/ := range []string{} {
+		fmt.Println(k, v)
+	}
 ```
 
 Default: `false`
@@ -744,6 +727,7 @@
 | `gc_details` | Toggle the calculation of gc annotations. <br/> Default: `false` |
 | `generate` | Runs `go generate` for a given directory. <br/> Default: `true` |
 | `regenerate_cgo` | Regenerates cgo definitions. <br/> Default: `true` |
+| `run_vulncheck_exp` | Run vulnerability check (`govulncheck`). <br/> Default: `false` |
 | `test` | Runs `go test` for a specific set of test or benchmark functions. <br/> Default: `false` |
 | `tidy` | Runs `go mod tidy` for a module. <br/> Default: `true` |
 | `upgrade_dependency` | Upgrades a dependency in the go.mod file for a module. <br/> Default: `true` |
@@ -837,12 +821,14 @@
 | `stubmethods` | stub methods analyzer <br/> This analyzer generates method stubs for concrete types in order to implement a target interface <br/> Default: `true` |
 | `testinggoroutine` | report calls to (*testing.T).Fatal from goroutines started by a test. <br/> Functions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and Skip{,f,Now} methods of *testing.T, must be called from the test goroutine itself. This checker detects calls to these functions that occur within a goroutine started by the test. For example: <br/> func TestFoo(t *testing.T) {     go func() {         t.Fatal("oops") // error: (*T).Fatal called from non-test goroutine     }() } <br/> <br/> Default: `true` |
 | `tests` | check for common mistaken usages of tests and examples <br/> The tests checker walks Test, Benchmark and Example functions checking malformed names, wrong signatures and examples documenting non-existent identifiers. <br/> Please see the documentation for package testing in golang.org/pkg/testing for the conventions that are enforced for Tests, Benchmarks, and Examples. <br/> Default: `true` |
+| `timeformat` | check for calls of (time.Time).Format or time.Parse with 2006-02-01 <br/> The timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm) format. Internationally, "yyyy-dd-mm" does not occur in common calendar date standards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended. <br/> <br/> Default: `true` |
 | `undeclaredname` | suggested fixes for "undeclared name: <>" <br/> This checker provides suggested fixes for type errors of the type "undeclared name: <>". It will either insert a new statement, such as: <br/> "<> := " <br/> or a new function declaration, such as: <br/> func <>(inferred parameters) { <pre>panic("implement me!")</pre>} <br/> <br/> Default: `true` |
 | `unmarshal` | report passing non-pointer or non-interface values to unmarshal <br/> The unmarshal analysis reports calls to functions such as json.Unmarshal in which the argument type is not a pointer or an interface. <br/> Default: `true` |
 | `unreachable` | check for unreachable code <br/> The unreachable analyzer finds statements that execution can never reach because they are preceded by an return statement, a call to panic, an infinite loop, or similar constructs. <br/> Default: `true` |
 | `unsafeptr` | check for invalid conversions of uintptr to unsafe.Pointer <br/> The unsafeptr analyzer reports likely incorrect uses of unsafe.Pointer to convert integers to pointers. A conversion from uintptr to unsafe.Pointer is invalid if it implies that there is a uintptr-typed word in memory that holds a pointer value, because that word will be invisible to stack copying and to the garbage collector. <br/> Default: `true` |
 | `unusedparams` | check for unused parameters of functions <br/> The unusedparams analyzer checks functions to see if there are any parameters that are not being used. <br/> To reduce false positives it ignores: - methods - parameters that do not have a name or are underscored - functions in test files - functions with empty bodies or those with just a return stmt <br/> Default: `false` |
 | `unusedresult` | check for unused results of calls to some functions <br/> Some functions like fmt.Errorf return a result and have no side effects, so it is always a mistake to discard the result. This analyzer reports calls to certain functions in which the result of the call is ignored. <br/> The set of functions may be controlled using flags. <br/> Default: `true` |
+| `unusedvariable` | check for unused variables <br/> The unusedvariable analyzer suggests fixes for unused variables errors. <br/> <br/> Default: `false` |
 | `unusedwrite` | checks for unused writes <br/> The analyzer reports instances of writes to struct fields and arrays that are never read. Specifically, when a struct object or an array is copied, its elements are copied implicitly by the compiler, and any element write to this copy does nothing with the original object. <br/> For example: <br/> <pre>type T struct { x int }<br/>func f(input []T) {<br/>	for i, v := range input {  // v is a copy<br/>		v.x = i  // unused write to field x<br/>	}<br/>}</pre><br/> Another example is about non-pointer receiver: <br/> <pre>type T struct { x int }<br/>func (t T) f() {  // t is a copy<br/>	t.x = i  // unused write to field x<br/>}</pre><br/> <br/> Default: `false` |
 | `useany` | check for constraints that could be simplified to "any" <br/> Default: `false` |
 ### `ui.diagnostic.annotations`
@@ -912,6 +898,9 @@
 
 If company chooses to use its own `godoc.org`, its address can be used as well.
 
+Modules matching the GOPRIVATE environment variable will not have
+documentation links in hover.
+
 
 Default: `"pkg.go.dev"`
 ### `ui.documentation.linksInHover`
@@ -962,6 +951,18 @@
 
 
 Default: `"Dynamic"`
+### `ui.noSemanticNumber`
+
+(Experimental) noSemanticNumber  turns off the sending of the semantic token 'number'
+
+
+Default: `false`
+### `ui.noSemanticString`
+
+(Experimental) noSemanticString turns off the sending of the semantic token 'string'
+
+
+Default: `false`
 ### `ui.semanticTokens`
 
 (Experimental) semanticTokens controls whether the LSP server will send
diff --git a/package-lock.json b/package-lock.json
index 347256c..bc1ce3d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "go",
-  "version": "0.35.1",
+  "version": "0.35.2",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "go",
-      "version": "0.35.0",
+      "version": "0.35.2",
       "license": "MIT",
       "dependencies": {
         "diff": "4.0.2",
@@ -42,7 +42,6 @@
         "prettier": "2.2.1",
         "sinon": "9.2.4",
         "ts-loader": "7.0.5",
-        "tslint": "6.1.3",
         "typescript": "4.6.4",
         "yarn": "1.22.10"
       },
@@ -838,15 +837,6 @@
         "node": ">= 8"
       }
     },
-    "node_modules/argparse": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-      "dev": true,
-      "dependencies": {
-        "sprintf-js": "~1.0.2"
-      }
-    },
     "node_modules/array-union": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -1020,15 +1010,6 @@
         "node": ">=0.2.0"
       }
     },
-    "node_modules/builtin-modules": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/callsites": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -1191,12 +1172,6 @@
         "node": ">= 0.8"
       }
     },
-    "node_modules/commander": {
-      "version": "2.20.3",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
-      "dev": true
-    },
     "node_modules/concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -1729,19 +1704,6 @@
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
       }
     },
-    "node_modules/esprima": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
-      "dev": true,
-      "bin": {
-        "esparse": "bin/esparse.js",
-        "esvalidate": "bin/esvalidate.js"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/esquery": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
@@ -2609,19 +2571,6 @@
       "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
       "dev": true
     },
-    "node_modules/js-yaml": {
-      "version": "3.14.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
-      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
-      "dev": true,
-      "dependencies": {
-        "argparse": "^1.0.7",
-        "esprima": "^4.0.0"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
     "node_modules/jsbn": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
@@ -3998,12 +3947,6 @@
       "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==",
       "dev": true
     },
-    "node_modules/sprintf-js": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
-      "dev": true
-    },
     "node_modules/sshpk": {
       "version": "1.16.1",
       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
@@ -4283,120 +4226,6 @@
       "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
       "dev": true
     },
-    "node_modules/tslint": {
-      "version": "6.1.3",
-      "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz",
-      "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==",
-      "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.",
-      "dev": true,
-      "dependencies": {
-        "@babel/code-frame": "^7.0.0",
-        "builtin-modules": "^1.1.1",
-        "chalk": "^2.3.0",
-        "commander": "^2.12.1",
-        "diff": "^4.0.1",
-        "glob": "^7.1.1",
-        "js-yaml": "^3.13.1",
-        "minimatch": "^3.0.4",
-        "mkdirp": "^0.5.3",
-        "resolve": "^1.3.2",
-        "semver": "^5.3.0",
-        "tslib": "^1.13.0",
-        "tsutils": "^2.29.0"
-      },
-      "bin": {
-        "tslint": "bin/tslint"
-      },
-      "engines": {
-        "node": ">=4.8.0"
-      },
-      "peerDependencies": {
-        "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev"
-      }
-    },
-    "node_modules/tslint/node_modules/ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^1.9.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/tslint/node_modules/chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/tslint/node_modules/color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "1.1.3"
-      }
-    },
-    "node_modules/tslint/node_modules/color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-      "dev": true
-    },
-    "node_modules/tslint/node_modules/has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/tslint/node_modules/semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver"
-      }
-    },
-    "node_modules/tslint/node_modules/supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/tslint/node_modules/tsutils": {
-      "version": "2.29.0",
-      "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
-      "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
-      "dev": true,
-      "dependencies": {
-        "tslib": "^1.8.1"
-      },
-      "peerDependencies": {
-        "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev"
-      }
-    },
     "node_modules/tsutils": {
       "version": "3.21.0",
       "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
@@ -5415,15 +5244,6 @@
         "picomatch": "^2.0.4"
       }
     },
-    "argparse": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-      "dev": true,
-      "requires": {
-        "sprintf-js": "~1.0.2"
-      }
-    },
     "array-union": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -5558,12 +5378,6 @@
       "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=",
       "dev": true
     },
-    "builtin-modules": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
-      "dev": true
-    },
     "callsites": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -5682,12 +5496,6 @@
         "delayed-stream": "~1.0.0"
       }
     },
-    "commander": {
-      "version": "2.20.3",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
-      "dev": true
-    },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -6077,12 +5885,6 @@
         "eslint-visitor-keys": "^3.3.0"
       }
     },
-    "esprima": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
-      "dev": true
-    },
     "esquery": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
@@ -6729,16 +6531,6 @@
       "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
       "dev": true
     },
-    "js-yaml": {
-      "version": "3.14.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
-      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
-      "dev": true,
-      "requires": {
-        "argparse": "^1.0.7",
-        "esprima": "^4.0.0"
-      }
-    },
     "jsbn": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
@@ -7778,12 +7570,6 @@
       "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==",
       "dev": true
     },
-    "sprintf-js": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
-      "dev": true
-    },
     "sshpk": {
       "version": "1.16.1",
       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
@@ -7996,94 +7782,6 @@
       "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
       "dev": true
     },
-    "tslint": {
-      "version": "6.1.3",
-      "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz",
-      "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.0.0",
-        "builtin-modules": "^1.1.1",
-        "chalk": "^2.3.0",
-        "commander": "^2.12.1",
-        "diff": "^4.0.1",
-        "glob": "^7.1.1",
-        "js-yaml": "^3.13.1",
-        "minimatch": "^3.0.4",
-        "mkdirp": "^0.5.3",
-        "resolve": "^1.3.2",
-        "semver": "^5.3.0",
-        "tslib": "^1.13.0",
-        "tsutils": "^2.29.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "dev": true,
-          "requires": {
-            "color-convert": "^1.9.0"
-          }
-        },
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
-          }
-        },
-        "color-convert": {
-          "version": "1.9.3",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-          "dev": true,
-          "requires": {
-            "color-name": "1.1.3"
-          }
-        },
-        "color-name": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-          "dev": true
-        },
-        "has-flag": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-          "dev": true
-        },
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
-        },
-        "tsutils": {
-          "version": "2.29.0",
-          "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
-          "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
-          "dev": true,
-          "requires": {
-            "tslib": "^1.8.1"
-          }
-        }
-      }
-    },
     "tsutils": {
       "version": "3.21.0",
       "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
diff --git a/package.json b/package.json
index 9884ac0..15bf017 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "go",
   "displayName": "Go",
-  "version": "0.35.1",
+  "version": "0.35.2",
   "publisher": "golang",
   "description": "Rich Go language support for Visual Studio Code",
   "author": {
@@ -81,12 +81,12 @@
     "prettier": "2.2.1",
     "sinon": "9.2.4",
     "ts-loader": "7.0.5",
-    "tslint": "6.1.3",
     "typescript": "4.6.4",
     "yarn": "1.22.10"
   },
   "engines": {
-    "vscode": "^1.67.0"
+    "vscode": "^1.67.0",
+    "node": ">=12.0.0"
   },
   "activationEvents": [
     "onLanguage:go",
@@ -94,6 +94,7 @@
     "workspaceContains:*/*.go",
     "workspaceContains:*/*/*.go",
     "onCommand:go.gopath",
+    "onCommand:go.goroot",
     "onCommand:go.tools.install",
     "onCommand:go.locate.tools",
     "onCommand:go.show.commands",
@@ -211,6 +212,11 @@
         "description": "See the currently set GOPATH."
       },
       {
+        "command": "go.goroot",
+        "title": "Go: Current GOROOT",
+        "description": "See the currently set GOROOT."
+      },
+      {
         "command": "go.locate.tools",
         "title": "Go: Locate Configured Go Tools",
         "description": "List all the Go tools being used by this extension along with their locations."
@@ -2042,41 +2048,6 @@
           "scope": "resource",
           "type": "boolean"
         },
-        "go.inlayHints.assignVariableTypes": {
-          "type": "boolean",
-          "markdownDescription": "Enable/disable inlay hints for variable types in assign statements.\n```go\n\ni /*int*/, j /*int*/ := 0, len(r)-1\n```",
-          "default": false
-        },
-        "go.inlayHints.compositeLiteralFields": {
-          "type": "boolean",
-          "markdownDescription": "Enable/disable inlay hints for composite literal field names.\n```go\n\nfor _, c := range []struct {in, want string}{\n\t{/*in:*/ \"Hello, world\", /*want:*/ \"dlrow ,olleH\"},\n\t{/*in:*/ \"Hello, δΈ–η•Œ\", /*want:*/ \"η•ŒδΈ– ,olleH\"},\n\t{/*in:*/ \"\", /*want:*/ \"\"},\n} {\n\t...\n}\n```",
-          "default": false
-        },
-        "go.inlayHints.compositeLiteralTypes": {
-          "type": "boolean",
-          "markdownDescription": "Enable/disable inlay hints for composite literal types.\n```go\n\nfor _, c := range []struct {in, want string}{\n\t/*struct{ in, want string }*/{\"Hello, world\", \"dlrow ,olleH\"},\n\t/*struct{ in, want string }*/{\"Hello, δΈ–η•Œ\", \"η•ŒδΈ– ,olleH\"},\n\t/*struct{ in, want string }*/{\"\", \"\"},\n} {\n\t...\n}\n```",
-          "default": false
-        },
-        "go.inlayHints.constantValues": {
-          "type": "boolean",
-          "markdownDescription": "Enable/disable inlay hints for constant values.\n```go\n\nconst (\n\tKindNone   = iota\t/*= 0*/\n\tKindPrint\t/*= 1*/\n\tKindPrintf\t/*= 2*/\n\tKindErrorf\t/*= 3*/\n)\n```",
-          "default": false
-        },
-        "go.inlayHints.functionTypeParameters": {
-          "type": "boolean",
-          "markdownDescription": "Enable/disable inlay hints for implicit type parameters on generic functions.\n```go\n\nfunc myFunc[T any](a T) { ... }\n\nfunc main() {\n\tmyFunc/*[int]*/(1)\n}\n```",
-          "default": false
-        },
-        "go.inlayHints.parameterNames": {
-          "type": "boolean",
-          "markdownDescription": "Enable/disable inlay hints for parameter names.\n```go\n\nhttp.HandleFunc(/*pattern:*/ \"/\", /*handler:*/ indexHandler)\n```",
-          "default": false
-        },
-        "go.inlayHints.rangeVariableTypes": {
-          "type": "boolean",
-          "markdownDescription": "Enable/disable inlay hints for variable types in range statements.\n```go\n\nfor k /*int*/, v /*string*/ := range []string{} { ... }\n```",
-          "default": false
-        },
         "gopls": {
           "type": "object",
           "markdownDescription": "Configure the default Go language server ('gopls'). In most cases, configuring this section is unnecessary. See [the documentation](https://github.com/golang/tools/blob/master/gopls/doc/settings.md) for all available settings.",
@@ -2189,6 +2160,11 @@
                   "markdownDescription": "Regenerates cgo definitions.",
                   "default": true
                 },
+                "run_vulncheck_exp": {
+                  "type": "boolean",
+                  "markdownDescription": "Run vulnerability check (`govulncheck`).",
+                  "default": false
+                },
                 "test": {
                   "type": "boolean",
                   "markdownDescription": "Runs `go test` for a specific set of test or benchmark functions.",
@@ -2435,6 +2411,11 @@
                   "markdownDescription": "check for common mistaken usages of tests and examples\n\nThe tests checker walks Test, Benchmark and Example functions checking\nmalformed names, wrong signatures and examples documenting non-existent\nidentifiers.\n\nPlease see the documentation for package testing in golang.org/pkg/testing\nfor the conventions that are enforced for Tests, Benchmarks, and Examples.",
                   "default": true
                 },
+                "timeformat": {
+                  "type": "boolean",
+                  "markdownDescription": "check for calls of (time.Time).Format or time.Parse with 2006-02-01\n\nThe timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm)\nformat. Internationally, \"yyyy-dd-mm\" does not occur in common calendar date\nstandards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended.\n",
+                  "default": true
+                },
                 "undeclaredname": {
                   "type": "boolean",
                   "markdownDescription": "suggested fixes for \"undeclared name: <>\"\n\nThis checker provides suggested fixes for type errors of the\ntype \"undeclared name: <>\". It will either insert a new statement,\nsuch as:\n\n\"<> := \"\n\nor a new function declaration, such as:\n\nfunc <>(inferred parameters) {\n\tpanic(\"implement me!\")\n}\n",
@@ -2465,6 +2446,11 @@
                   "markdownDescription": "check for unused results of calls to some functions\n\nSome functions like fmt.Errorf return a result and have no side effects,\nso it is always a mistake to discard the result. This analyzer reports\ncalls to certain functions in which the result of the call is ignored.\n\nThe set of functions may be controlled using flags.",
                   "default": true
                 },
+                "unusedvariable": {
+                  "type": "boolean",
+                  "markdownDescription": "check for unused variables\n\nThe unusedvariable analyzer suggests fixes for unused variables errors.\n",
+                  "default": false
+                },
                 "unusedwrite": {
                   "type": "boolean",
                   "markdownDescription": "checks for unused writes\n\nThe analyzer reports instances of writes to struct fields and\narrays that are never read. Specifically, when a struct object\nor an array is copied, its elements are copied implicitly by\nthe compiler, and any element write to this copy does nothing\nwith the original object.\n\nFor example:\n\n\ttype T struct { x int }\n\tfunc f(input []T) {\n\t\tfor i, v := range input {  // v is a copy\n\t\t\tv.x = i  // unused write to field x\n\t\t}\n\t}\n\nAnother example is about non-pointer receiver:\n\n\ttype T struct { x int }\n\tfunc (t T) f() {  // t is a copy\n\t\tt.x = i  // unused write to field x\n\t}\n",
@@ -2544,7 +2530,7 @@
             },
             "ui.documentation.linkTarget": {
               "type": "string",
-              "markdownDescription": "linkTarget controls where documentation links go.\nIt might be one of:\n\n* `\"godoc.org\"`\n* `\"pkg.go.dev\"`\n\nIf company chooses to use its own `godoc.org`, its address can be used as well.\n",
+              "markdownDescription": "linkTarget controls where documentation links go.\nIt might be one of:\n\n* `\"godoc.org\"`\n* `\"pkg.go.dev\"`\n\nIf company chooses to use its own `godoc.org`, its address can be used as well.\n\nModules matching the GOPRIVATE environment variable will not have\ndocumentation links in hover.\n",
               "default": "pkg.go.dev",
               "scope": "resource"
             },
@@ -2604,6 +2590,18 @@
               "default": "Dynamic",
               "scope": "resource"
             },
+            "ui.noSemanticNumber": {
+              "type": "boolean",
+              "markdownDescription": "(Experimental) noSemanticNumber  turns off the sending of the semantic token 'number'\n",
+              "default": false,
+              "scope": "resource"
+            },
+            "ui.noSemanticString": {
+              "type": "boolean",
+              "markdownDescription": "(Experimental) noSemanticString turns off the sending of the semantic token 'string'\n",
+              "default": false,
+              "scope": "resource"
+            },
             "ui.semanticTokens": {
               "type": "boolean",
               "markdownDescription": "(Experimental) semanticTokens controls whether the LSP server will send\nsemantic tokens to the client.\n",
@@ -2617,6 +2615,41 @@
               "scope": "resource"
             }
           }
+        },
+        "go.inlayHints.assignVariableTypes": {
+          "type": "boolean",
+          "markdownDescription": "Enable/disable inlay hints for variable types in assign statements:\n```go\n\ti/* int*/, j/* int*/ := 0, len(r)-1\n```",
+          "default": false
+        },
+        "go.inlayHints.compositeLiteralFields": {
+          "type": "boolean",
+          "markdownDescription": "Enable/disable inlay hints for composite literal field names:\n```go\n\t{/*in: */\"Hello, world\", /*want: */\"dlrow ,olleH\"}\n```",
+          "default": false
+        },
+        "go.inlayHints.compositeLiteralTypes": {
+          "type": "boolean",
+          "markdownDescription": "Enable/disable inlay hints for composite literal types:\n```go\n\tfor _, c := range []struct {\n\t\tin, want string\n\t}{\n\t\t/*struct{ in string; want string }*/{\"Hello, world\", \"dlrow ,olleH\"},\n\t}\n```",
+          "default": false
+        },
+        "go.inlayHints.constantValues": {
+          "type": "boolean",
+          "markdownDescription": "Enable/disable inlay hints for constant values:\n```go\n\tconst (\n\t\tKindNone   Kind = iota/* = 0*/\n\t\tKindPrint/*  = 1*/\n\t\tKindPrintf/* = 2*/\n\t\tKindErrorf/* = 3*/\n\t)\n```",
+          "default": false
+        },
+        "go.inlayHints.functionTypeParameters": {
+          "type": "boolean",
+          "markdownDescription": "Enable/disable inlay hints for implicit type parameters on generic functions:\n```go\n\tmyFoo/*[int, string]*/(1, \"hello\")\n```",
+          "default": false
+        },
+        "go.inlayHints.parameterNames": {
+          "type": "boolean",
+          "markdownDescription": "Enable/disable inlay hints for parameter names:\n```go\n\tparseInt(/* str: */ \"123\", /* radix: */ 8)\n```",
+          "default": false
+        },
+        "go.inlayHints.rangeVariableTypes": {
+          "type": "boolean",
+          "markdownDescription": "Enable/disable inlay hints for variable types in range statements:\n```go\n\tfor k/* int*/, v/* string*/ := range []string{} {\n\t\tfmt.Println(k, v)\n\t}\n```",
+          "default": false
         }
       }
     },
diff --git a/src/commands/getCurrentGoRoot.ts b/src/commands/getCurrentGoRoot.ts
new file mode 100644
index 0000000..cd0a5af
--- /dev/null
+++ b/src/commands/getCurrentGoRoot.ts
@@ -0,0 +1,18 @@
+/*---------------------------------------------------------
+ * Copyright 2022 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+import * as vscode from 'vscode';
+
+import { CommandFactory } from '.';
+import { getCurrentGoRoot as utilGetCurrentGoRoot } from '../utils/pathUtils';
+
+export const getCurrentGoRoot: CommandFactory = () => {
+	return () => {
+		const goroot = utilGetCurrentGoRoot();
+		const msg = `${goroot} is the current GOROOT.`;
+		vscode.window.showInformationMessage(msg);
+		return goroot;
+	};
+};
diff --git a/src/commands/index.ts b/src/commands/index.ts
index d82ba4a..d15dffc 100644
--- a/src/commands/index.ts
+++ b/src/commands/index.ts
@@ -10,6 +10,7 @@
 export { applyCoverprofile } from './applyCoverprofile';
 export { getConfiguredGoTools } from './getConfiguredGoTools';
 export { getCurrentGoPath } from './getCurrentGoPath';
+export { getCurrentGoRoot } from './getCurrentGoRoot';
 export { extractFunction, extractVariable } from '../goDoctor';
 export { runFillStruct } from '../goFillStruct';
 export { implCursor } from '../goImpl';
diff --git a/src/goGenerateTests.ts b/src/goGenerateTests.ts
index eb67da3..12e0e42 100644
--- a/src/goGenerateTests.ts
+++ b/src/goGenerateTests.ts
@@ -16,7 +16,7 @@
 import { promptForMissingTool } from './goInstallTools';
 import { GoDocumentSymbolProvider } from './goDocumentSymbols';
 import { outputChannel } from './goStatus';
-import { getBinPath } from './util';
+import { getBinPath, resolvePath } from './util';
 import { CommandFactory } from './commands';
 import { GoExtensionContext } from './context';
 
@@ -178,6 +178,12 @@
 				i++;
 				continue;
 			}
+			if (i + 1 < goGenerateTestsFlags.length && (flag === '-template_dir' || flag === '-template_params_file')) {
+				const configFilePath = resolvePath(goGenerateTestsFlags[i + 1]);
+				args.push(flag, configFilePath);
+				i++;
+				continue;
+			}
 			args.push(flag);
 		}
 
diff --git a/src/goMain.ts b/src/goMain.ts
index db31bbb..a525684 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -136,6 +136,7 @@
 	ctx.subscriptions.push(goCtx.vetDiagnosticCollection);
 
 	registerCommand('go.gopath', commands.getCurrentGoPath);
+	registerCommand('go.goroot', commands.getCurrentGoRoot);
 	registerCommand('go.locate.tools', commands.getConfiguredGoTools);
 	registerCommand('go.add.tags', commands.addTags);
 	registerCommand('go.remove.tags', commands.removeTags);
diff --git a/src/goModules.ts b/src/goModules.ts
index 9d3f39d..6305caf 100644
--- a/src/goModules.ts
+++ b/src/goModules.ts
@@ -48,8 +48,12 @@
 	return getModFolderPath(fileuri, isDir).then((modPath) => !!modPath);
 }
 
+// packagePathToGoModPathMap is a cache that maps from a file path (of a package directory)
+// to the module root directory path (directory of `go env GOMOD`) if the file belongs to a module.
 export const packagePathToGoModPathMap: { [key: string]: string } = {};
 
+// getModFolderPath returns the module root of the file. '' or undefined value indicates
+// the file is outside of any module or Go module is disabled.
 export async function getModFolderPath(fileuri?: vscode.Uri, isDir?: boolean): Promise<string | undefined> {
 	const pkgUri = isDir ? fileuri : fileuri && vscodeUri.Utils.dirname(fileuri);
 	const pkgPath = pkgUri?.fsPath ?? '';
diff --git a/src/goTest/resolve.ts b/src/goTest/resolve.ts
index b096657..2b4d93c 100644
--- a/src/goTest/resolve.ts
+++ b/src/goTest/resolve.ts
@@ -328,12 +328,16 @@
 			}
 
 			if (nested) {
-				const bits = parent.uri ? path.relative(parent.uri.path, uri.path).split(path.sep) : [];
+				const bits = parent.uri ? path.relative(parent.uri.fsPath, uri.fsPath).split(path.sep) : [];
 				while (bits.length > 1) {
 					if (!parent.uri?.path) continue;
 					const dir = bits.shift();
 					if (!dir) continue;
-					const dirUri = uri.with({ path: path.join(parent.uri.path, dir), query: '', fragment: '' });
+					const dirUri = uri.with({
+						path: Uri.file(path.join(parent.uri.fsPath, dir)).path,
+						query: '',
+						fragment: ''
+					});
 					parent = this.getOrCreateItem(parent, dir, dirUri, 'package');
 				}
 			}
diff --git a/src/goToolsInformation.ts b/src/goToolsInformation.ts
index 4a009c4..bdb617b 100644
--- a/src/goToolsInformation.ts
+++ b/src/goToolsInformation.ts
@@ -195,10 +195,10 @@
 		description: 'Language Server from Google',
 		usePrereleaseInPreviewMode: true,
 		minimumGoVersion: semver.coerce('1.13'),
-		latestVersion: semver.parse('v0.9.1'),
-		latestVersionTimestamp: moment('2022-07-13', 'YYYY-MM-DD'),
-		latestPrereleaseVersion: semver.parse('v0.9.1'),
-		latestPrereleaseVersionTimestamp: moment('2022-07-13', 'YYYY-MM-DD')
+		latestVersion: semver.parse('v0.9.3'),
+		latestVersionTimestamp: moment('2022-08-11', 'YYYY-MM-DD'),
+		latestPrereleaseVersion: semver.parse('v0.9.3'),
+		latestPrereleaseVersionTimestamp: moment('2022-08-11', 'YYYY-MM-DD')
 	},
 	'dlv': {
 		name: 'dlv',
diff --git a/test/gopls/vulncheck.test.ts b/test/gopls/vulncheck.test.ts
index 70a622f..2706b66 100644
--- a/test/gopls/vulncheck.test.ts
+++ b/test/gopls/vulncheck.test.ts
@@ -29,44 +29,60 @@
 		vscode.Disposable.from(...disposables).dispose();
 	});
 
-	test('populates webview', async function () {
-		this.timeout(5000);
-		const webviewPanel = _register(
-			vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, {})
-		);
-		const source = path.join(fixtureDir, 'test.vulncheck.json');
-		const doc = await vscode.workspace.openTextDocument(source);
-		const canceller = new vscode.CancellationTokenSource();
-		_register(canceller);
+	test('populates webview', async () => {
+		const doTest = async (tag: string) => {
+			const webviewPanel = _register(
+				vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, {})
+			);
+			const source = path.join(fixtureDir, 'test.vulncheck.json');
+			const doc = await vscode.workspace.openTextDocument(source);
+			console.timeLog(tag, 'opened document');
+			const canceller = new vscode.CancellationTokenSource();
+			_register(canceller);
 
-		const watcher = getMessage<{ type: string; target?: string }>(webviewPanel);
+			const watcher = getMessage<{ type: string; target?: string }>(webviewPanel);
 
-		await provider.resolveCustomTextEditor(doc, webviewPanel, canceller.token);
-		webviewPanel.reveal();
+			await provider.resolveCustomTextEditor(doc, webviewPanel, canceller.token);
+			console.timeLog(tag, 'resolved custom text editor');
 
-		// Trigger snapshotContent that sends `snapshot-result` as a result.
-		webviewPanel.webview.postMessage({ type: 'snapshot-request' });
-		const res = await watcher;
+			webviewPanel.reveal();
 
-		assert.deepStrictEqual(res.type, 'snapshot-result', `want snapshot-result, got ${JSON.stringify(res)}`);
-		// res.target type is defined in vulncheckView.js.
-		const { log = '', vulns = '', unaffecting = '' } = JSON.parse(res.target ?? '{}');
+			// Trigger snapshotContent that sends `snapshot-result` as a result.
+			webviewPanel.webview.postMessage({ type: 'snapshot-request' });
+			console.timeLog(tag, 'posted snapshot-request');
 
-		assert(
-			log.includes('Found 1 known vulnerabilities'),
-			`expected "1 known vulnerabilities", got ${JSON.stringify(res.target)}`
-		);
-		assert(
-			vulns.includes('GO-2021-0113') &&
-				vulns.includes('<td>Affecting</td><td>github.com/golang/vscode-go/test/testdata/vuln</td>'),
-			`expected "Affecting" section, got ${JSON.stringify(res.target)}`
-		);
-		// Unaffecting vulnerability's detail is omitted, but its ID is reported.
-		assert(
-			unaffecting.includes('GO-2021-0000') && unaffecting.includes('golang.org/x/text'),
-			`expected reports about unaffecting vulns, got ${JSON.stringify(res.target)}`
-		);
-	});
+			const res = await watcher;
+			console.timeLog(tag, 'received message');
+
+			assert.deepStrictEqual(res.type, 'snapshot-result', `want snapshot-result, got ${JSON.stringify(res)}`);
+			// res.target type is defined in vulncheckView.js.
+			const { log = '', vulns = '', unaffecting = '' } = JSON.parse(res.target ?? '{}');
+
+			assert(
+				log.includes('Found 1 known vulnerabilities'),
+				`expected "1 known vulnerabilities", got ${JSON.stringify(res.target)}`
+			);
+			assert(
+				vulns.includes('GO-2021-0113') &&
+					vulns.includes('<td>Affecting</td><td>github.com/golang/vscode-go/test/testdata/vuln</td>'),
+				`expected "Affecting" section, got ${JSON.stringify(res.target)}`
+			);
+			// Unaffecting vulnerability's detail is omitted, but its ID is reported.
+			assert(
+				unaffecting.includes('GO-2021-0000') && unaffecting.includes('golang.org/x/text'),
+				`expected reports about unaffecting vulns, got ${JSON.stringify(res.target)}`
+			);
+		};
+		try {
+			console.time('populates-webview');
+			await doTest('populates-webview');
+		} catch (e) {
+			console.timeLog('populates-webview', `error thrown: ${e}`);
+			throw e;
+		} finally {
+			console.timeEnd('populates-webview');
+		}
+	}).timeout(5_000);
 
 	test('handles empty input', async () => {
 		const webviewPanel = _register(
diff --git a/test/integration/extension.test.ts b/test/integration/extension.test.ts
index 6446c55..d155347 100644
--- a/test/integration/extension.test.ts
+++ b/test/integration/extension.test.ts
@@ -46,6 +46,7 @@
 import cp = require('child_process');
 import os = require('os');
 import { MockExtensionContext } from '../mocks/MockContext';
+import { affectedByIssue832 } from './testutils';
 
 const testAll = (isModuleMode: boolean) => {
 	const dummyCancellationSource = new vscode.CancellationTokenSource();
@@ -151,7 +152,7 @@
 		const uri = vscode.Uri.file(path.join(fixturePath, 'gogetdocTestData', 'test.go'));
 		const textDocument = await vscode.workspace.openTextDocument(uri);
 
-		const promises = testCases.map(([position, expected, expectedDoc, expectedParams]) =>
+		const promises = testCases.map(([position, expected, expectedDocPrefix, expectedParams]) =>
 			provider.provideSignatureHelp(textDocument, position, dummyCancellationSource.token).then((sigHelp) => {
 				assert.ok(
 					sigHelp,
@@ -159,7 +160,10 @@
 				);
 				assert.equal(sigHelp.signatures.length, 1, 'unexpected number of overloads');
 				assert.equal(sigHelp.signatures[0].label, expected);
-				assert.equal(sigHelp.signatures[0].documentation, expectedDoc);
+				assert(
+					sigHelp.signatures[0].documentation?.toString().startsWith(expectedDocPrefix),
+					`expected doc starting with ${expectedDocPrefix}, got ${JSON.stringify(sigHelp.signatures[0])}`
+				);
 				assert.equal(sigHelp.signatures[0].parameters.length, expectedParams.length);
 				for (let i = 0; i < expectedParams.length; i++) {
 					assert.equal(sigHelp.signatures[0].parameters[i].label, expectedParams[i]);
@@ -189,7 +193,10 @@
 				}
 				assert(res);
 				assert.equal(res.contents.length, 1);
-				assert.equal((<vscode.MarkdownString>res.contents[0]).value, expectedHover);
+				assert(
+					(<vscode.MarkdownString>res.contents[0]).value.startsWith(expectedHover),
+					`expected hover starting with ${expectedHover}, got ${JSON.stringify(res.contents[0])}`
+				);
 			})
 		);
 		return Promise.all(promises);
@@ -226,11 +233,7 @@
 			this.skip();
 		} // not working in module mode
 
-		const printlnDoc = `Println formats using the default formats for its operands and writes to
-standard output. Spaces are always added between operands and a newline is
-appended. It returns the number of bytes written and any write error
-encountered.
-`;
+		const printlnDocPrefix = 'Println formats using the default formats for its operands and writes';
 		const printlnSig = goVersion.lt('1.18')
 			? 'Println(a ...interface{}) (n int, err error)'
 			: 'Println(a ...any) (n int, err error)';
@@ -239,7 +242,7 @@
 			[
 				new vscode.Position(19, 13),
 				printlnSig,
-				printlnDoc,
+				printlnDocPrefix,
 				[goVersion.lt('1.18') ? 'a ...interface{}' : 'a ...any']
 			],
 			[
@@ -277,10 +280,7 @@
 			return;
 		}
 
-		const printlnDoc = `Println formats using the default formats for its operands and writes to standard output.
-Spaces are always added between operands and a newline is appended.
-It returns the number of bytes written and any write error encountered.
-`;
+		const printlnDocPrefix = 'Println formats using the default formats for its operands and writes';
 		const printlnSig = goVersion.lt('1.18')
 			? 'Println(a ...interface{}) (n int, err error)'
 			: 'Println(a ...any) (n int, err error)';
@@ -289,7 +289,7 @@
 			[
 				new vscode.Position(19, 13),
 				printlnSig,
-				printlnDoc,
+				printlnDocPrefix,
 				[goVersion.lt('1.18') ? 'a ...interface{}' : 'a ...any']
 			],
 			[
@@ -322,11 +322,7 @@
 			this.skip();
 		} // not working in module mode
 
-		const printlnDoc = `Println formats using the default formats for its operands and writes to
-standard output. Spaces are always added between operands and a newline is
-appended. It returns the number of bytes written and any write error
-encountered.
-`;
+		const printlnDocPrefix = 'Println formats using the default formats for its operands and writes';
 		const printlnSig = goVersion.lt('1.18')
 			? 'Println func(a ...interface{}) (n int, err error)'
 			: 'Println func(a ...any) (n int, err error)';
@@ -339,7 +335,7 @@
 			[new vscode.Position(28, 16), null, null], // inside a number
 			[new vscode.Position(22, 5), 'main func()', '\n'],
 			[new vscode.Position(40, 23), 'import (math "math")', null],
-			[new vscode.Position(19, 6), printlnSig, printlnDoc],
+			[new vscode.Position(19, 6), printlnSig, printlnDocPrefix],
 			[
 				new vscode.Position(23, 4),
 				'print func(txt string)',
@@ -363,10 +359,7 @@
 			return;
 		}
 
-		const printlnDoc = `Println formats using the default formats for its operands and writes to standard output.
-Spaces are always added between operands and a newline is appended.
-It returns the number of bytes written and any write error encountered.
-`;
+		const printlnDocPrefix = 'Println formats using the default formats for its operands and writes';
 		const printlnSig = goVersion.lt('1.18')
 			? 'func Println(a ...interface{}) (n int, err error)'
 			: 'func Println(a ...any) (n int, err error)';
@@ -387,7 +380,7 @@
 				'package math',
 				'Package math provides basic constants and mathematical functions.\n\nThis package does not guarantee bit-identical results across architectures.\n'
 			],
-			[new vscode.Position(19, 6), printlnSig, printlnDoc],
+			[new vscode.Position(19, 6), printlnSig, printlnDocPrefix],
 			[
 				new vscode.Position(27, 14),
 				'type ABC struct {\n    a int\n    b int\n    c int\n}',
@@ -435,40 +428,45 @@
 	});
 
 	test('Linting - lint errors with multiple open files', async () => {
-		// handleDiagnosticErrors may adjust the lint errors' ranges to make the error more visible.
-		// This adjustment applies only to the text documents known to vscode. This test checks
-		// the adjustment is made consistently across multiple open text documents.
-		const file1 = await vscode.workspace.openTextDocument(
-			vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_1.go'))
-		);
-		const file2 = await vscode.workspace.openTextDocument(
-			vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_2.go'))
-		);
-		const warnings = await goLint(
-			file2.uri,
-			Object.create(getGoConfig(), {
-				lintTool: { value: 'staticcheck' },
-				lintFlags: { value: ['-checks', 'all,-ST1000,-ST1016'] }
-				// staticcheck skips debatable checks such as ST1003 by default,
-				// but this test depends on ST1003 (MixedCaps package name) presented in both files
-				// in the same package. So, enable that.
-			}),
-			Object.create(getGoplsConfig(), {}),
-			'package'
-		);
+		try {
+			// handleDiagnosticErrors may adjust the lint errors' ranges to make the error more visible.
+			// This adjustment applies only to the text documents known to vscode. This test checks
+			// the adjustment is made consistently across multiple open text documents.
+			const file1 = await vscode.workspace.openTextDocument(
+				vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_1.go'))
+			);
+			const file2 = await vscode.workspace.openTextDocument(
+				vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_2.go'))
+			);
+			console.log('start linting');
+			const warnings = await goLint(
+				file2.uri,
+				Object.create(getGoConfig(), {
+					lintTool: { value: 'staticcheck' },
+					lintFlags: { value: ['-checks', 'all,-ST1000,-ST1016'] }
+					// staticcheck skips debatable checks such as ST1003 by default,
+					// but this test depends on ST1003 (MixedCaps package name) presented in both files
+					// in the same package. So, enable that.
+				}),
+				Object.create(getGoplsConfig(), {}),
+				'package'
+			);
 
-		const diagnosticCollection = vscode.languages.createDiagnosticCollection('linttest');
-		handleDiagnosticErrors({}, file2, warnings, diagnosticCollection);
+			const diagnosticCollection = vscode.languages.createDiagnosticCollection('linttest');
+			handleDiagnosticErrors({}, file2, warnings, diagnosticCollection);
 
-		// The first diagnostic message for each file should be about the use of MixedCaps in package name.
-		// Both files belong to the same package name, and we want them to be identical.
-		const file1Diagnostics = diagnosticCollection.get(file1.uri);
-		const file2Diagnostics = diagnosticCollection.get(file2.uri);
-		assert(file1Diagnostics);
-		assert(file2Diagnostics);
-		assert(file1Diagnostics.length > 0);
-		assert(file2Diagnostics.length > 0);
-		assert.deepStrictEqual(file1Diagnostics[0], file2Diagnostics[0]);
+			// The first diagnostic message for each file should be about the use of MixedCaps in package name.
+			// Both files belong to the same package name, and we want them to be identical.
+			const file1Diagnostics = diagnosticCollection.get(file1.uri);
+			const file2Diagnostics = diagnosticCollection.get(file2.uri);
+			assert(file1Diagnostics);
+			assert(file2Diagnostics);
+			assert(file1Diagnostics.length > 0);
+			assert(file2Diagnostics.length > 0);
+			assert.deepStrictEqual(file1Diagnostics[0], file2Diagnostics[0]);
+		} catch (e) {
+			assert.fail(`failed to lint: ${e}`);
+		}
 	});
 
 	test('Error checking', async () => {
@@ -741,7 +739,10 @@
 		assert.equal(interfaces[0].name, 'circle');
 	});
 
-	test('Test listPackages', async () => {
+	test('Test listPackages', async function () {
+		if (affectedByIssue832()) {
+			this.skip(); // timeout on windows
+		}
 		const uri = vscode.Uri.file(path.join(fixturePath, 'baseTest', 'test.go'));
 		const document = await vscode.workspace.openTextDocument(uri);
 		await vscode.window.showTextDocument(document);
@@ -793,7 +794,10 @@
 		});
 	});
 
-	test('Workspace Symbols', () => {
+	test('Workspace Symbols', function () {
+		if (affectedByIssue832()) {
+			this.skip(); // frequent timeout on windows
+		}
 		const workspacePath = path.join(fixturePath, 'vendoring');
 		const configWithoutIgnoringFolders = Object.create(getGoConfig(), {
 			gotoSymbol: {
@@ -861,12 +865,12 @@
 		return Promise.all([withIgnoringFolders, withoutIgnoringFolders, withIncludingGoroot, withoutIncludingGoroot]);
 	});
 
-	test('Test Completion', async () => {
-		const printlnDoc = `Println formats using the default formats for its operands and writes to
-standard output. Spaces are always added between operands and a newline is
-appended. It returns the number of bytes written and any write error
-encountered.
-`;
+	test('Test Completion', async function () {
+		if (affectedByIssue832()) {
+			this.skip(); // timeout on windows
+		}
+
+		const printlnDocPrefix = 'Println formats using the default formats for its operands';
 		const printlnSig = goVersion.lt('1.18')
 			? 'func(a ...interface{}) (n int, err error)'
 			: 'func(a ...any) (n int, err error)';
@@ -874,7 +878,7 @@
 		const provider = new GoCompletionItemProvider();
 		const testCases: [vscode.Position, string, string | null, string | null][] = [
 			[new vscode.Position(7, 4), 'fmt', 'fmt', null],
-			[new vscode.Position(7, 6), 'Println', printlnSig, printlnDoc]
+			[new vscode.Position(7, 6), 'Println', printlnSig, printlnDocPrefix]
 		];
 		const uri = vscode.Uri.file(path.join(fixturePath, 'baseTest', 'test.go'));
 		const textDocument = await vscode.workspace.openTextDocument(uri);
@@ -896,22 +900,30 @@
 					if (!resolvedItemResult) {
 						return;
 					}
-					if (resolvedItemResult instanceof vscode.CompletionItem) {
-						if (resolvedItemResult.documentation) {
-							assert.equal((<vscode.MarkdownString>resolvedItemResult.documentation).value, expectedDoc);
+					const resolvedItem =
+						resolvedItemResult instanceof vscode.CompletionItem
+							? resolvedItemResult
+							: await resolvedItemResult;
+					if (resolvedItem?.documentation) {
+						const got = (<vscode.MarkdownString>resolvedItem.documentation).value;
+						if (expectedDoc) {
+							assert(
+								got.startsWith(expectedDoc),
+								`expected doc starting with ${expectedDoc}, got ${got}`
+							);
+						} else {
+							assert.equal(got, expectedDoc);
 						}
-						return;
-					}
-					const resolvedItem = await resolvedItemResult;
-					if (resolvedItem) {
-						assert.equal((<vscode.MarkdownString>resolvedItem.documentation).value, expectedDoc);
 					}
 				})
 		);
 		await Promise.all(promises);
 	});
 
-	test('Test Completion Snippets For Functions', async () => {
+	test('Test Completion Snippets For Functions', async function () {
+		if (affectedByIssue832()) {
+			this.skip(); // timeout on windows
+		}
 		const provider = new GoCompletionItemProvider();
 		const uri = vscode.Uri.file(path.join(fixturePath, 'completions', 'snippets.go'));
 		const baseConfig = getGoConfig();
@@ -1109,6 +1121,9 @@
 	});
 
 	test('Test No Completion Snippets For Functions', async () => {
+		if (affectedByIssue832()) {
+			return;
+		}
 		const provider = new GoCompletionItemProvider();
 		const uri = vscode.Uri.file(path.join(fixturePath, 'completions', 'nosnippets.go'));
 		const baseConfig = getGoConfig();
@@ -1176,7 +1191,7 @@
 	});
 
 	test('Test Completion on unimported packages', async function () {
-		if (isModuleMode) {
+		if (isModuleMode || affectedByIssue832()) {
 			this.skip();
 		}
 		// gocode-gomod does not handle unimported package completion.
@@ -1212,7 +1227,10 @@
 		await Promise.all(promises);
 	});
 
-	test('Test Completion on unimported packages (multiple)', async () => {
+	test('Test Completion on unimported packages (multiple)', async function () {
+		if (affectedByIssue832()) {
+			this.skip();
+		}
 		const config = Object.create(getGoConfig(), {
 			gocodeFlags: { value: ['-builtin'] }
 		});
diff --git a/test/integration/goDebug.test.ts b/test/integration/goDebug.test.ts
index 471db8b..1a6ac4b 100644
--- a/test/integration/goDebug.test.ts
+++ b/test/integration/goDebug.test.ts
@@ -32,6 +32,7 @@
 import getPort = require('get-port');
 import util = require('util');
 import { TimestampedLogger } from '../../src/goLogging';
+import { affectedByIssue832 } from './testutils';
 
 // For debugging test and streaming the trace instead of buffering, set this.
 const PRINT_TO_CONSOLE = false;
@@ -412,14 +413,45 @@
 		if (continueOnStart) {
 			args.push('--continue');
 		}
-		const childProcess = cp.spawn(toolPath, args, {
-			cwd: serverFolder,
-			env: { PORT: `${serverPort}`, ...process.env }
-		});
 
-		// Give dlv a few seconds to start.
-		await new Promise((resolve) => setTimeout(resolve, 10_000));
-		return childProcess;
+		const promise = new Promise<cp.ChildProcess>((resolve, reject) => {
+			const p = cp.spawn(toolPath, args, {
+				cwd: serverFolder,
+				env: { PORT: `${serverPort}`, ...process.env }
+			});
+
+			let started = false;
+			const timeoutToken: NodeJS.Timer = setTimeout(() => {
+				console.log(`dlv debug server (PID: ${p.pid}) is not responding`);
+				reject(new Error('timed out while waiting for DAP server to start'));
+			}, 30_000);
+
+			const stopWaitingForServerToStart = () => {
+				clearTimeout(timeoutToken);
+				started = true;
+				resolve(p);
+			};
+
+			if (continueOnStart) {
+				// wait till helloWorldServer starts and prints its log message to STDERR.
+				p.stderr.on('data', (chunk) => {
+					const msg = chunk.toString();
+					if (!started && msg.includes('helloWorldServer starting to listen on')) {
+						stopWaitingForServerToStart();
+					}
+					console.log(msg);
+				});
+			} else {
+				p.stdout.on('data', (chunk) => {
+					const msg = chunk.toString();
+					if (!started && msg.includes('listening at:')) {
+						stopWaitingForServerToStart();
+					}
+					console.log(msg);
+				});
+			}
+		});
+		return promise;
 	}
 
 	/**
@@ -438,7 +470,9 @@
 		// an initialized event.
 		await Promise.all([
 			new Promise<void>(async (resolve) => {
-				console.log(`Setting up attach request for ${JSON.stringify(debugConfig)}.`);
+				const debugConfigCopy = Object.assign({}, debugConfig);
+				delete debugConfigCopy.env;
+				console.log(`Setting up attach request for ${JSON.stringify(debugConfigCopy)}.`);
 				const attachResult = await dc.attachRequest(debugConfig as DebugProtocol.AttachRequestArguments);
 				assert.ok(attachResult.success);
 				resolve();
@@ -477,6 +511,24 @@
 	}
 
 	/**
+	 * Helper function to create a promise that's resolved when
+	 * output event with any of the provided strings is observed.
+	 */
+	async function waitForOutputMessage(dc: DebugClient, ...patterns: string[]): Promise<DebugProtocol.Event> {
+		return await new Promise<DebugProtocol.Event>((resolve, reject) => {
+			dc.on('output', (event) => {
+				for (const pattern of patterns) {
+					if (event.body.output.includes(pattern)) {
+						// Resolve when we have found the event that we want.
+						resolve(event);
+						return;
+					}
+				}
+			});
+		});
+	}
+
+	/**
 	 * Helper function to assert that a variable has a particular value.
 	 * This should be called when the program is stopped.
 	 *
@@ -555,6 +607,10 @@
 	});
 
 	suite('env', () => {
+		if (!isDlvDap) {
+			return;
+		}
+
 		let sandbox: sinon.SinonSandbox;
 
 		setup(() => {
@@ -619,6 +675,9 @@
 	});
 
 	suite('launch', () => {
+		if (!isDlvDap) {
+			return;
+		}
 		test('should run program to the end', async () => {
 			const PROGRAM = path.join(DATA_ROOT, 'baseTest');
 
@@ -734,7 +793,6 @@
 				this.skip(); // not working in dlv-dap.
 			}
 
-			// TODO(hyangah): why does it take 30sec?
 			const PROGRAM = path.join(DATA_ROOT, 'baseTest');
 			const config = {
 				name: 'Launch',
@@ -744,13 +802,16 @@
 				program: PROGRAM,
 				dlvFlags: ['--invalid']
 			};
-			try {
-				await initializeDebugConfig(config);
-				await dc.initializeRequest();
-			} catch (err) {
-				return;
-			}
-			throw new Error('does not report error on invalid delve flag');
+
+			await initializeDebugConfig(config);
+
+			await Promise.race([
+				// send an initialize request, which triggers launchDelveDAP
+				// from the thin adapter. We expect no response.
+				dc.initializeRequest().then(() => Promise.reject('unexpected initialization success')),
+				// we expect the useful error message.
+				waitForOutputMessage(dc, 'Error: unknown flag: --invalid')
+			]);
 		});
 
 		test('should run program with showLog=false and logOutput specified', async () => {
@@ -827,6 +888,9 @@
 	});
 
 	suite('set current working directory', () => {
+		if (!isDlvDap) {
+			return;
+		}
 		test('should debug program with cwd set', async () => {
 			const WD = path.join(DATA_ROOT, 'cwdTest');
 			const PROGRAM = path.join(WD, 'cwdTest');
@@ -907,15 +971,7 @@
 		});
 
 		async function waitForHelloGoodbyeOutput(dc: DebugClient): Promise<DebugProtocol.Event> {
-			return await new Promise<DebugProtocol.Event>((resolve, reject) => {
-				dc.on('output', (event) => {
-					if (event.body.output === 'Hello, World!\n' || event.body.output === 'Goodbye, World.\n') {
-						// Resolve when we have found the event that we want.
-						resolve(event);
-						return;
-					}
-				});
-			});
+			return waitForOutputMessage(dc, 'Hello, World!\n', 'Goodbye, World.\n');
 		}
 
 		test('should run program with cwd set (noDebug)', async () => {
@@ -993,6 +1049,9 @@
 	});
 
 	suite('remote attach', () => {
+		if (withConsole) {
+			return;
+		}
 		let childProcess: cp.ChildProcess;
 		let server: number;
 		let debugConfig: DebugConfiguration;
@@ -1093,6 +1152,11 @@
 			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));
 		});
 
+		// stop here for integrated terminal test mode.
+		if (withConsole) {
+			return;
+		}
+
 		test('stopped for a breakpoint set during initialization (remote attach)', async () => {
 			const FILE = path.join(DATA_ROOT, 'helloWorldServer', 'main.go');
 			const BREAKPOINT_LINE = 29;
@@ -1211,21 +1275,16 @@
 			]);
 		}
 
-		test('should set breakpoints during next', async function () {
-			if (!isDlvDap) {
-				this.skip();
-			}
+		// Skip this test because it is flaky.
+		test.skip('should set breakpoints during next', async () => {
 			await setBreakpointsWhileRunningStep(async () => {
 				const nextResponse = await dc.nextRequest({ threadId: 1 });
 				assert.ok(nextResponse.success);
 			});
 		});
 
-		test('should set breakpoints during step out', async function () {
-			if (!isDlvDap) {
-				this.skip();
-			}
-
+		// Skip this test because it is flaky.
+		test.skip('should set breakpoints during step out', async () => {
 			await setBreakpointsWhileRunningStep(async () => {
 				await Promise.all([dc.stepInRequest({ threadId: 1 }), dc.assertStoppedLocation('step', {})]);
 
@@ -1302,6 +1361,9 @@
 	});
 
 	suite('conditionalBreakpoints', () => {
+		if (withConsole) {
+			return;
+		}
 		test('should stop on conditional breakpoint', async () => {
 			const PROGRAM = path.join(DATA_ROOT, 'condbp');
 			const FILE = path.join(DATA_ROOT, 'condbp', 'condbp.go');
@@ -1436,6 +1498,9 @@
 	});
 
 	suite('panicBreakpoints', () => {
+		if (withConsole) {
+			return;
+		}
 		test('should stop on panic', async () => {
 			const PROGRAM_WITH_EXCEPTION = path.join(DATA_ROOT, 'panic');
 
@@ -1523,6 +1588,9 @@
 	});
 
 	suite('disconnect', () => {
+		if (withConsole) {
+			return;
+		}
 		// The teardown code for the Go Debug Adapter test suite issues a disconnectRequest.
 		// In order for these tests to pass, the debug adapter must not fail if a
 		// disconnectRequest is sent after it has already disconnected.
@@ -1728,7 +1796,7 @@
 		// has a chance to clean up.
 		// BUG(https://github.com/golang/vscode-go/issues/1993)
 		test('should cleanup when stopped', async function () {
-			if (!isDlvDap) {
+			if (!isDlvDap || affectedByIssue832()) {
 				this.skip();
 			}
 			const PROGRAM = path.join(DATA_ROOT, 'loop');
@@ -1779,6 +1847,9 @@
 	});
 
 	suite('switch goroutine', () => {
+		if (withConsole) {
+			return;
+		}
 		async function continueAndFindParkedGoroutine(file: string): Promise<number> {
 			// Find a goroutine that is stopped in parked.
 			const bp = getBreakpointLocation(file, 8);
@@ -1919,6 +1990,9 @@
 	});
 
 	suite('logDest attribute tests', () => {
+		if (!isDlvDap) {
+			return;
+		}
 		const PROGRAM = path.join(DATA_ROOT, 'baseTest');
 
 		let tmpDir: string;
@@ -1926,7 +2000,7 @@
 			tmpDir = fs.mkdtempSync(path.join(tmpdir(), 'logDestTest'));
 		});
 		suiteTeardown(() => {
-			rmdirRecursive(tmpDir);
+			tryRmdirRecursive(tmpDir);
 		});
 
 		test('logs are written to logDest file', async function () {
@@ -1990,6 +2064,9 @@
 	});
 
 	suite('substitute path', () => {
+		if (withConsole || affectedByIssue832()) {
+			return;
+		}
 		// TODO(suzmue): add unit tests for substitutePath.
 		let tmpDir: string;
 
@@ -1998,7 +2075,7 @@
 		});
 
 		suiteTeardown(() => {
-			rmdirRecursive(tmpDir);
+			tryRmdirRecursive(tmpDir);
 		});
 
 		function copyDirectory(name: string) {
@@ -2014,7 +2091,7 @@
 		async function buildGoProgram(cwd: string, outputFile: string): Promise<string> {
 			const goRuntimePath = getBinPath('go');
 			const execFile = util.promisify(cp.execFile);
-			const child = await execFile(goRuntimePath, ['build', '-o', outputFile, "--gcflags='all=-N -l'", '.'], {
+			const child = await execFile(goRuntimePath, ['build', '-o', outputFile, '--gcflags=all=-N -l', '.'], {
 				cwd
 			});
 			if (child.stderr.length > 0) {
@@ -2030,13 +2107,13 @@
 			});
 
 			suiteTeardown(() => {
-				rmdirRecursive(goBuildOutput);
+				tryRmdirRecursive(goBuildOutput);
 			});
 
 			async function copyBuildDelete(program: string): Promise<{ program: string; output: string }> {
 				const wd = copyDirectory(program);
 				const output = await buildGoProgram(wd, path.join(goBuildOutput, program));
-				rmdirRecursive(wd);
+				tryRmdirRecursive(wd);
 				return { program: wd, output };
 			}
 
@@ -2081,7 +2158,7 @@
 			});
 
 			suiteTeardown(() => {
-				rmdirRecursive(helloWorldLocal);
+				tryRmdirRecursive(helloWorldLocal);
 			});
 
 			test('stopped for a breakpoint set during initialization using substitutePath (remote attach)', async () => {
@@ -2149,7 +2226,7 @@
 			});
 			suiteTeardown(() => {
 				fs.unlinkSync(symlinkPath);
-				rmdirRecursive(realPath);
+				tryRmdirRecursive(realPath);
 			});
 			test('should stop on a breakpoint', async function () {
 				if (!isDlvDap) this.skip(); // BUG: the legacy adapter fails with 'breakpoint verification mismatch' error.
@@ -2227,6 +2304,9 @@
 };
 
 suite('Go Debug Adapter Tests (legacy)', function () {
+	if (affectedByIssue832()) {
+		return;
+	}
 	this.timeout(60_000);
 	testAll(this.ctx, false);
 });
@@ -2428,3 +2508,11 @@
 function sleep(ms: number) {
 	return new Promise((resolve) => setTimeout(resolve, ms));
 }
+
+function tryRmdirRecursive(dir: string) {
+	try {
+		rmdirRecursive(dir);
+	} catch (e) {
+		console.log(`failed to delete ${dir}: ${e}`);
+	}
+}
diff --git a/test/integration/goDebugConfiguration.test.ts b/test/integration/goDebugConfiguration.test.ts
index d95f9a6..8b9ab7f 100644
--- a/test/integration/goDebugConfiguration.test.ts
+++ b/test/integration/goDebugConfiguration.test.ts
@@ -14,6 +14,7 @@
 import goEnv = require('../../src/goEnv');
 import { MockCfg } from '../mocks/MockCfg';
 import { extensionId } from '../../src/const';
+import { affectedByIssue832 } from './testutils';
 
 suite('Debug Environment Variable Merge Test', () => {
 	const debugConfigProvider = new GoDebugConfigurationProvider();
@@ -630,6 +631,9 @@
 });
 
 suite('Debug Configuration Converts Relative Paths', () => {
+	if (affectedByIssue832()) {
+		return;
+	}
 	const debugConfigProvider = new GoDebugConfigurationProvider();
 
 	let workspaceDir = '';
diff --git a/test/integration/goExplorer.test.ts b/test/integration/goExplorer.test.ts
index 2cb3e83..27ce150 100644
--- a/test/integration/goExplorer.test.ts
+++ b/test/integration/goExplorer.test.ts
@@ -41,7 +41,7 @@
 		const [goenv, gomod] = (await explorer.getChildren(env)) as { key: string; value: string }[];
 		assert.strictEqual(goenv.key, 'GOENV');
 		assert.strictEqual(gomod.key, 'GOMOD');
-		assert.strictEqual(resolveHomeDir(gomod.value), `${fixtureDir}/go.mod`);
+		assert.strictEqual(resolveHomeDir(gomod.value), path.join(fixtureDir, 'go.mod'));
 	});
 
 	test('tools tree', async () => {
diff --git a/test/integration/goTest.run.test.ts b/test/integration/goTest.run.test.ts
index a16ad33..ac9ceaa 100644
--- a/test/integration/goTest.run.test.ts
+++ b/test/integration/goTest.run.test.ts
@@ -118,6 +118,10 @@
 	});
 
 	suite('Subtest', () => {
+		// WARNING: each call to testExplorer.runner.run triggers one or more
+		// `go test` command runs (testUtils.goTest is spied, not mocked or replaced).
+		// Each `go test` command invocation can take seconds on slow machines.
+		// As we add more cases, the timeout should be increased accordingly.
 		const sandbox = sinon.createSandbox();
 		const subTestDir = path.join(fixtureDir, 'subTest');
 		const ctx = MockExtensionContext.new();
@@ -214,6 +218,6 @@
 				'Failed to execute `go test`'
 			);
 			assert.strictEqual(spy.callCount, 0, 'expected no calls to goTest');
-		}).timeout(4000);
+		}).timeout(10000);
 	});
 });
diff --git a/test/integration/goTest.utils.ts b/test/integration/goTest.utils.ts
index 914ea18..caa727f 100644
--- a/test/integration/goTest.utils.ts
+++ b/test/integration/goTest.utils.ts
@@ -24,14 +24,14 @@
 	function walk(dir: Uri, modpath?: string) {
 		const dirs: Uri[] = [];
 		for (const [name, type] of workspace.fs.dirs.get(dir.toString()) ?? []) {
-			const uri = dir.with({ path: path.join(dir.path, name) });
+			const uri = Uri.file(path.join(dir.fsPath, name));
 			if (type === FileType.Directory) {
 				dirs.push(uri);
 			} else if (name === 'go.mod') {
-				modpath = dir.path;
+				modpath = dir.fsPath;
 			}
 		}
-		packagePathToGoModPathMap[dir.path] = modpath || '';
+		packagePathToGoModPathMap[dir.fsPath] = modpath || '';
 		for (const dir of dirs) {
 			walk(dir, modpath);
 		}
diff --git a/test/integration/install.test.ts b/test/integration/install.test.ts
index f14c028..18adf18 100644
--- a/test/integration/install.test.ts
+++ b/test/integration/install.test.ts
@@ -104,6 +104,9 @@
 
 		const missingTools = testCases.map((tc) => getToolAtVersion(tc.name));
 		const goVersion = await getGoVersion();
+
+		sandbox.stub(vscode.commands, 'executeCommand').withArgs('go.languageserver.restart');
+
 		await installTools(missingTools, goVersion);
 
 		// Confirm that each expected tool has been installed.
diff --git a/test/integration/testutils.ts b/test/integration/testutils.ts
new file mode 100644
index 0000000..7f85315
--- /dev/null
+++ b/test/integration/testutils.ts
@@ -0,0 +1,3 @@
+export function affectedByIssue832(): boolean {
+	return process.platform === 'win32';
+}
diff --git a/test/testdata/helloWorldServer/main.go b/test/testdata/helloWorldServer/main.go
index a1598af..ff35e27 100644
--- a/test/testdata/helloWorldServer/main.go
+++ b/test/testdata/helloWorldServer/main.go
@@ -16,8 +16,8 @@
 	if p := os.Getenv("PORT"); p != "" {
 		addr = ":" + p
 	}
-
-	log.Printf("server starting to listen on %s", addr)
+	// NOTE: goDebug.test.ts setupRemoteProgram expects this log message.
+	log.Printf("helloWorldServer starting to listen on %s", addr)
 	http.HandleFunc("/", home)
 	if err := http.ListenAndServe(addr, nil); err != nil {
 		log.Fatalf("server listen error: %+v", err)
@@ -26,6 +26,6 @@
 
 // home logs the received request and returns a simple response.
 func home(w http.ResponseWriter, r *http.Request) {
-	log.Printf("received request: %s %s", r.Method, r.URL.Path)
+	log.Printf("received request: %s %s", r.Method, r.URL.Path) // Breakpoint
 	fmt.Fprintf(w, "Hello, world!")
 }
diff --git a/tools/goplssetting/goplssetting.go b/tools/goplssetting/goplssetting.go
index e78d26c..b300ec1 100644
--- a/tools/goplssetting/goplssetting.go
+++ b/tools/goplssetting/goplssetting.go
@@ -17,10 +17,6 @@
 	"strings"
 )
 
-var skipHierarchy map[string]bool = map[string]bool{
-	"ui.inlayhint": true,
-}
-
 // Generate reads package.json and updates the gopls settings section
 // based on `gopls api-json` output. This function requires `jq` to
 // manipulate package.json.
@@ -185,22 +181,21 @@
 			return v[i].Name < v[j].Name
 		})
 	}
-	properties, err := collectProperties(seen)
+	goplsProperties, goProperties, err := collectProperties(seen)
 	if err != nil {
 		return nil, err
 	}
-	return json.Marshal(map[string]*Object{
-		"gopls": {
-			Type:                 "object",
-			MarkdownDescription:  "Configure the default Go language server ('gopls'). In most cases, configuring this section is unnecessary. See [the documentation](https://github.com/golang/tools/blob/master/gopls/doc/settings.md) for all available settings.",
-			Scope:                "resource",
-			AdditionalProperties: false,
-			Properties:           properties,
-		},
-	})
+	goProperties["gopls"] = &Object{
+		Type:                 "object",
+		MarkdownDescription:  "Configure the default Go language server ('gopls'). In most cases, configuring this section is unnecessary. See [the documentation](https://github.com/golang/tools/blob/master/gopls/doc/settings.md) for all available settings.",
+		Scope:                "resource",
+		AdditionalProperties: false,
+		Properties:           goplsProperties,
+	}
+	return json.Marshal(goProperties)
 }
 
-func collectProperties(m map[string][]*OptionJSON) (map[string]*Object, error) {
+func collectProperties(m map[string][]*OptionJSON) (goplsProperties, goProperties map[string]*Object, err error) {
 	var sorted []string
 	var containsEmpty bool
 	for k := range m {
@@ -214,9 +209,23 @@
 	if containsEmpty {
 		sorted = append(sorted, "")
 	}
-	properties := map[string]*Object{}
+	goplsProperties, goProperties = map[string]*Object{}, map[string]*Object{}
 	for _, hierarchy := range sorted {
-		if skip := skipHierarchy[hierarchy]; skip {
+		if hierarchy == "ui.inlayhint" {
+			for _, opt := range m[hierarchy] {
+				for _, k := range opt.EnumKeys.Keys {
+					unquotedName, err := strconv.Unquote(k.Name)
+					if err != nil {
+						return nil, nil, err
+					}
+					key := "go.inlayHints." + unquotedName
+					goProperties[key] = &Object{
+						MarkdownDescription: k.Doc,
+						Type:                "boolean",
+						Default:             formatDefault(k.Default, "boolean"),
+					}
+				}
+			}
 			continue
 		}
 		for _, opt := range m[hierarchy] {
@@ -237,7 +246,7 @@
 				for _, v := range opt.EnumValues {
 					unquotedName, err := strconv.Unquote(v.Value)
 					if err != nil {
-						return nil, err
+						return nil, nil, err
 					}
 					obj.Enum = append(obj.Enum, unquotedName)
 					obj.MarkdownEnumDescriptions = append(obj.MarkdownEnumDescriptions, v.Doc)
@@ -251,7 +260,7 @@
 				for _, k := range opt.EnumKeys.Keys {
 					unquotedName, err := strconv.Unquote(k.Name)
 					if err != nil {
-						return nil, err
+						return nil, nil, err
 					}
 					obj.Properties[unquotedName] = &Object{
 						Type:                propertyType(opt.EnumKeys.ValueType),
@@ -267,10 +276,10 @@
 			if hierarchy != "" {
 				key = hierarchy + "." + key
 			}
-			properties[key] = obj
+			goplsProperties[key] = obj
 		}
 	}
-	return properties, nil
+	return goplsProperties, goProperties, nil
 }
 
 func formatOptionDefault(opt *OptionJSON) interface{} {