sync: merge microsoft/vscode-go@f3dd04b into master
Change-Id: I818414713f9e6f1561ddaef5d741c7c3ef2592c9
diff --git a/.travis.yml b/.travis.yml
index b454685..54cf743 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -54,6 +54,7 @@
- go get -u -v github.com/zmb3/gogetdoc
- go get -u -v golang.org/x/lint/golint
- go get -u -v golang.org/x/tools/cmd/gorename
+ - GO111MODULE=on go get golang.org/x/tools/gopls
script:
- npm run lint
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 481c0d9..ac1e019 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -44,7 +44,7 @@
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/integration/index",
"--timeout",
- "999999",
+ "999999"
],
"stopOnEntry": false,
"sourceMaps": true,
@@ -54,6 +54,27 @@
"preLaunchTask": "npm: watch"
},
{
+ "name": "Launch Extension Tests with Gopls",
+ "type": "extensionHost",
+ "request": "launch",
+ "runtimeExecutable": "${execPath}",
+ // the workspace path should be GOPATH
+ "args": [
+ "--disable-extensions",
+ "--extensionDevelopmentPath=${workspaceFolder}",
+ "--extensionTestsPath=${workspaceFolder}/out/test/gopls/index",
+ "--user-data-dir", "${workspaceFolder}/test/gopls/testfixtures/src/workspace",
+ "--timeout", "999999",
+ "${workspaceFolder}/test/gopls/testfixtures/src/workspace" // gopls requires a workspace to work with.
+ ],
+ "stopOnEntry": false,
+ "sourceMaps": true,
+ "outFiles": [
+ "${workspaceFolder}/out/test/**/*.js"
+ ],
+ "preLaunchTask": "npm: watch",
+ },
+ {
"type": "node",
"request": "launch",
"name": "Launch Unit Tests",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40010f2..e6305a4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,34 @@
+## 0.14.2 - Coming Soon...
+
+* [Hyang-Ah Hana Kim (@hyangah)](https://github.com/hyangah)
+ * Allow debugging when having multiple versions of Go. Fixes [Bug 3152](https://github.com/Microsoft/vscode-go/issues/3152) with [PR 3159](https://github.com/Microsoft/vscode-go/pull/3159)
+ * Fix bug introduced in the last update where there is no prompt to install/update `gopls`. Fixes [Bug 3194](https://github.com/Microsoft/vscode-go/issues/3194) with [PR 3197](https://github.com/Microsoft/vscode-go/pull/3197)
+
+* [@tom-shan](https://github.com/tom-shan)
+ * Fix placeholder in the debug configuration snippet for debugging single file. Fixes [Bug 3154](https://github.com/Microsoft/vscode-go/issues/3154) with [PR 3155](https://github.com/Microsoft/vscode-go/pull/3155)
+
+* [Rebecca Stambler (@stamblerre)](https://github.com/stamblerre)
+ * When using the language server, drop support for disabling `format` and `highlight` features. [PR 3156](https://github.com/Microsoft/vscode-go/pull/3156)
+
+* [Mike Patnode (@mpatnode)](https://github.com/mpatnode)
+ * Add note to use WSL 2 for debugging to work in Windows Subsystem for Linux. [PR 3167](https://github.com/Microsoft/vscode-go/pull/3167)
+
+* [mo2zie (@stdupp)](https://github.com/stdupp)
+ * Fix the `Go: Fill struct` to work correctly when file has multi byte characters. [PR 2611](https://github.com/Microsoft/vscode-go/pull/2611)
+
+* [Kegsay @Kegsay](https://github.com/Kegsay)
+ * Invalidate applied code coverage on file save instead of on file change. Fixes [Bug 2551](https://github.com/Microsoft/vscode-go/issues/2551) with [PR 2853](https://github.com/Microsoft/vscode-go/pull/2853)
+
+* [Felipe Munhoz (@fnmunhoz)](https://github.com/fnmunhoz)
+ * Allow setting breakpoints on a file from the module cache. [PR 3079](https://github.com/Microsoft/vscode-go/pull/3079)
+
+* [@neclepsio](https://github.com/neclepsio)
+ * Fix bug where gopls does not start behind a blocking proxy. Fixes [Bug 3204](https://github.com/Microsoft/vscode-go/issues/3204) with [PR 3205](https://github.com/Microsoft/vscode-go/pull/3205)
+
+* [@polinasok](https://github.com/https://github.com/polinasok)
+ * Improve the error message seen when debugging for "bad access". [PR 3196](https://github.com/Microsoft/vscode-go/pull/3196)
+
+
## 0.14.1 - 15th April, 2020
* [Ramya Rao (@ramya-rao-a)](https://github.com/ramya-rao-a)
diff --git a/package-lock.json b/package-lock.json
index 1750715..3d865ca 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -75,6 +75,12 @@
"integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==",
"dev": true
},
+ "@types/deep-equal": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@types/deep-equal/-/deep-equal-1.0.1.tgz",
+ "integrity": "sha512-mMUu4nWHLBlHtxXY17Fg6+ucS/MnndyOWyOe7MmwkoMYxvfQU2ajtRaEvqSUv+aVkMqH/C0NCI8UoVfRNQ10yg==",
+ "dev": true
+ },
"@types/events": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
@@ -114,9 +120,9 @@
"dev": true
},
"@types/node": {
- "version": "13.11.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz",
- "integrity": "sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==",
+ "version": "13.13.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.0.tgz",
+ "integrity": "sha512-WE4IOAC6r/yBZss1oQGM5zs2D7RuKR6Q+w+X2SouPofnWn+LbCqClRyhO3ZE7Ix8nmFgo/oVuuE01cJT2XB13A==",
"dev": true
},
"@types/semver": {
@@ -220,6 +226,11 @@
"sprintf-js": "~1.0.2"
}
},
+ "array-filter": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
+ "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM="
+ },
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -268,6 +279,14 @@
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
"dev": true
},
+ "available-typed-arrays": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz",
+ "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==",
+ "requires": {
+ "array-filter": "^1.0.0"
+ }
+ },
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
@@ -510,11 +529,37 @@
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true
},
+ "deep-equal": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.2.tgz",
+ "integrity": "sha512-kX0bjV7tdMuhrhzKPEnVwqfQCuf+IEfN+4Xqv4eKd75xGRyn8yzdQ9ujPY6a221rgJKyQC4KBu1PibDTpa6m9w==",
+ "requires": {
+ "es-abstract": "^1.17.5",
+ "es-get-iterator": "^1.1.0",
+ "is-arguments": "^1.0.4",
+ "is-date-object": "^1.0.2",
+ "is-regex": "^1.0.5",
+ "isarray": "^2.0.5",
+ "object-is": "^1.0.2",
+ "object-keys": "^1.1.1",
+ "regexp.prototype.flags": "^1.3.0",
+ "side-channel": "^1.0.2",
+ "which-boxed-primitive": "^1.0.1",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.1"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
+ }
+ }
+ },
"define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "dev": true,
"requires": {
"object-keys": "^1.0.12"
}
@@ -576,7 +621,6 @@
"version": "1.17.5",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
"integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
- "dev": true,
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
@@ -591,11 +635,31 @@
"string.prototype.trimright": "^2.1.1"
}
},
+ "es-get-iterator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz",
+ "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==",
+ "requires": {
+ "es-abstract": "^1.17.4",
+ "has-symbols": "^1.0.1",
+ "is-arguments": "^1.0.4",
+ "is-map": "^2.0.1",
+ "is-set": "^2.0.1",
+ "is-string": "^1.0.5",
+ "isarray": "^2.0.5"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
+ }
+ }
+ },
"es-to-primitive": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
"requires": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
@@ -697,6 +761,11 @@
"is-buffer": "~2.0.3"
}
},
+ "foreach": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
+ },
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
@@ -740,8 +809,7 @@
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"get-caller-file": {
"version": "2.0.5",
@@ -810,7 +878,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
"requires": {
"function-bind": "^1.1.1"
}
@@ -824,8 +891,7 @@
"has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
- "dev": true
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
},
"he": {
"version": "1.2.0",
@@ -912,6 +978,16 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
+ "is-arguments": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
+ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA=="
+ },
+ "is-bigint": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.0.tgz",
+ "integrity": "sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g=="
+ },
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -921,6 +997,11 @@
"binary-extensions": "^2.0.0"
}
},
+ "is-boolean-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz",
+ "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ=="
+ },
"is-buffer": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
@@ -930,14 +1011,12 @@
"is-callable": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
- "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
- "dev": true
+ "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q=="
},
"is-date-object": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
- "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
- "dev": true
+ "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
},
"is-extglob": {
"version": "2.1.1",
@@ -960,35 +1039,74 @@
"is-extglob": "^2.1.1"
}
},
+ "is-map": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz",
+ "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw=="
+ },
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
+ "is-number-object": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
+ "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw=="
+ },
"is-regex": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
"integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
- "dev": true,
"requires": {
"has": "^1.0.3"
}
},
+ "is-set": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz",
+ "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA=="
+ },
+ "is-string": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
+ "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ=="
+ },
"is-symbol": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
"integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
- "dev": true,
"requires": {
"has-symbols": "^1.0.1"
}
},
+ "is-typed-array": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz",
+ "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==",
+ "requires": {
+ "available-typed-arrays": "^1.0.0",
+ "es-abstract": "^1.17.4",
+ "foreach": "^2.0.5",
+ "has-symbols": "^1.0.1"
+ }
+ },
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
+ "is-weakmap": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+ "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA=="
+ },
+ "is-weakset": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz",
+ "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw=="
+ },
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
@@ -1039,6 +1157,13 @@
"jsonparse": "1.x.x",
"lodash": "3.x.x",
"object-assign": "4.x"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+ }
}
},
"json-schema": {
@@ -1099,9 +1224,10 @@
}
},
"lodash": {
- "version": "3.10.1",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
- "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "dev": true
},
"lodash.get": {
"version": "4.4.2",
@@ -1291,20 +1417,26 @@
"object-inspect": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
- "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
- "dev": true
+ "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
+ },
+ "object-is": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz",
+ "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
"object.assign": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
- "dev": true,
"requires": {
"define-properties": "^1.1.2",
"function-bind": "^1.1.1",
@@ -1423,6 +1555,15 @@
"picomatch": "^2.0.4"
}
},
+ "regexp.prototype.flags": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
+ "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0-next.1"
+ }
+ },
"request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
@@ -1463,9 +1604,9 @@
"dev": true
},
"resolve": {
- "version": "1.16.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.0.tgz",
- "integrity": "sha512-LarL/PIKJvc09k1jaeT4kQb/8/7P+qV4qSnN2K80AES+OHdfZELAKVOBjxsvtToT/uLOfFbvYvKfZmV8cee7nA==",
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz",
+ "integrity": "sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig==",
"dev": true,
"requires": {
"path-parse": "^1.0.6"
@@ -1506,6 +1647,15 @@
"resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",
"integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="
},
+ "side-channel": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz",
+ "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==",
+ "requires": {
+ "es-abstract": "^1.17.0-next.1",
+ "object-inspect": "^1.7.0"
+ }
+ },
"sinon": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.2.tgz",
@@ -1579,7 +1729,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
"integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
- "dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
@@ -1589,7 +1738,6 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
"integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
- "dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5",
@@ -1600,7 +1748,6 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
"integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
- "dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5",
@@ -1611,7 +1758,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
"integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
- "dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
@@ -1790,12 +1936,12 @@
"integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A=="
},
"vscode-languageclient": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz",
- "integrity": "sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.0.tgz",
+ "integrity": "sha512-Tcp0VoOaa0YzxL4nEfK9tsmcy76Eo8jNLvFQZwh2c8oMm02luL8uGYPLQNAiZ3XGgegfcwiQFZMqbW7DNV0vxA==",
"requires": {
"semver": "^6.3.0",
- "vscode-languageserver-protocol": "^3.15.3"
+ "vscode-languageserver-protocol": "^3.15.2"
},
"dependencies": {
"semver": {
@@ -1862,12 +2008,48 @@
"isexe": "^2.0.0"
}
},
+ "which-boxed-primitive": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz",
+ "integrity": "sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==",
+ "requires": {
+ "is-bigint": "^1.0.0",
+ "is-boolean-object": "^1.0.0",
+ "is-number-object": "^1.0.3",
+ "is-string": "^1.0.4",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "which-collection": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+ "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+ "requires": {
+ "is-map": "^2.0.1",
+ "is-set": "^2.0.1",
+ "is-weakmap": "^2.0.1",
+ "is-weakset": "^2.0.1"
+ }
+ },
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
"dev": true
},
+ "which-typed-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz",
+ "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==",
+ "requires": {
+ "available-typed-arrays": "^1.0.2",
+ "es-abstract": "^1.17.5",
+ "foreach": "^2.0.5",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.1",
+ "is-typed-array": "^1.1.3"
+ }
+ },
"wide-align": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
@@ -1993,14 +2175,6 @@
"flat": "^4.1.0",
"lodash": "^4.17.15",
"yargs": "^13.3.0"
- },
- "dependencies": {
- "lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
- "dev": true
- }
}
}
}
diff --git a/package.json b/package.json
index 2ec6eda..d4f6d54 100644
--- a/package.json
+++ b/package.json
@@ -53,8 +53,9 @@
"vscode-debugadapter": "^1.40.0",
"vscode-debugprotocol": "^1.40.0",
"vscode-extension-telemetry": "^0.1.2",
- "vscode-languageclient": "^6.1.3",
- "web-request": "^1.0.7"
+ "vscode-languageclient": "6.1.0",
+ "web-request": "^1.0.7",
+ "deep-equal": "^2.0.2"
},
"devDependencies": {
"@types/fs-extra": "^8.1.0",
@@ -71,7 +72,8 @@
"sinon": "^9.0.2",
"tslint": "^6.1.1",
"typescript": "^3.8.3",
- "vscode-test": "^1.3.0"
+ "vscode-test": "^1.3.0",
+ "@types/deep-equal": "^1.0.1"
},
"engines": {
"vscode": "^1.41.0"
diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts
index 4181998..687b61b 100644
--- a/src/debugAdapter/goDebug.ts
+++ b/src/debugAdapter/goDebug.ts
@@ -1833,21 +1833,19 @@
}
let errorMessage = err.toString();
- // Handle unpropagated fatalpanic errors with a more user friendly message:
+ // Use a more user friendly message for an unpropagated SIGSEGV (EXC_BAD_ACCESS)
+ // signal that delve is unable to send back to the target process to be
+ // handled as a panic.
// https://github.com/microsoft/vscode-go/issues/1903#issuecomment-460126884
// https://github.com/go-delve/delve/issues/852
- // This affects macOS only although we're agnostic of the OS at this stage, only handle the error
+ // This affects macOS only although we're agnostic of the OS at this stage.
if (errorMessage === 'bad access') {
+ // Reuse the panic message from the Go runtime.
errorMessage =
- 'unpropagated fatalpanic: signal SIGSEGV (EXC_BAD_ACCESS). This fatalpanic is not traceable on macOS, see https://github.com/go-delve/delve/issues/852';
+ `runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation]\nUnable to propogate EXC_BAD_ACCESS signal to target process and panic (see https://github.com/go-delve/delve/issues/852)`;
}
logError(message + ' - ' + errorMessage);
-
- if (errorMessage === 'bad access') {
- logError('WARNING: this stack might not be from the expected active goroutine');
- }
-
this.dumpStacktrace();
}
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index 60ccce9..60a7144 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -543,9 +543,7 @@
(tool) =>
new Promise<Tool>((resolve, reject) => {
const toolPath = getBinPath(tool.name);
- fs.exists(toolPath, (exists) => {
- resolve(exists ? null : tool);
- });
+ resolve(path.isAbsolute(toolPath) ? null : tool);
})
)
).then((res) => {
diff --git a/src/goLanguageServer.ts b/src/goLanguageServer.ts
index 909ac7a..746969c 100644
--- a/src/goLanguageServer.ts
+++ b/src/goLanguageServer.ts
@@ -6,6 +6,7 @@
'use strict';
import cp = require('child_process');
+import deepEqual = require('deep-equal');
import moment = require('moment');
import path = require('path');
import semver = require('semver');
@@ -13,36 +14,24 @@
import vscode = require('vscode');
import {
Command,
- FormattingOptions,
HandleDiagnosticsSignature,
LanguageClient,
ProvideCompletionItemsSignature,
- ProvideDocumentFormattingEditsSignature,
ProvideDocumentLinksSignature,
RevealOutputChannelOn
} from 'vscode-languageclient';
import WebRequest = require('web-request');
-import { GoDefinitionProvider } from './goDeclaration';
-import { GoHoverProvider } from './goExtraInfo';
-import { GoDocumentFormattingEditProvider } from './goFormat';
-import { GoImplementationProvider } from './goImplementations';
import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
-import { parseLiveFile } from './goLiveErrors';
-import { GO_MODE } from './goMode';
-import { GoDocumentSymbolProvider } from './goOutline';
import { getToolFromToolPath } from './goPath';
-import { GoReferenceProvider } from './goReferences';
-import { GoRenameProvider } from './goRename';
-import { GoSignatureHelpProvider } from './goSignature';
-import { GoCompletionItemProvider } from './goSuggest';
-import { GoWorkspaceSymbolProvider } from './goSymbol';
import { getTool, Tool } from './goTools';
-import { GoTypeDefinitionProvider } from './goTypeDefinition';
import { getBinPath, getCurrentGoPath, getGoConfig, getToolsEnvVars } from './util';
interface LanguageServerConfig {
+ serverName: string;
+ path: string;
enabled: boolean;
flags: string[];
+ env: any;
features: {
diagnostics: boolean;
documentLink: boolean;
@@ -50,48 +39,91 @@
checkForUpdates: boolean;
}
-// registerLanguageFeatures registers providers for all the language features.
-// It looks to either the language server or the standard providers for these features.
-export async function registerLanguageFeatures(ctx: vscode.ExtensionContext) {
+// Global variables used for management of the language client.
+// They are global so that the server can be easily restarted with
+// new configurations.
+let languageClient: LanguageClient;
+let languageServerDisposable: vscode.Disposable;
+let latestConfig: LanguageServerConfig;
+let serverOutputChannel: vscode.OutputChannel;
+
+// startLanguageServer starts the language server (if enabled), returning
+// true on success.
+export async function registerLanguageFeatures(ctx: vscode.ExtensionContext): Promise<boolean> {
// Subscribe to notifications for changes to the configuration of the language server.
ctx.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e) => watchLanguageServerConfiguration(e)));
const config = parseLanguageServerConfig();
-
- // If the user has not enabled the language server,
- // register the default language features and return.
if (!config.enabled) {
- registerUsualProviders(ctx);
- return;
+ return false;
}
- // The user has opted into the language server.
- const languageServerToolPath = getLanguageServerToolPath();
- const toolName = getToolFromToolPath(languageServerToolPath);
- if (!toolName) {
- // language server binary is not installed yet.
- // Return immediately. The information messages such as
- // offering to install missing tools, and suggesting to
- // reload the window after installing the language server
- // should be presented by now.
- return;
- }
- const env = getToolsEnvVars();
+ // Support a command to restart the language server, if it's enabled.
+ ctx.subscriptions.push(vscode.commands.registerCommand('go.languageserver.restart', () => {
+ return startLanguageServer(ctx, parseLanguageServerConfig());
+ }));
- // If installed, check. The user may not have the most up-to-date version of the language server.
- const tool = getTool(toolName);
- const versionToUpdate = await shouldUpdateLanguageServer(tool, languageServerToolPath, config.checkForUpdates);
-
- if (versionToUpdate) {
- promptForUpdatingTool(toolName, versionToUpdate);
+ // If the language server is gopls, we can check if the user needs to
+ // update their gopls version.
+ if (config.serverName === 'gopls') {
+ const tool = getTool(config.serverName);
+ if (!tool) {
+ return false;
+ }
+ const versionToUpdate = await shouldUpdateLanguageServer(tool, config.path, config.checkForUpdates);
+ if (versionToUpdate) {
+ promptForUpdatingTool(tool.name);
+ }
}
- const c = new LanguageClient(
- toolName,
+ // This function handles the case when the server isn't started yet,
+ // so we can call it to start the language server.
+ return startLanguageServer(ctx, config);
+}
+
+async function startLanguageServer(ctx: vscode.ExtensionContext, config: LanguageServerConfig): Promise<boolean> {
+ // If the client has already been started, make sure to clear existing
+ // diagnostics and stop it.
+ if (languageClient) {
+ if (languageClient.diagnostics) {
+ languageClient.diagnostics.clear();
+ }
+ await languageClient.stop();
+ if (languageServerDisposable) {
+ languageServerDisposable.dispose();
+ }
+ }
+
+ // Check if we should recreate the language client. This may be necessary
+ // if the user has changed settings in their config.
+ if (!deepEqual(latestConfig, config)) {
+ // Track the latest config used to start the language server.
+ latestConfig = config;
+
+ // If the user has not enabled or installed the language server, return.
+ if (!config.enabled || !config.path) {
+ return false;
+ }
+ buildLanguageClient(config);
+ }
+
+ languageServerDisposable = languageClient.start();
+ ctx.subscriptions.push(languageServerDisposable);
+
+ return true;
+}
+
+function buildLanguageClient(config: LanguageServerConfig) {
+ // Reuse the same output channel for each instance of the server.
+ if (!serverOutputChannel) {
+ serverOutputChannel = vscode.window.createOutputChannel(config.serverName);
+ }
+ languageClient = new LanguageClient(
+ config.serverName,
{
- command: languageServerToolPath,
+ command: config.path,
args: ['-mode=stdio', ...config.flags],
- options: { env }
+ options: { env: config.env },
},
{
initializationOptions: {},
@@ -102,6 +134,7 @@
(uri.scheme ? uri : uri.with({ scheme: 'file' })).toString(),
protocol2Code: (uri: string) => vscode.Uri.parse(uri)
},
+ outputChannel: serverOutputChannel,
revealOutputChannelOn: RevealOutputChannelOn.Never,
middleware: {
handleDiagnostics: (
@@ -179,30 +212,14 @@
}
}
);
-
- c.onReady().then(() => {
- const capabilities = c.initializeResult && c.initializeResult.capabilities;
+ languageClient.onReady().then(() => {
+ const capabilities = languageClient.initializeResult && languageClient.initializeResult.capabilities;
if (!capabilities) {
return vscode.window.showErrorMessage(
'The language server is not able to serve any features at the moment.'
);
}
});
-
- let languageServerDisposable = c.start();
- ctx.subscriptions.push(languageServerDisposable);
-
- ctx.subscriptions.push(
- vscode.commands.registerCommand('go.languageserver.restart', async () => {
- if (c.diagnostics) {
- c.diagnostics.clear();
- }
- await c.stop();
- languageServerDisposable.dispose();
- languageServerDisposable = c.start();
- ctx.subscriptions.push(languageServerDisposable);
- })
- );
}
function watchLanguageServerConfiguration(e: vscode.ConfigurationChangeEvent) {
@@ -242,8 +259,12 @@
export function parseLanguageServerConfig(): LanguageServerConfig {
const goConfig = getGoConfig();
-
- const config = {
+ const toolsEnv = getToolsEnvVars();
+ const languageServerPath = getLanguageServerToolPath();
+ const languageServerName = getToolFromToolPath(languageServerPath);
+ return {
+ serverName: languageServerName,
+ path: languageServerPath,
enabled: goConfig['useLanguageServer'],
flags: goConfig['languageServerFlags'] || [],
features: {
@@ -252,9 +273,9 @@
diagnostics: goConfig['languageServerExperimentalFeatures']['diagnostics'],
documentLink: goConfig['languageServerExperimentalFeatures']['documentLink']
},
+ env: toolsEnv,
checkForUpdates: goConfig['useGoProxyToCheckForToolUpdates']
};
- return config;
}
/**
@@ -298,9 +319,10 @@
if (alternateTools['go-langserver']) {
vscode.window.showErrorMessage(`Support for "go-langserver" has been deprecated.
The recommended language server is gopls. Delete the alternate tool setting for "go-langserver" to use gopls, or change "go-langserver" to "gopls" in your settings.json and reload the VS Code window.`);
+ return;
}
- return;
}
+
// Prompt the user to install gopls.
promptForMissingTool('gopls');
}
@@ -313,28 +335,6 @@
return vscode.workspace.workspaceFolders.find((x) => tempGopath !== getCurrentGoPath(x.uri)) ? false : true;
}
-// registerUsualProviders registers the language feature providers if the language server is not enabled.
-function registerUsualProviders(ctx: vscode.ExtensionContext) {
- const provider = new GoCompletionItemProvider(ctx.globalState);
- ctx.subscriptions.push(provider);
- ctx.subscriptions.push(vscode.languages.registerCompletionItemProvider(GO_MODE, provider, '.', '"'));
- ctx.subscriptions.push(vscode.languages.registerHoverProvider(GO_MODE, new GoHoverProvider()));
- ctx.subscriptions.push(vscode.languages.registerDefinitionProvider(GO_MODE, new GoDefinitionProvider()));
- ctx.subscriptions.push(vscode.languages.registerReferenceProvider(GO_MODE, new GoReferenceProvider()));
- ctx.subscriptions.push(vscode.languages.registerDocumentSymbolProvider(GO_MODE, new GoDocumentSymbolProvider()));
- ctx.subscriptions.push(vscode.languages.registerWorkspaceSymbolProvider(new GoWorkspaceSymbolProvider()));
- ctx.subscriptions.push(
- vscode.languages.registerSignatureHelpProvider(GO_MODE, new GoSignatureHelpProvider(), '(', ',')
- );
- ctx.subscriptions.push(vscode.languages.registerImplementationProvider(GO_MODE, new GoImplementationProvider()));
- ctx.subscriptions.push(
- vscode.languages.registerDocumentFormattingEditProvider(GO_MODE, new GoDocumentFormattingEditProvider())
- );
- ctx.subscriptions.push(vscode.languages.registerTypeDefinitionProvider(GO_MODE, new GoTypeDefinitionProvider()));
- ctx.subscriptions.push(vscode.languages.registerRenameProvider(GO_MODE, new GoRenameProvider()));
- vscode.workspace.onDidChangeTextDocument(parseLiveFile, null, ctx.subscriptions);
-}
-
const acceptGoplsPrerelease = true; // For nightly, we accept the prerelease version.
const defaultLatestVersion = semver.coerce('0.3.1');
const defaultLatestVersionTime = moment('2020-02-04', 'YYYY-MM-DD');
@@ -454,7 +454,9 @@
includePrerelease: true,
loose: true
});
- versions.push(parsed);
+ if (parsed) {
+ versions.push(parsed);
+ }
}
if (versions.length === 0) {
return null;
diff --git a/src/goMain.ts b/src/goMain.ts
index b5ac805..7f34b11 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -21,11 +21,15 @@
updateCodeCoverageDecorators
} from './goCover';
import { GoDebugConfigurationProvider } from './goDebugConfiguration';
+import { GoDefinitionProvider } from './goDeclaration';
import { extractFunction, extractVariable } from './goDoctor';
+import { GoHoverProvider } from './goExtraInfo';
import { runFillStruct } from './goFillStruct';
+import { GoDocumentFormattingEditProvider } from './goFormat';
import * as goGenerateTests from './goGenerateTests';
import { goGetPackage } from './goGetPackage';
import { implCursor } from './goImpl';
+import { GoImplementationProvider } from './goImplementations';
import { addImport, addImportToWorkspace } from './goImport';
import { installCurrentPackage } from './goInstall';
import {
@@ -37,16 +41,24 @@
} from './goInstallTools';
import { registerLanguageFeatures } from './goLanguageServer';
import { lintCode } from './goLint';
+import { parseLiveFile } from './goLiveErrors';
import { GO_MODE } from './goMode';
import { addTags, removeTags } from './goModifytags';
import { GO111MODULE, isModSupported } from './goModules';
+import { GoDocumentSymbolProvider } from './goOutline';
import { clearCacheForTools, fileExists } from './goPath';
import { playgroundCommand } from './goPlayground';
+import { GoReferenceProvider } from './goReferences';
import { GoReferencesCodeLensProvider } from './goReferencesCodelens';
+import { GoRenameProvider } from './goRename';
import { GoRunTestCodeLensProvider } from './goRunTestCodelens';
+import { GoSignatureHelpProvider } from './goSignature';
import { outputChannel, showHideStatus } from './goStatus';
+import { GoCompletionItemProvider } from './goSuggest';
+import { GoWorkspaceSymbolProvider } from './goSymbol';
import { testAtCursor, testCurrentFile, testCurrentPackage, testPrevious, testWorkspace } from './goTest';
import { getConfiguredTools } from './goTools';
+import { GoTypeDefinitionProvider } from './goTypeDefinition';
import { vetCode } from './goVet';
import {
getFromGlobalState,
@@ -134,7 +146,10 @@
// This handles all of the configurations and registrations for the language server.
// It also registers the necessary language feature providers that the language server may not support.
- await registerLanguageFeatures(ctx);
+ const ok = await registerLanguageFeatures(ctx);
+ if (!ok) {
+ registerUsualProviders(ctx);
+ }
if (
vscode.window.activeTextEditor &&
@@ -607,6 +622,28 @@
);
}
+// registerUsualProviders registers the language feature providers if the language server is not enabled.
+function registerUsualProviders(ctx: vscode.ExtensionContext) {
+ const provider = new GoCompletionItemProvider(ctx.globalState);
+ ctx.subscriptions.push(provider);
+ ctx.subscriptions.push(vscode.languages.registerCompletionItemProvider(GO_MODE, provider, '.', '"'));
+ ctx.subscriptions.push(vscode.languages.registerHoverProvider(GO_MODE, new GoHoverProvider()));
+ ctx.subscriptions.push(vscode.languages.registerDefinitionProvider(GO_MODE, new GoDefinitionProvider()));
+ ctx.subscriptions.push(vscode.languages.registerReferenceProvider(GO_MODE, new GoReferenceProvider()));
+ ctx.subscriptions.push(vscode.languages.registerDocumentSymbolProvider(GO_MODE, new GoDocumentSymbolProvider()));
+ ctx.subscriptions.push(vscode.languages.registerWorkspaceSymbolProvider(new GoWorkspaceSymbolProvider()));
+ ctx.subscriptions.push(
+ vscode.languages.registerSignatureHelpProvider(GO_MODE, new GoSignatureHelpProvider(), '(', ',')
+ );
+ ctx.subscriptions.push(vscode.languages.registerImplementationProvider(GO_MODE, new GoImplementationProvider()));
+ ctx.subscriptions.push(
+ vscode.languages.registerDocumentFormattingEditProvider(GO_MODE, new GoDocumentFormattingEditProvider())
+ );
+ ctx.subscriptions.push(vscode.languages.registerTypeDefinitionProvider(GO_MODE, new GoTypeDefinitionProvider()));
+ ctx.subscriptions.push(vscode.languages.registerRenameProvider(GO_MODE, new GoRenameProvider()));
+ vscode.workspace.onDidChangeTextDocument(parseLiveFile, null, ctx.subscriptions);
+}
+
function addOnChangeTextDocumentListeners(ctx: vscode.ExtensionContext) {
vscode.workspace.onDidChangeTextDocument(trackCodeCoverageRemovalOnFileChange, null, ctx.subscriptions);
vscode.workspace.onDidChangeTextDocument(removeTestStatus, null, ctx.subscriptions);
diff --git a/test/gopls/extension.test.ts b/test/gopls/extension.test.ts
new file mode 100644
index 0000000..3d59143
--- /dev/null
+++ b/test/gopls/extension.test.ts
@@ -0,0 +1,135 @@
+import * as assert from 'assert';
+import cp = require('child_process');
+import * as fs from 'fs-extra';
+import * as path from 'path';
+import * as vscode from 'vscode';
+import { updateGoPathGoRootFromConfig } from '../../src/goInstallTools';
+import { extensionId } from '../../src/telemetry';
+import { getCurrentGoPath } from '../../src/util';
+
+// Env is a collection of test related variables
+// that define the test environment such as vscode workspace.
+class Env {
+
+ // Currently gopls requires a workspace and does not work in a single-file mode.
+ // Code in test environment does not support dynamically adding folders.
+ // tslint:disable-next-line:max-line-length
+ // https://github.com/microsoft/vscode/blob/890f62dfd9f3e70198931f788c5c332b3e8b7ad7/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts#L281
+ //
+ // So, when we start the gopls tests, we start the test extension host with a
+ // dummy workspace, ${projectDir}/test/gopls/testfixtures/src/workspace
+ // (see test/runTest.ts and launch.json).
+ // Then copy necessary files to the workspace using Env.reset() from the
+ // fixturesRoot directory.
+ public workspaceDir: string;
+ public fixturesRoot: string;
+
+ public extension: vscode.Extension<any>;
+
+ constructor(projectDir: string) {
+ if (!projectDir) {
+ assert.fail('project directory cannot be determined');
+ }
+ this.workspaceDir = path.resolve(projectDir, 'test/gopls/testfixtures/src/workspace');
+ this.fixturesRoot = path.resolve(projectDir, 'test/fixtures');
+ this.extension = vscode.extensions.getExtension(extensionId);
+
+ // Ensure the vscode extension host is configured as expected.
+ const workspaceFolder = path.resolve(vscode.workspace.workspaceFolders[0].uri.fsPath);
+ if (this.workspaceDir !== workspaceFolder) {
+ assert.fail(`specified workspaceDir: ${this.workspaceDir} does not match the workspace folder: ${workspaceFolder}`);
+ }
+ }
+
+ public async setup() {
+ const wscfg = vscode.workspace.getConfiguration('go');
+ if (!wscfg.get('useLanguageServer')) {
+ wscfg.update('useLanguageServer', true, vscode.ConfigurationTarget.Workspace);
+ }
+
+ await this.reset();
+ await this.extension.activate();
+ await sleep(2000); // allow extension host + gopls to start.
+ }
+
+ public async reset(fixtureDirName?: string) { // name of the fixtures subdirectory to use.
+ try {
+ // clean everything except the .gitignore file
+ // needed to keep the empty directory in vcs.
+ await fs.readdir(this.workspaceDir).then((files) => {
+ return Promise.all(
+ files.filter((filename) => filename !== '.gitignore').map((file) => {
+ fs.remove(path.resolve(this.workspaceDir, file));
+ }));
+ });
+
+ if (!fixtureDirName) {
+ return;
+ }
+ const src = path.resolve(this.fixturesRoot, fixtureDirName);
+ const dst = this.workspaceDir;
+ await fs.copy(src, dst, { recursive: true });
+ } catch (err) {
+ assert.fail(err);
+ }
+ }
+
+ // openDoc opens the file in the workspace with the given path (paths
+ // are the path elements of a file).
+ public async openDoc(...paths: string[]) {
+ const uri = vscode.Uri.file(path.resolve(this.workspaceDir, ...paths));
+ const doc = await vscode.workspace.openTextDocument(uri);
+ return { uri, doc };
+ }
+}
+
+async function sleep(ms: number) {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+}
+
+suite('Go Extension Tests With Gopls', function() {
+ this.timeout(1000000);
+ const projectDir = path.join(__dirname, '..', '..', '..');
+ const env = new Env(projectDir);
+
+ suiteSetup(async () => { await env.setup(); });
+ suiteTeardown(async () => { await env.reset(); });
+
+ test('HoverProvider', async () => {
+ await env.reset('gogetdocTestData');
+ const { uri, doc } = await env.openDoc('test.go');
+
+ // TODO(hyangah): find a way to wait for the language server to complete processing.
+
+ const testCases: [string, vscode.Position, string | null, string | null][] = [
+ // [new vscode.Position(3,3), '/usr/local/go/src/fmt'],
+ ['keyword', new vscode.Position(0, 3), null, null], // keyword
+ ['inside a string', new vscode.Position(23, 14), null, null], // inside a string
+ ['just a }', new vscode.Position(20, 0), null, null], // just a }
+ ['inside a number', new vscode.Position(28, 16), null, null], // inside a number
+ ['func main()', new vscode.Position(22, 5), 'func main()', null],
+ ['import "math"', new vscode.Position(40, 23), 'package math', '`math` on'],
+ ['func Println()', new vscode.Position(19, 6), 'func fmt.Println(a ...interface{}) (n int, err error)', 'Println formats '],
+ ['func print()', new vscode.Position(23, 4), 'func print(txt string)', 'This is an unexported function ']
+ ];
+
+ const promises = testCases.map(async ([name, position, expectedSignature, expectedDoc]) => {
+ const hovers = await vscode.commands.executeCommand(
+ 'vscode.executeHoverProvider', uri, position) as vscode.Hover[];
+
+ if (expectedSignature === null && expectedDoc === null) {
+ assert.equal(hovers.length, 0, `check hovers over ${name} failed: unexpected non-empty hover message.`);
+ return;
+ }
+
+ const hover = hovers[0];
+ assert.equal(hover.contents.length, 1, `check hovers over ${name} failed: unexpected number of hover messages.`);
+ const gotMessage = (<vscode.MarkdownString>hover.contents[0]).value;
+ assert.ok(
+ gotMessage.includes('```go\n' + expectedSignature + '\n```')
+ && (!expectedDoc || gotMessage.includes(expectedDoc)),
+ `check hovers over ${name} failed: got ${gotMessage}`);
+ });
+ return Promise.all(promises);
+ });
+});
diff --git a/test/gopls/index.ts b/test/gopls/index.ts
new file mode 100644
index 0000000..1aa3b7f
--- /dev/null
+++ b/test/gopls/index.ts
@@ -0,0 +1,40 @@
+/*---------------------------------------------------------
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------*/
+import * as glob from 'glob';
+import * as Mocha from 'mocha';
+import * as path from 'path';
+export function run(): Promise<void> {
+ // Create the mocha test
+ const mocha = new Mocha({
+ ui: 'tdd'
+ });
+ mocha.useColors(true);
+
+ const testsRoot = path.resolve(__dirname, '..');
+
+ return new Promise((c, e) => {
+ glob('gopls/**.test.js', { cwd: testsRoot }, (err, files) => {
+ if (err) {
+ return e(err);
+ }
+
+ // Add files to the test suite
+ files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f)));
+
+ try {
+ // Run the mocha test
+ mocha.run((failures) => {
+ if (failures > 0) {
+ e(new Error(`${failures} tests failed.`));
+ } else {
+ c();
+ }
+ });
+ } catch (err) {
+ e(err);
+ }
+ });
+ });
+}
diff --git a/test/gopls/testfixtures/src/workspace/.gitignore b/test/gopls/testfixtures/src/workspace/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/test/gopls/testfixtures/src/workspace/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/test/runTest.ts b/test/runTest.ts
index 82f76e3..ee29d48 100644
--- a/test/runTest.ts
+++ b/test/runTest.ts
@@ -1,13 +1,14 @@
+import * as fs from 'fs-extra';
import * as path from 'path';
-
import { runTests } from 'vscode-test';
+import { extensionId } from '../src/telemetry';
async function main() {
- try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
- const extensionDevelopmentPath = path.resolve(__dirname, '../../');
+ const extensionDevelopmentPath = path.resolve(__dirname, '../../');
+ try {
// The path to the extension test script
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, './integration/index');
@@ -15,9 +16,31 @@
// Download VS Code, unzip it and run the integration test
await runTests({ extensionDevelopmentPath, extensionTestsPath });
} catch (err) {
- console.error('Failed to run tests');
+ console.error('Failed to run integration tests' + err);
process.exit(1);
}
+
+ // Integration tests using gopls.
+ try {
+ // Currently gopls requires a workspace. Code in test environment does not support
+ // dynamically adding folders.
+ // tslint:disable-next-line:max-line-length
+ // https://github.com/microsoft/vscode/blob/890f62dfd9f3e70198931f788c5c332b3e8b7ad7/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts#L281
+ // So, we start the test extension host with a dummy workspace (test/gopls/testfixtures/src/workspace)
+ // and copy necessary files to the workspace.
+ const ws = path.resolve(extensionDevelopmentPath, 'test/gopls/testfixtures/src/workspace');
+
+ await runTests({
+ extensionDevelopmentPath,
+ extensionTestsPath: path.resolve(__dirname, './gopls/index'),
+ launchArgs: [
+ '--disable-extensions', // disable all other extensions
+ ws // dummy workspace to start with
+ ],
+ });
+ } catch (err) {
+ console.error('Failed to run gopls tests' + err);
+ }
}
main();