diff --git a/package-lock.json b/package-lock.json index aa0e75433..d1df7157c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,18 +21,18 @@ "devDependencies": { "@types/marked": "^0.6.5", "@types/mocha": "^9.1.0", - "@types/node": "^10.12.21", + "@types/node": "^18.15.0", "@types/prismjs": "^1.16.8", - "@types/vscode": "^1.68.0", + "@types/vscode": "^1.80.0", "@types/ws": "^8.2.2", + "@vscode/vsce": "^2.21.0", "esbuild": "^0.15.2", "ts-node": "^10.9.1", "tslint": "^5.20.1", - "typescript": "^3.5.1", - "vsce": "^2.10.0" + "typescript": "^5.2.2" }, "engines": { - "vscode": "^1.68.0" + "vscode": "^1.80.0" } }, "node_modules/@babel/code-frame": { @@ -151,9 +151,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "version": "18.18.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.3.tgz", + "integrity": "sha512-0OVfGupTl3NBFr8+iXpfZ8NR7jfFO+P1Q+IO/q0wbo02wYkP5gy36phojeYWpLQ6WAMjl+VfmqUk2YbUfp0irA==", "dev": true }, "node_modules/@types/prismjs": { @@ -163,9 +163,9 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.68.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.68.0.tgz", - "integrity": "sha512-duBwEK5ta/eBBMJMQ7ECMEsMvlE3XJdRGh3xoS1uOO4jl2Z4LPBl5vx8WvBP10ERAgDRmIt/FaSD4RHyBGbChw==", + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.82.0.tgz", + "integrity": "sha512-VSHV+VnpF8DEm8LNrn8OJ8VuUNcBzN3tMvKrNpbhhfuVjFm82+6v44AbDhLvVFgCzn6vs94EJNTp7w8S6+Q1Rw==", "dev": true }, "node_modules/@types/ws": { @@ -177,6 +177,80 @@ "@types/node": "*" } }, + "node_modules/@vscode/vsce": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.21.1.tgz", + "integrity": "sha512-f45/aT+HTubfCU2oC7IaWnH9NjOWp668ML002QiFObFRVUCoLtcwepp9mmql/ArFUy+HCHp54Xrq4koTcOD6TA==", + "dev": true, + "dependencies": { + "azure-devops-node-api": "^11.0.1", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "commander": "^6.2.1", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^12.3.2", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^7.5.2", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 14" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "node_modules/@vscode/vsce/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@vscode/vsce/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@vscode/vsce/node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", @@ -203,6 +277,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, + "optional": true, "engines": { "node": ">=0.10.0" } @@ -223,13 +298,15 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true + "dev": true, + "optional": true }, "node_modules/are-we-there-yet": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "dev": true, + "optional": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -288,13 +365,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "optional": true }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, + "optional": true, "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -306,6 +385,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, + "optional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -349,6 +429,7 @@ "url": "https://feross.org/support" } ], + "optional": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -446,13 +527,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true + "dev": true, + "optional": true }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, + "optional": true, "engines": { "node": ">=0.10.0" } @@ -487,13 +570,15 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "dev": true, + "optional": true }, "node_modules/create-require": { "version": "1.1.1", @@ -534,6 +619,7 @@ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", "dev": true, + "optional": true, "dependencies": { "mimic-response": "^2.0.0" }, @@ -546,6 +632,7 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, + "optional": true, "engines": { "node": ">=4.0.0" } @@ -554,13 +641,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true + "dev": true, + "optional": true }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, + "optional": true, "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -647,6 +736,7 @@ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, + "optional": true, "dependencies": { "once": "^1.4.0" } @@ -1057,6 +1147,7 @@ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "dev": true, + "optional": true, "engines": { "node": ">=6" } @@ -1079,7 +1170,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "dev": true, + "optional": true }, "node_modules/fs.realpath": { "version": "1.0.0", @@ -1098,6 +1190,7 @@ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, + "optional": true, "dependencies": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", @@ -1127,7 +1220,8 @@ "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true + "dev": true, + "optional": true }, "node_modules/glob": { "version": "7.1.6", @@ -1195,7 +1289,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true + "dev": true, + "optional": true }, "node_modules/hosted-git-info": { "version": "4.1.0", @@ -1246,7 +1341,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "optional": true }, "node_modules/inflight": { "version": "1.0.6", @@ -1268,13 +1364,15 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "optional": true }, "node_modules/is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, + "optional": true, "dependencies": { "number-is-nan": "^1.0.0" }, @@ -1286,7 +1384,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "dev": true, + "optional": true }, "node_modules/js-tokens": { "version": "4.0.0", @@ -1307,12 +1406,19 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/keytar": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.7.0.tgz", "integrity": "sha512-YEY9HWqThQc5q5xbXbRwsZTh2PJ36OSYRjSv3NN2xf5s5dpLTjEZnC2YikR29OaVybf9nQ0dJ/80i40RS97t/A==", "dev": true, "hasInstallScript": true, + "optional": true, "dependencies": { "node-addon-api": "^3.0.0", "prebuild-install": "^6.0.0" @@ -1423,6 +1529,7 @@ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", "dev": true, + "optional": true, "engines": { "node": ">=8" }, @@ -1439,9 +1546,9 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1469,7 +1576,8 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true + "dev": true, + "optional": true }, "node_modules/mute-stream": { "version": "0.0.8", @@ -1481,7 +1589,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true + "dev": true, + "optional": true }, "node_modules/net": { "version": "1.0.2", @@ -1493,6 +1602,7 @@ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", "dev": true, + "optional": true, "dependencies": { "semver": "^5.4.1" } @@ -1501,13 +1611,15 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true + "dev": true, + "optional": true }, "node_modules/npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, + "optional": true, "dependencies": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -1532,6 +1644,7 @@ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, + "optional": true, "engines": { "node": ">=0.10.0" } @@ -1541,6 +1654,7 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, + "optional": true, "engines": { "node": ">=0.10.0" } @@ -1621,6 +1735,7 @@ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", "dev": true, + "optional": true, "dependencies": { "detect-libc": "^1.0.3", "expand-template": "^2.0.3", @@ -1655,7 +1770,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "dev": true, + "optional": true }, "node_modules/ps-tree": { "version": "1.2.0", @@ -1676,6 +1792,7 @@ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, + "optional": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -1701,6 +1818,7 @@ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, + "optional": true, "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -1728,6 +1846,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, + "optional": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -1769,7 +1888,8 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "optional": true }, "node_modules/sax": { "version": "1.2.4", @@ -1778,9 +1898,9 @@ "dev": true }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -1790,7 +1910,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "dev": true, + "optional": true }, "node_modules/side-channel": { "version": "1.0.4", @@ -1810,7 +1931,8 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true + "dev": true, + "optional": true }, "node_modules/simple-concat": { "version": "1.0.1", @@ -1830,13 +1952,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "optional": true }, "node_modules/simple-get": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", "dev": true, + "optional": true, "dependencies": { "decompress-response": "^4.2.0", "once": "^1.3.1", @@ -1873,6 +1997,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "optional": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -1882,6 +2007,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, + "optional": true, "dependencies": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -1896,6 +2022,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "dependencies": { "ansi-regex": "^2.0.0" }, @@ -1908,6 +2035,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, + "optional": true, "engines": { "node": ">=0.10.0" } @@ -1929,6 +2057,7 @@ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dev": true, + "optional": true, "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -1941,6 +2070,7 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, + "optional": true, "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -1957,6 +2087,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, + "optional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -2099,6 +2230,7 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, + "optional": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -2118,16 +2250,16 @@ } }, "node_modules/typescript": { - "version": "3.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz", - "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uc.micro": { @@ -2152,7 +2284,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "dev": true, + "optional": true }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", @@ -2160,49 +2293,6 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, - "node_modules/vsce": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-2.10.0.tgz", - "integrity": "sha512-b+wB3XMapEi368g64klSM6uylllZdNutseqbNY+tUoHYSy6g2NwnlWuAGKDQTYc0IqfDUjUFRQBpPgA89Q+Fyw==", - "dev": true, - "dependencies": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "glob": "^7.0.6", - "hosted-git-info": "^4.0.2", - "keytar": "^7.7.0", - "leven": "^3.1.0", - "markdown-it": "^12.3.2", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^4.0.1", - "xml2js": "^0.4.23", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "vsce" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/vsce/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/vscode-debugadapter": { "version": "1.41.0", "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.41.0.tgz", @@ -2241,9 +2331,9 @@ } }, "node_modules/vscode-languageclient/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2273,6 +2363,7 @@ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dev": true, + "optional": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -2303,19 +2394,6 @@ } } }, - "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/xmlbuilder": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", @@ -2461,9 +2539,9 @@ "dev": true }, "@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "version": "18.18.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.3.tgz", + "integrity": "sha512-0OVfGupTl3NBFr8+iXpfZ8NR7jfFO+P1Q+IO/q0wbo02wYkP5gy36phojeYWpLQ6WAMjl+VfmqUk2YbUfp0irA==", "dev": true }, "@types/prismjs": { @@ -2473,9 +2551,9 @@ "dev": true }, "@types/vscode": { - "version": "1.68.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.68.0.tgz", - "integrity": "sha512-duBwEK5ta/eBBMJMQ7ECMEsMvlE3XJdRGh3xoS1uOO4jl2Z4LPBl5vx8WvBP10ERAgDRmIt/FaSD4RHyBGbChw==", + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.82.0.tgz", + "integrity": "sha512-VSHV+VnpF8DEm8LNrn8OJ8VuUNcBzN3tMvKrNpbhhfuVjFm82+6v44AbDhLvVFgCzn6vs94EJNTp7w8S6+Q1Rw==", "dev": true }, "@types/ws": { @@ -2487,6 +2565,62 @@ "@types/node": "*" } }, + "@vscode/vsce": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.21.1.tgz", + "integrity": "sha512-f45/aT+HTubfCU2oC7IaWnH9NjOWp668ML002QiFObFRVUCoLtcwepp9mmql/ArFUy+HCHp54Xrq4koTcOD6TA==", + "dev": true, + "requires": { + "azure-devops-node-api": "^11.0.1", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "commander": "^6.2.1", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "keytar": "^7.7.0", + "leven": "^3.1.0", + "markdown-it": "^12.3.2", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^7.5.2", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "dependencies": { + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + } + } + }, "acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", @@ -2503,7 +2637,8 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "dev": true, + "optional": true }, "ansi-styles": { "version": "3.2.1", @@ -2518,13 +2653,15 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true + "dev": true, + "optional": true }, "are-we-there-yet": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "dev": true, + "optional": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -2569,13 +2706,15 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "dev": true, + "optional": true }, "bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, + "optional": true, "requires": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -2587,6 +2726,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, + "optional": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -2615,6 +2755,7 @@ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, + "optional": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -2693,13 +2834,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true + "dev": true, + "optional": true }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "dev": true, + "optional": true }, "color-convert": { "version": "1.9.3", @@ -2731,13 +2874,15 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "dev": true, + "optional": true }, "create-require": { "version": "1.1.1", @@ -2769,6 +2914,7 @@ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", "dev": true, + "optional": true, "requires": { "mimic-response": "^2.0.0" } @@ -2777,19 +2923,22 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true + "dev": true, + "optional": true }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true + "dev": true, + "optional": true }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true + "dev": true, + "optional": true }, "diff": { "version": "4.0.2", @@ -2849,6 +2998,7 @@ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, + "optional": true, "requires": { "once": "^1.4.0" } @@ -3058,7 +3208,8 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true + "dev": true, + "optional": true }, "fd-slicer": { "version": "1.1.0", @@ -3078,7 +3229,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "dev": true, + "optional": true }, "fs.realpath": { "version": "1.0.0", @@ -3097,6 +3249,7 @@ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, + "optional": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", @@ -3123,7 +3276,8 @@ "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true + "dev": true, + "optional": true }, "glob": { "version": "7.1.6", @@ -3173,7 +3327,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true + "dev": true, + "optional": true }, "hosted-git-info": { "version": "4.1.0", @@ -3200,7 +3355,8 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "dev": true, + "optional": true }, "inflight": { "version": "1.0.6", @@ -3222,13 +3378,15 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3237,7 +3395,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "dev": true, + "optional": true }, "js-tokens": { "version": "4.0.0", @@ -3255,11 +3414,18 @@ "esprima": "^4.0.0" } }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "keytar": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.7.0.tgz", "integrity": "sha512-YEY9HWqThQc5q5xbXbRwsZTh2PJ36OSYRjSv3NN2xf5s5dpLTjEZnC2YikR29OaVybf9nQ0dJ/80i40RS97t/A==", "dev": true, + "optional": true, "requires": { "node-addon-api": "^3.0.0", "prebuild-install": "^6.0.0" @@ -3347,7 +3513,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true + "dev": true, + "optional": true }, "min-document": { "version": "2.19.0", @@ -3358,9 +3525,9 @@ } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } @@ -3382,7 +3549,8 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true + "dev": true, + "optional": true }, "mute-stream": { "version": "0.0.8", @@ -3394,7 +3562,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true + "dev": true, + "optional": true }, "net": { "version": "1.0.2", @@ -3406,6 +3575,7 @@ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", "dev": true, + "optional": true, "requires": { "semver": "^5.4.1" } @@ -3414,13 +3584,15 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true + "dev": true, + "optional": true }, "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, + "optional": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -3441,13 +3613,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "dev": true, + "optional": true }, "object-inspect": { "version": "1.12.0", @@ -3519,6 +3693,7 @@ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", "dev": true, + "optional": true, "requires": { "detect-libc": "^1.0.3", "expand-template": "^2.0.3", @@ -3544,7 +3719,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "dev": true, + "optional": true }, "ps-tree": { "version": "1.2.0", @@ -3559,6 +3735,7 @@ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, + "optional": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -3578,6 +3755,7 @@ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, + "optional": true, "requires": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -3599,6 +3777,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, + "optional": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3631,7 +3810,8 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "optional": true }, "sax": { "version": "1.2.4", @@ -3640,16 +3820,17 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "dev": true, + "optional": true }, "side-channel": { "version": "1.0.4", @@ -3666,19 +3847,22 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true + "dev": true, + "optional": true }, "simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true + "dev": true, + "optional": true }, "simple-get": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", "dev": true, + "optional": true, "requires": { "decompress-response": "^4.2.0", "once": "^1.3.1", @@ -3712,6 +3896,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "optional": true, "requires": { "safe-buffer": "~5.1.0" } @@ -3721,6 +3906,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3732,6 +3918,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3740,7 +3927,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "dev": true, + "optional": true }, "supports-color": { "version": "5.5.0", @@ -3756,6 +3944,7 @@ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dev": true, + "optional": true, "requires": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -3768,6 +3957,7 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, + "optional": true, "requires": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -3781,6 +3971,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, + "optional": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -3879,6 +4070,7 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -3895,9 +4087,9 @@ } }, "typescript": { - "version": "3.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz", - "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true }, "uc.micro": { @@ -3922,7 +4114,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "dev": true, + "optional": true }, "v8-compile-cache-lib": { "version": "3.0.1", @@ -3930,42 +4123,6 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, - "vsce": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-2.10.0.tgz", - "integrity": "sha512-b+wB3XMapEi368g64klSM6uylllZdNutseqbNY+tUoHYSy6g2NwnlWuAGKDQTYc0IqfDUjUFRQBpPgA89Q+Fyw==", - "dev": true, - "requires": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "glob": "^7.0.6", - "hosted-git-info": "^4.0.2", - "keytar": "^7.7.0", - "leven": "^3.1.0", - "markdown-it": "^12.3.2", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^4.0.1", - "xml2js": "^0.4.23", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - } - } - }, "vscode-debugadapter": { "version": "1.41.0", "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.41.0.tgz", @@ -3996,9 +4153,9 @@ }, "dependencies": { "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -4024,6 +4181,7 @@ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dev": true, + "optional": true, "requires": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -4040,16 +4198,6 @@ "integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==", "requires": {} }, - "xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, "xmlbuilder": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", diff --git a/package.json b/package.json index cbfb4d190..62784de2c 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "author": "The Godot Engine community", "publisher": "geequlim", "engines": { - "vscode": "^1.68.0" + "vscode": "^1.80.0" }, "categories": [ "Programming Languages", @@ -26,9 +26,6 @@ ], "activationEvents": [ "workspaceContains:project.godot", - "onLanguage:gdscript", - "onLanguage:gdshader", - "onLanguage:gdresource", "onDebugResolve:godot" ], "main": "./out/extension.js", @@ -49,6 +46,14 @@ "command": "godotTools.openEditor", "title": "Godot Tools: Open workspace with Godot editor" }, + { + "command": "godotTools.startLanguageServer", + "title": "Godot Tools: Start the GDScript Language Server for this workspace" + }, + { + "command": "godotTools.stopLanguageServer", + "title": "Godot Tools: Stop the GDScript Language Server for this workspace" + }, { "command": "godotTools.runProject", "title": "Godot Tools: Run workspace as Godot project" @@ -184,10 +189,20 @@ "default": 6008, "description": "The server port of the GDScript language server" }, - "godotTools.editorPath": { + "godotTools.lsp.headless": { + "type": "boolean", + "default": false, + "description": "Whether to launch the LSP as a headless child process" + }, + "godotTools.editorPath.godot3": { "type": "string", - "default": "", - "description": "The absolute path to the Godot editor executable" + "default": "godot3", + "description": "The absolute path to the Godot 3 editor executable" + }, + "godotTools.editorPath.godot4": { + "type": "string", + "default": "godot4", + "description": "The absolute path to the Godot 4 editor executable" }, "godotTools.sceneFileConfig": { "type": "string", @@ -546,7 +561,7 @@ "editor/context": [ { "command": "godotTools.openTypeDocumentation", - "when": "godotTools.context.connectedToEditor", + "when": "godotTools.context.connectedToLSP && godotTools.context.typeFound", "group": "navigation@9" }, { @@ -560,15 +575,15 @@ "devDependencies": { "@types/marked": "^0.6.5", "@types/mocha": "^9.1.0", - "@types/node": "^10.12.21", + "@types/node": "^18.15.0", "@types/prismjs": "^1.16.8", - "@types/vscode": "^1.68.0", + "@types/vscode": "^1.80.0", "@types/ws": "^8.2.2", + "@vscode/vsce": "^2.21.0", "esbuild": "^0.15.2", "ts-node": "^10.9.1", "tslint": "^5.20.1", - "typescript": "^3.5.1", - "vsce": "^2.10.0" + "typescript": "^5.2.2" }, "dependencies": { "await-notify": "^1.0.1", diff --git a/src/document_link_provider.ts b/src/document_link_provider.ts index c2f5d4015..39cfa79c2 100644 --- a/src/document_link_provider.ts +++ b/src/document_link_provider.ts @@ -1,5 +1,5 @@ import * as vscode from "vscode"; -import { Uri, Position, Range, TextDocument } from "vscode"; +import { Uri, Position, Range } from "vscode"; import { convert_resource_path_to_uri } from "./utils"; export class GDDocumentLinkProvider implements vscode.DocumentLinkProvider { diff --git a/src/godot-tools.ts b/src/godot-tools.ts index 129e1d84d..8327c6b6d 100644 --- a/src/godot-tools.ts +++ b/src/godot-tools.ts @@ -2,82 +2,70 @@ import * as fs from "fs"; import * as path from "path"; import * as vscode from "vscode"; import { GDDocumentLinkProvider } from "./document_link_provider"; -import GDScriptLanguageClient, { ClientStatus } from "./lsp/GDScriptLanguageClient"; +import { ClientConnectionManager } from "./lsp/ClientConnectionManager"; import { ScenePreviewProvider } from "./scene_preview_provider"; -import { get_configuration, set_configuration, find_file, set_context, find_project_file } from "./utils"; +import { + get_configuration, + set_configuration, + find_file, + find_project_file, + register_command +} from "./utils"; const TOOL_NAME = "GodotTools"; export class GodotTools { - private reconnection_attempts = 0; private context: vscode.ExtensionContext; - private client: GDScriptLanguageClient = null; + + private lspClientManager: ClientConnectionManager = null; private linkProvider: GDDocumentLinkProvider = null; private scenePreviewManager: ScenePreviewProvider = null; - private connection_status: vscode.StatusBarItem = null; - constructor(p_context: vscode.ExtensionContext) { this.context = p_context; - this.client = new GDScriptLanguageClient(p_context); - this.client.watch_status(this.on_client_status_changed.bind(this)); - this.connection_status = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); + this.lspClientManager = new ClientConnectionManager(p_context); this.linkProvider = new GDDocumentLinkProvider(p_context); - - setInterval(() => { - this.retry_callback(); - }, get_configuration("lsp.autoReconnect.cooldown", 3000)); } public activate() { - vscode.commands.registerCommand("godotTools.openEditor", () => { + register_command("openEditor", () => { this.open_workspace_with_editor("-e").catch(err => vscode.window.showErrorMessage(err)); }); - vscode.commands.registerCommand("godotTools.runProject", () => { + register_command("runProject", () => { this.open_workspace_with_editor().catch(err => vscode.window.showErrorMessage(err)); }); - vscode.commands.registerCommand("godotTools.runProjectDebug", () => { + register_command("runProjectDebug", () => { this.open_workspace_with_editor("--debug-collisions --debug-navigation").catch(err => vscode.window.showErrorMessage(err)); }); - vscode.commands.registerCommand("godotTools.checkStatus", this.check_client_status.bind(this)); - vscode.commands.registerCommand("godotTools.setSceneFile", this.set_scene_file.bind(this)); - vscode.commands.registerCommand("godotTools.copyResourcePathContext", this.copy_resource_path.bind(this)); - vscode.commands.registerCommand("godotTools.copyResourcePath", this.copy_resource_path.bind(this)); - vscode.commands.registerCommand("godotTools.openTypeDocumentation", this.open_type_documentation.bind(this)); - vscode.commands.registerCommand("godotTools.switchSceneScript", this.switch_scene_script.bind(this)); - - set_context("godotTools.context.connectedToEditor", false); + register_command("setSceneFile", this.set_scene_file.bind(this)); + register_command("copyResourcePathContext", this.copy_resource_path.bind(this)); + register_command("copyResourcePath", this.copy_resource_path.bind(this)); + register_command("openTypeDocumentation", this.open_type_documentation.bind(this)); + register_command("switchSceneScript", this.switch_scene_script.bind(this)); this.scenePreviewManager = new ScenePreviewProvider(); - - this.connection_status.text = "$(sync) Initializing"; - this.connection_status.command = "godotTools.checkStatus"; - this.connection_status.show(); - - this.reconnection_attempts = 0; - this.client.connect_to_server(); } public deactivate() { - this.client.stop(); + this.lspClientManager.client.stop(); } private open_workspace_with_editor(params = "") { return new Promise(async (resolve, reject) => { let valid = false; - let project_dir = ''; - let project_file = ''; - - if (vscode.workspace.workspaceFolders != undefined) { - const files = await vscode.workspace.findFiles("**/project.godot"); - if (files) { - project_file = files[0].fsPath; - project_dir = path.dirname(project_file); - let cfg = project_file; - valid = (fs.existsSync(cfg) && fs.statSync(cfg).isFile()); - } - } + let project_dir = ''; + let project_file = ''; + + if (vscode.workspace.workspaceFolders != undefined) { + const files = await vscode.workspace.findFiles("**/project.godot"); + if (files) { + project_file = files[0].fsPath; + project_dir = path.dirname(project_file); + let cfg = project_file; + valid = (fs.existsSync(cfg) && fs.statSync(cfg).isFile()); + } + } if (valid) { this.run_editor(`--path "${project_dir}" ${params}`).then(() => resolve()).catch(err => { reject(err); @@ -93,11 +81,11 @@ export class GodotTools { uri = vscode.window.activeTextEditor.document.uri; } - const project_dir = path.dirname(find_project_file(uri.fsPath)); - if (project_dir === null) { - return - } - + const project_dir = path.dirname(find_project_file(uri.fsPath)); + if (project_dir === null) { + return; + } + let relative_path = path.normalize(path.relative(project_dir, uri.fsPath)); relative_path = relative_path.split(path.sep).join(path.posix.sep); relative_path = "res://" + relative_path; @@ -105,15 +93,8 @@ export class GodotTools { vscode.env.clipboard.writeText(relative_path); } - private open_type_documentation(uri: vscode.Uri) { - // get word under cursor - const activeEditor = vscode.window.activeTextEditor; - const document = activeEditor.document; - const curPos = activeEditor.selection.active; - const wordRange = document.getWordRangeAtPosition(curPos); - const symbolName = document.getText(wordRange); - - this.client.open_documentation(symbolName); + private open_type_documentation() { + this.lspClientManager.client.open_documentation(); } private async switch_scene_script() { @@ -145,7 +126,7 @@ export class GodotTools { } private run_editor(params = "") { - + // TODO: rewrite this entire function return new Promise((resolve, reject) => { const run_godot = (path: string, params: string) => { const is_powershell_path = (path?: string) => { @@ -206,7 +187,8 @@ export class GodotTools { resolve(); }; - let editorPath = get_configuration("editorPath", ""); + // TODO: This config doesn't exist anymore + let editorPath = get_configuration("editorPath"); if (!fs.existsSync(editorPath) || !fs.statSync(editorPath).isFile()) { vscode.window.showOpenDialog({ openLabel: "Run", @@ -228,95 +210,4 @@ export class GodotTools { } }); } - - private check_client_status() { - let host = get_configuration("lsp.serverPort", "localhost"); - let port = get_configuration("lsp.serverHost", 6008); - switch (this.client.status) { - case ClientStatus.PENDING: - vscode.window.showInformationMessage(`Connecting to the GDScript language server at ${host}:${port}`); - break; - case ClientStatus.CONNECTED: - vscode.window.showInformationMessage("Connected to the GDScript language server."); - break; - case ClientStatus.DISCONNECTED: - this.retry_connect_client(); - break; - } - } - - private on_client_status_changed(status: ClientStatus) { - let host = get_configuration("lsp.serverHost", "localhost"); - let port = get_configuration("lsp.serverPort", 6008); - switch (status) { - case ClientStatus.PENDING: - this.connection_status.text = `$(sync) Connecting`; - this.connection_status.tooltip = `Connecting to the GDScript language server at ${host}:${port}`; - break; - case ClientStatus.CONNECTED: - this.retry = false; - set_context("godotTools.context.connectedToEditor", true); - this.connection_status.text = `$(check) Connected`; - this.connection_status.tooltip = `Connected to the GDScript language server.`; - if (!this.client.started) { - this.context.subscriptions.push(this.client.start()); - } - break; - case ClientStatus.DISCONNECTED: - if (this.retry) { - this.connection_status.text = `$(sync) Connecting ` + this.reconnection_attempts; - this.connection_status.tooltip = `Connecting to the GDScript language server...`; - } else { - set_context("godotTools.context.connectedToEditor", false); - this.connection_status.text = `$(x) Disconnected`; - this.connection_status.tooltip = `Disconnected from the GDScript language server.`; - } - this.retry = true; - break; - default: - break; - } - } - - private retry = false; - - private retry_callback() { - if (this.retry) { - this.retry_connect_client(); - } - } - - private retry_connect_client() { - const auto_retry = get_configuration("lsp.autoReconnect.enabled", true); - const max_attempts = get_configuration("lsp.autoReconnect.attempts", 10); - if (auto_retry && this.reconnection_attempts <= max_attempts) { - this.reconnection_attempts++; - this.client.connect_to_server(); - this.connection_status.text = `Connecting ` + this.reconnection_attempts; - this.retry = true; - return; - } - - this.retry = false; - this.connection_status.text = `$(x) Disconnected`; - this.connection_status.tooltip = `Disconnected from the GDScript language server.`; - - let host = get_configuration("lsp.serverHost", "localhost"); - let port = get_configuration("lsp.serverPort", 6008); - let message = `Couldn't connect to the GDScript language server at ${host}:${port}. Is the Godot editor running?`; - vscode.window.showErrorMessage(message, "Open Godot Editor", "Retry", "Ignore").then(item => { - if (item == "Retry") { - this.reconnection_attempts = 0; - this.client.connect_to_server(); - } else if (item == "Open Godot Editor") { - this.client.status = ClientStatus.PENDING; - this.open_workspace_with_editor("-e").then(() => { - setTimeout(() => { - this.reconnection_attempts = 0; - this.client.connect_to_server(); - }, 10 * 1000); - }); - } - }); - } } diff --git a/src/logger.ts b/src/logger.ts index 76d645230..25bfe6dd4 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,20 +1,21 @@ + export class Logger { protected buffer: string = ""; - protected tag: string = ''; + protected tag: string = ""; protected time: boolean = false; - + constructor(tag: string, time: boolean) { this.tag = tag; this.time = time; } - + clear() { this.buffer = ""; } - + log(...messages) { - - let line = ''; + + let line = ""; if (this.tag) { line += `[${this.tag}]`; } @@ -22,9 +23,9 @@ export class Logger { line += `[${new Date().toISOString()}]`; } if (line) { - line += ' '; + line += " "; } - + for (let index = 0; index < messages.length; index++) { line += messages[index]; if (index < messages.length) { @@ -33,15 +34,75 @@ export class Logger { line += "\n"; } } - + this.buffer += line; console.log(line); } - + get_buffer(): string { return this.buffer; } } -const logger = new Logger('godot-tools', true); +export class Logger2 { + protected tag: string = ""; + protected level: string = ""; + protected time: boolean = false; + + constructor(tag: string) { + this.tag = tag; + } + + log(...messages) { + let line = "[godotTools]"; + if (this.time) { + line += `[${new Date().toISOString()}]`; + } + if (this.level) { + line += `[${this.level}]`; + this.level = ""; + } + if (this.tag) { + line += `[${this.tag}]`; + } + if (line) { + line += " "; + } + + for (let index = 0; index < messages.length; index++) { + line += messages[index]; + if (index < messages.length) { + line += " "; + } else { + line += "\n"; + } + } + + console.log(line); + } + + info(...messages) { + this.level = "INFO"; + this.log(messages); + } + debug(...messages) { + this.level = "DEBUG"; + this.log(messages); + } + warn(...messages) { + this.level = "WARNING"; + this.log(messages); + } + error(...messages) { + this.level = "ERROR"; + this.log(messages); + } +} + + +export function createLogger(tag) { + return new Logger2(tag); +} + +const logger = new Logger("godot-tools", true); export default logger; diff --git a/src/lsp/ClientConnectionManager.ts b/src/lsp/ClientConnectionManager.ts new file mode 100644 index 000000000..06e4f5a5a --- /dev/null +++ b/src/lsp/ClientConnectionManager.ts @@ -0,0 +1,331 @@ +import * as vscode from "vscode"; +import * as fs from "fs"; +import GDScriptLanguageClient, { ClientStatus } from "./GDScriptLanguageClient"; +import { + get_configuration, + get_free_port, + get_project_version, + get_project_dir, + set_context, + register_command, + set_configuration, +} from "../utils"; +import { createLogger } from "../logger"; +import { execSync } from "child_process"; +import { subProcess, killSubProcesses } from '../utils/subspawn'; + +const log = createLogger("lsp.manager"); + +enum ManagerStatus { + INITIALIZING, + INITIALIZING_LSP, + PENDING, + PENDING_LSP, + DISCONNECTED, + CONNECTED, + RETRYING, +} + +export class ClientConnectionManager { + private context: vscode.ExtensionContext; + public client: GDScriptLanguageClient = null; + + private reconnection_attempts = 0; + + private status: ManagerStatus = ManagerStatus.INITIALIZING; + private statusWidget: vscode.StatusBarItem = null; + + constructor(p_context: vscode.ExtensionContext) { + this.context = p_context; + + this.client = new GDScriptLanguageClient(p_context); + this.client.watch_status(this.on_client_status_changed.bind(this)); + + setInterval(() => { + this.retry_callback(); + }, get_configuration("lsp.autoReconnect.cooldown")); + + register_command("startLanguageServer", () => { + this.start_language_server(); + this.reconnection_attempts = 0; + this.client.connect_to_server(); + }); + register_command("stopLanguageServer", this.stop_language_server.bind(this)); + register_command("checkStatus", this.on_status_item_click.bind(this)); + + set_context("connectedToLSP", false); + + this.statusWidget = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); + this.statusWidget.command = "godotTools.checkStatus"; + this.statusWidget.show(); + this.update_status_widget(); + + this.connect_to_language_server(); + } + + private async connect_to_language_server() { + this.client.port = -1; + + if (get_configuration("lsp.headless")) { + await this.start_language_server(); + } + + this.reconnection_attempts = 0; + this.client.connect_to_server(); + } + + private stop_language_server() { + killSubProcesses('LSP'); + } + + private async start_language_server() { + this.stop_language_server(); + + const projectDir = await get_project_dir(); + + if (!projectDir) { + vscode.window.showErrorMessage("Current workspace is not a Godot project"); + return; + } + + const projectVersion = await get_project_version(); + + let minimumVersion = '6'; + let targetVersion = '3.6'; + if (projectVersion.startsWith('4')) { + minimumVersion = '2'; + targetVersion = '4.2'; + } + const settingName = `editorPath.godot${projectVersion[0]}`; + const godotPath = get_configuration(settingName); + + try { + const output = execSync(`${godotPath} --version`).toString().trim(); + const pattern = /([34])\.([0-9]+)\.(?:[0-9]+\.)?\w+.\w+.[0-9a-f]{9}/; + const match = output.match(pattern); + if (!match) { + const message = `Cannot launch headless LSP: '${settingName}' of '${godotPath}' is not a valid Godot executable`; + vscode.window.showErrorMessage(message, "Select Godot executable", "Ignore").then(item => { + if (item == "Select Godot executable") { + this.select_godot_executable(settingName); + } + }); + return; + } + + if (match[1] !== projectVersion[0]) { + const message = `Cannot launch headless LSP: The current project uses Godot v${projectVersion}, but the specified Godot executable is version ${match[0]}`; + vscode.window.showErrorMessage(message, "Select Godot executable", "Ignore").then(item => { + if (item == "Select Godot executable") { + this.select_godot_executable(settingName); + } + }); + return; + } + + if (match[2] < minimumVersion) { + const message = `Cannot launch headless LSP: Headless LSP mode is only available on version ${targetVersion} or newer, but the specified Godot executable is version ${match[0]}.`; + vscode.window.showErrorMessage(message, "Select Godot executable", "Disable Headless LSP", "Ignore").then(item => { + if (item == "Select Godot executable") { + this.select_godot_executable(settingName); + } else if (item == "Disable Headless LSP") { + set_configuration("lsp.headless", false); + this.prompt_for_reload(); + } + }); + return; + } + } catch (e) { + const message = `Cannot launch headless LSP: ${settingName} of ${godotPath} is not a valid Godot executable`; + vscode.window.showErrorMessage(message, "Select Godot executable", "Ignore").then(item => { + if (item == "Select Godot executable") { + this.select_godot_executable(settingName); + } + }); + return; + } + + this.client.port = await get_free_port(); + + log.info(`starting headless LSP on port ${this.client.port}`); + + const headlessFlags = "--headless --no-window"; + const command = `${godotPath} --path "${projectDir}" --editor ${headlessFlags} --lsp-port ${this.client.port}`; + const lspProcess = subProcess("LSP", command, { shell: true }); + + const lspStdout = createLogger("lsp.stdout"); + lspProcess.stdout.on('data', (data) => { + const out = data.toString().trim(); + if (out) { + lspStdout.debug(out); + } + }); + + // const lspStderr = createLogger("lsp.stderr"); + // lspProcess.stderr.on('data', (data) => { + // const out = data.toString().trim(); + // if (out) { + // lspStderr.debug(out); + // } + // }); + + lspProcess.on('close', (code) => { + log.info(`LSP process exited with code ${code}`); + }); + } + + private async select_godot_executable(settingName: string) { + vscode.window.showOpenDialog({ + openLabel: "Select Godot executable", + filters: process.platform === "win32" ? { "Godot Editor Binary": ["exe", "EXE"] } : undefined + }).then(async (uris: vscode.Uri[]) => { + if (!uris) { + return; + } + const path = uris[0].fsPath; + set_configuration(settingName, path); + this.prompt_for_reload(); + }); + } + + private async prompt_for_reload() { + const message = `Reload VSCode to apply settings`; + vscode.window.showErrorMessage(message, "Reload").then(item => { + if (item == "Reload") { + vscode.commands.executeCommand("workbench.action.reloadWindow"); + } + }); + } + + private get_lsp_connection_string() { + let host = get_configuration("lsp.serverHost"); + let port = get_configuration("lsp.serverPort"); + if (this.client.port !== -1) { + port = this.client.port; + } + return `${host}:${port}`; + } + + private on_status_item_click() { + const lsp_target = this.get_lsp_connection_string(); + // TODO: fill these out with the ACTIONS a user could perform in each state + switch (this.status) { + case ManagerStatus.INITIALIZING: + // vscode.window.showInformationMessage("Initializing extension"); + break; + case ManagerStatus.INITIALIZING_LSP: + // vscode.window.showInformationMessage("Initializing LSP"); + break; + case ManagerStatus.PENDING: + // vscode.window.showInformationMessage(`Connecting to the GDScript language server at ${lsp_target}`); + break; + case ManagerStatus.CONNECTED: + // vscode.window.showInformationMessage("Connected to the GDScript language server."); + break; + case ManagerStatus.DISCONNECTED: + this.retry_connect_client(); + break; + case ManagerStatus.RETRYING: + break; + } + } + + private update_status_widget() { + const lsp_target = this.get_lsp_connection_string(); + switch (this.status) { + case ManagerStatus.INITIALIZING: + // this.statusWidget.text = `INITIALIZING`; + this.statusWidget.text = `$(sync~spin) Initializing`; + this.statusWidget.tooltip = `Initializing extension...`; + break; + case ManagerStatus.INITIALIZING_LSP: + // this.statusWidget.text = `INITIALIZING_LSP ` + this.reconnection_attempts; + this.statusWidget.text = `$(sync~spin) Initializing LSP`; + this.statusWidget.tooltip = `Connecting to headless GDScript language server at ${lsp_target}`; + break; + case ManagerStatus.PENDING: + // this.statusWidget.text = `PENDING`; + this.statusWidget.text = `$(sync~spin) Connecting`; + this.statusWidget.tooltip = `Connecting to the GDScript language server at ${lsp_target}`; + break; + case ManagerStatus.CONNECTED: + // this.statusWidget.text = `CONNECTED`; + this.statusWidget.text = `$(check) Connected`; + this.statusWidget.tooltip = `Connected to the GDScript language server.`; + break; + case ManagerStatus.DISCONNECTED: + // this.statusWidget.text = `DISCONNECTED`; + this.statusWidget.text = `$(x) Disconnected`; + this.statusWidget.tooltip = `Disconnected from the GDScript language server.`; + break; + case ManagerStatus.RETRYING: + // this.statusWidget.text = `RETRYING ` + this.reconnection_attempts; + this.statusWidget.text = `$(sync~spin) Connecting ` + this.reconnection_attempts; + this.statusWidget.tooltip = `Connecting to the GDScript language server at ${lsp_target}`; + break; + } + } + + private on_client_status_changed(status: ClientStatus) { + switch (status) { + case ClientStatus.PENDING: + this.status = ManagerStatus.PENDING; + break; + case ClientStatus.CONNECTED: + this.retry = false; + set_context("connectedToLSP", true); + this.status = ManagerStatus.CONNECTED; + if (!this.client.started) { + this.context.subscriptions.push(this.client.start()); + } + break; + case ClientStatus.DISCONNECTED: + set_context("connectedToLSP", false); + if (this.retry) { + if (this.client.port != -1) { + this.status = ManagerStatus.INITIALIZING_LSP; + } else { + this.status = ManagerStatus.RETRYING; + } + } else { + this.status = ManagerStatus.DISCONNECTED; + } + this.retry = true; + break; + default: + break; + } + this.update_status_widget(); + } + + private retry = false; + + private retry_callback() { + if (this.retry) { + this.retry_connect_client(); + } + } + + private retry_connect_client() { + const auto_retry = get_configuration("lsp.autoReconnect.enabled"); + const max_attempts = get_configuration("lsp.autoReconnect.attempts"); + if (auto_retry && this.reconnection_attempts <= max_attempts - 1) { + this.reconnection_attempts++; + this.client.connect_to_server(); + this.retry = true; + return; + } + + this.retry = false; + this.status = ManagerStatus.DISCONNECTED; + this.update_status_widget(); + + const lsp_target = this.get_lsp_connection_string(); + let message = `Couldn't connect to the GDScript language server at ${lsp_target}. Is the Godot editor or language server running?`; + vscode.window.showErrorMessage(message, "Retry", "Ignore").then(item => { + if (item == "Retry") { + this.connect_to_language_server(); + } + }); + } +} diff --git a/src/lsp/GDScriptLanguageClient.ts b/src/lsp/GDScriptLanguageClient.ts index cc4127568..40ee2b19c 100644 --- a/src/lsp/GDScriptLanguageClient.ts +++ b/src/lsp/GDScriptLanguageClient.ts @@ -1,11 +1,13 @@ import { EventEmitter } from "events"; import * as vscode from 'vscode'; -import { LanguageClient, RequestMessage } from "vscode-languageclient/node"; -import logger from "../logger"; -import { get_configuration, is_debug_mode } from "../utils"; +import { LanguageClient, RequestMessage, ResponseMessage } from "vscode-languageclient/node"; +import { createLogger } from "../logger"; +import { get_configuration, set_context } from "../utils"; import { Message, MessageIO, MessageIOReader, MessageIOWriter, TCPMessageIO, WebSocketMessageIO } from "./MessageIO"; import NativeDocumentManager from './NativeDocumentManager'; +const log = createLogger("lsp.client"); + export enum ClientStatus { PENDING, DISCONNECTED, @@ -15,19 +17,23 @@ const CUSTOM_MESSAGE = "gdscrip_client/"; export default class GDScriptLanguageClient extends LanguageClient { - public readonly io: MessageIO = (get_configuration("lsp.serverProtocol", "tcp") == "ws") ? new WebSocketMessageIO() : new TCPMessageIO(); + public readonly io: MessageIO = (get_configuration("lsp.serverProtocol") == "ws") ? new WebSocketMessageIO() : new TCPMessageIO(); private context: vscode.ExtensionContext; - private _started : boolean = false; - private _status : ClientStatus; - private _status_changed_callbacks: ((v : ClientStatus)=>void)[] = []; + private _started: boolean = false; + private _status: ClientStatus; + private _status_changed_callbacks: ((v: ClientStatus) => void)[] = []; private _initialize_request: Message = null; private message_handler: MessageHandler = null; private native_doc_manager: NativeDocumentManager = null; - public get started() : boolean { return this._started; } - public get status() : ClientStatus { return this._status; } - public set status(v : ClientStatus) { + public port: number = -1; + public sentMessages = new Map(); + public lastSymbolHovered: string = ""; + + public get started(): boolean { return this._started; } + public get status(): ClientStatus { return this._status; } + public set status(v: ClientStatus) { if (this._status != v) { this._status = v; for (const callback of this._status_changed_callbacks) { @@ -36,14 +42,15 @@ export default class GDScriptLanguageClient extends LanguageClient { } } - public watch_status(callback: (v : ClientStatus)=>void) { + public watch_status(callback: (v: ClientStatus) => void) { if (this._status_changed_callbacks.indexOf(callback) == -1) { this._status_changed_callbacks.push(callback); } } - public open_documentation(symbolName: string) { - this.native_doc_manager.request_documentation(symbolName); + public open_documentation() { + const symbol = this.lastSymbolHovered; + this.native_doc_manager.request_documentation(symbol); } constructor(context: vscode.ExtensionContext) { @@ -51,7 +58,7 @@ export default class GDScriptLanguageClient extends LanguageClient { `GDScriptLanguageClient`, () => { return new Promise((resolve, reject) => { - resolve({reader: new MessageIOReader(this.io), writer: new MessageIOWriter(this.io)}); + resolve({ reader: new MessageIOReader(this.io), writer: new MessageIOWriter(this.io) }); }); }, { @@ -78,45 +85,91 @@ export default class GDScriptLanguageClient extends LanguageClient { connect_to_server() { this.status = ClientStatus.PENDING; - let host = get_configuration("lsp.serverHost", "127.0.0.1"); - let port = get_configuration("lsp.serverPort", 6008); + const host = get_configuration("lsp.serverHost"); + let port = get_configuration("lsp.serverPort"); + if (this.port !== -1) { + port = this.port; + } + log.info(`attempting to connect to LSP at port ${port}`); this.io.connect_to_language_server(host, port); } - start(): vscode.Disposable { + start() { this._started = true; return super.start(); } - private on_send_message(message: Message) { - if (is_debug_mode()) { - logger.log("[client]", JSON.stringify(message)); - } - if ((message as RequestMessage).method == "initialize") { + private on_send_message(message: RequestMessage) { + log.debug("tx: " + JSON.stringify(message)); + + this.sentMessages.set(message.id, message.method); + + if (message.method == "initialize") { this._initialize_request = message; } } - private on_message(message: Message) { - if (is_debug_mode()) { - logger.log("[server]", JSON.stringify(message)); - } + private on_message(message: ResponseMessage) { + const msgString = JSON.stringify(message); + log.debug("rx: " + msgString); // This is a dirty hack to fix the language server sending us // invalid file URIs // This should be forward-compatible, meaning that it will work // with the current broken version, AND the fixed future version. - const match = JSON.stringify(message).match(/"target":"file:\/\/[^\/][^"]*"/); + const match = msgString.match(/"target":"file:\/\/[^\/][^"]*"/); if (match) { - for (let i = 0; i < message["result"].length; i++) { - const x = message["result"][i]["target"]; + const count = (message["result"] as Array).length; + for (let i = 0; i < count; i++) { + const x: string = message["result"][i]["target"]; message["result"][i]["target"] = x.replace('file://', 'file:///'); } } + const method = this.sentMessages.get(message.id); + if (method === "textDocument/hover") { + this.handle_hover_response(message); + + // this is a dirty hack to fix language server sending us prerendered + // markdown but not correctly stripping leading #'s, leading to + // docstrings being displayed as titles + const value: string = message.result["contents"].value; + message.result["contents"].value = value.replace(/\n[#]+/g, '\n'); + } + this.message_handler.on_message(message); } + private handle_hover_response(message: ResponseMessage) { + this.lastSymbolHovered = ""; + set_context("typeFound", false); + + let decl: string = message.result["contents"].value; + decl = decl.split('\n')[0].trim(); + + // strip off the value + if (decl.includes("=")) { + decl = decl.split("=")[0]; + } + if (decl.includes(":")) { + const parts = decl.split(":"); + if (parts.length === 2) { + decl = parts[1].trim(); + + } + } + if (decl.includes("")) { + decl = decl.split(" ")[2]; + } + + if (decl.includes(" ")) { + return; + } + + this.lastSymbolHovered = decl; + set_context("typeFound", true); + } + private on_connected() { if (this._initialize_request) { this.io.writer.write(this._initialize_request); @@ -129,10 +182,7 @@ export default class GDScriptLanguageClient extends LanguageClient { } } - - class MessageHandler extends EventEmitter { - private io: MessageIO = null; constructor(io: MessageIO) { @@ -140,8 +190,8 @@ class MessageHandler extends EventEmitter { this.io = io; } - changeWorkspace(params: {path: string}) { - vscode.window.showErrorMessage("The GDScript language server can't work properly!\nThe open workspace is different from the editor's.", 'Reload', 'Ignore').then(item=>{ + changeWorkspace(params: { path: string }) { + vscode.window.showErrorMessage("The GDScript language server can't work properly!\nThe open workspace is different from the editor's.", 'Reload', 'Ignore').then(item => { if (item == "Reload") { let folderUrl = vscode.Uri.file(params.path); vscode.commands.executeCommand('vscode.openFolder', folderUrl, false); @@ -150,7 +200,6 @@ class MessageHandler extends EventEmitter { } on_message(message: any) { - // FIXME: Hot fix VSCode 1.42 hover position if (message && message.result && message.result.range && message.result.contents) { message.result.range = undefined; diff --git a/src/lsp/MessageBuffer.ts b/src/lsp/MessageBuffer.ts index f2d63c84a..d70c66755 100644 --- a/src/lsp/MessageBuffer.ts +++ b/src/lsp/MessageBuffer.ts @@ -10,12 +10,12 @@ const CRLF: string = '\r\n'; export default class MessageBuffer { - private encoding: string; + private encoding: BufferEncoding; private index: number; private buffer: Buffer; constructor(encoding: string = 'utf8') { - this.encoding = encoding; + this.encoding = encoding as BufferEncoding; this.index = 0; this.buffer = Buffer.allocUnsafe(DefaultSize); } diff --git a/src/lsp/MessageIO.ts b/src/lsp/MessageIO.ts index 3899b05e1..ba652e331 100644 --- a/src/lsp/MessageIO.ts +++ b/src/lsp/MessageIO.ts @@ -108,7 +108,7 @@ export class MessageIOReader extends AbstractMessageReader implements MessageRea private buffer: MessageBuffer; private nextMessageLength: number; private messageToken: number; - private partialMessageTimer: NodeJS.Timer | undefined; + private partialMessageTimer: NodeJS.Timeout | undefined; private _partialMessageTimeout: number; public constructor(io: MessageIO, encoding: string = 'utf8') { @@ -204,14 +204,14 @@ const CRLF = '\r\n'; export class MessageIOWriter extends AbstractMessageWriter implements MessageWriter { private io: MessageIO; - private encoding: string; + private encoding: BufferEncoding; private errorCount: number; public constructor(io: MessageIO, encoding: string = 'utf8') { super(); this.io = io; this.io.writer = this; - this.encoding = encoding; + this.encoding = encoding as BufferEncoding; this.errorCount = 0; this.io.on('error', (error: any) => this.fireError(error)); this.io.on('close', () => this.fireClose()); diff --git a/src/lsp/NativeDocumentManager.ts b/src/lsp/NativeDocumentManager.ts index 7bf456280..9394783f0 100644 --- a/src/lsp/NativeDocumentManager.ts +++ b/src/lsp/NativeDocumentManager.ts @@ -5,7 +5,7 @@ import { MessageIO } from "./MessageIO"; import { NotificationMessage } from "vscode-jsonrpc"; import * as Prism from "../deps/prism/prism"; import * as marked from "marked"; -import { get_configuration } from "../utils"; +import { get_configuration, register_command } from "../utils"; import { Methods, NativeSymbolInspectParams, @@ -13,6 +13,7 @@ import { GodotNativeClassInfo, GodotCapabilities, } from "./gdscript.capabilities"; + marked.setOptions({ highlight: function (code, lang) { return Prism.highlight(code, GDScriptGrammar, lang); @@ -52,10 +53,7 @@ export default class NativeDocumentManager extends EventEmitter { } }); - vscode.commands.registerCommand( - "godotTools.listNativeClasses", - this.list_native_classes.bind(this) - ); + register_command("listNativeClasses", this.list_native_classes.bind(this)); } public request_documentation(symbolName: string) { @@ -85,7 +83,7 @@ export default class NativeDocumentManager extends EventEmitter { private inspect_native_symbol(params: NativeSymbolInspectParams) { let json_data = ""; - if (get_configuration("lsp.serverProtocol", "tcp") == "ws") { + if (get_configuration("lsp.serverProtocol") == "ws") { json_data = JSON.stringify({ id: -1, jsonrpc: "2.0", @@ -129,7 +127,7 @@ export default class NativeDocumentManager extends EventEmitter { * configuration and previously opened native symbols. */ private get_new_native_symbol_column(): vscode.ViewColumn { - const config_placement = get_configuration("nativeSymbolPlacement", "beside"); + const config_placement = get_configuration("nativeSymbolPlacement"); if (config_placement == "active") { return vscode.ViewColumn.Active; @@ -297,8 +295,7 @@ export default class NativeDocumentManager extends EventEmitter { ); const title = element( "p", - `${ - with_class ? `signal ${with_class ? `${classlink}.` : ""}` : "" + `${with_class ? `signal ${with_class ? `${classlink}.` : ""}` : "" }${s.name}( ${args} )` ); const doc = element( @@ -439,9 +436,8 @@ function element( props_str += ` ${key}="${props[key]}"`; } } - return `${indent || ""}<${tag} ${props_str}>${content}${ - new_line ? "\n" : "" - }`; + return `${indent || ""}<${tag} ${props_str}>${content}${new_line ? "\n" : "" + }`; } function make_link(classname: string, symbol: string) { if (!symbol || symbol == classname) { diff --git a/src/scene_preview_provider.ts b/src/scene_preview_provider.ts index 3f2b97d94..adb267b0e 100644 --- a/src/scene_preview_provider.ts +++ b/src/scene_preview_provider.ts @@ -10,12 +10,16 @@ import { import path = require("path"); import fs = require("fs"); import * as vscode from "vscode"; -import { get_configuration, set_configuration, find_file, set_context, convert_resource_path_to_uri } from "./utils"; -import logger from "./logger"; +import { + get_configuration, + find_file, + set_context, + convert_resource_path_to_uri, + register_command, +} from "./utils"; +import { createLogger } from "./logger"; -function log(...messages) { - logger.log("[scene preview]", messages); -} +const log = createLogger("scene preview"); export class ScenePreviewProvider implements TreeDataProvider { private root: SceneNode | undefined; @@ -84,15 +88,15 @@ export class ScenePreviewProvider implements TreeDataProvider { this.tree.onDidChangeSelection(this.tree_selection_changed); - vscode.commands.registerCommand("godotTools.scenePreview.pin", this.pin_preview.bind(this)); - vscode.commands.registerCommand("godotTools.scenePreview.unpin", this.unpin_preview.bind(this)); - vscode.commands.registerCommand("godotTools.scenePreview.copyNodePath", this.copy_node_path.bind(this)); - vscode.commands.registerCommand("godotTools.scenePreview.copyResourcePath", this.copy_resource_path.bind(this)); - vscode.commands.registerCommand("godotTools.scenePreview.openScene", this.open_scene.bind(this)); - vscode.commands.registerCommand("godotTools.scenePreview.openScript", this.open_script.bind(this)); - vscode.commands.registerCommand("godotTools.scenePreview.goToDefinition", this.go_to_definition.bind(this)); + register_command("scenePreview.pin", this.pin_preview.bind(this)); + register_command("scenePreview.unpin", this.unpin_preview.bind(this)); + register_command("scenePreview.copyNodePath", this.copy_node_path.bind(this)); + register_command("scenePreview.copyResourcePath", this.copy_resource_path.bind(this)); + register_command("scenePreview.openScene", this.open_scene.bind(this)); + register_command("scenePreview.openScript", this.open_script.bind(this)); + register_command("scenePreview.goToDefinition", this.go_to_definition.bind(this)); - vscode.commands.registerCommand("godotTools.scenePreview.refresh", () => + register_command("scenePreview.refresh", () => this.refresh() ); diff --git a/src/utils.ts b/src/utils.ts index 081111c86..d0b68a3ef 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,49 +1,106 @@ import * as vscode from "vscode"; import * as path from "path"; import * as fs from "fs"; +import { AddressInfo, createServer } from "net"; -const CONFIG_CONTAINER = "godotTools"; +const EXTENSION_PREFIX = "godotTools"; -export function get_configuration(name: string, default_value: any = null) { - let config_value = vscode.workspace.getConfiguration(CONFIG_CONTAINER).get(name, null); - if (config_value === null) { +const config = vscode.workspace.getConfiguration(EXTENSION_PREFIX); + +export function get_configuration(name: string, default_value?: any) { + let config_value = config.get(name, null); + if (default_value && config_value === null) { return default_value; } return config_value; } export function set_configuration(name: string, value: any) { - return vscode.workspace.getConfiguration(CONFIG_CONTAINER).update(name, value); + return config.update(name, value); } export function is_debug_mode(): boolean { return process.env.VSCODE_DEBUG_MODE === "true"; } +const CONTEXT_PREFIX = `${EXTENSION_PREFIX}.context.`; + export function set_context(name: string, value: any) { - vscode.commands.executeCommand("setContext", name, value); + return vscode.commands.executeCommand("setContext", CONTEXT_PREFIX + name, value); +} + +export function register_command(command: string, callback: (...args: any[]) => any, thisArg?: any): vscode.Disposable { + return vscode.commands.registerCommand(`${EXTENSION_PREFIX}.${command}`, callback); +} + +export function get_word_under_cursor(): string { + const activeEditor = vscode.window.activeTextEditor; + const document = activeEditor.document; + const curPos = activeEditor.selection.active; + const wordRange = document.getWordRangeAtPosition(curPos); + const symbolName = document.getText(wordRange); + return symbolName; +} + +export async function get_project_version(): Promise { + const project_dir = await get_project_dir(); + + if (!project_dir) { + return undefined; + } + + let godot_version = '3.x'; + const project_file = vscode.Uri.file(path.join(project_dir, 'project.godot')); + const document = await vscode.workspace.openTextDocument(project_file); + const text = document.getText(); + + const match = text.match(/config\/features=PackedStringArray\((.*)\)/); + if (match) { + const line = match[0]; + const version = line.match(/\"(4.[0-9]+)\"/); + if (version) { + godot_version = version[1]; + } + } + return godot_version; } -export function find_project_file(start: string, depth:number=20) { - // This function appears to be fast enough, but if speed is ever an issue, - // memoizing the result should be straightforward - const folder = path.dirname(start); - if (start == folder) { - return null; - } - const project_file = path.join(folder, "project.godot"); - - if (fs.existsSync(project_file)) { - return project_file; - } else { - if (depth === 0) { - return null; - } - return find_project_file(folder, depth - 1); - } +export async function get_project_dir() { + let project_dir = undefined; + let project_file = ''; + if (vscode.workspace.workspaceFolders != undefined) { + const files = await vscode.workspace.findFiles("**/project.godot"); + if (files) { + project_file = files[0].fsPath; + if (fs.existsSync(project_file) && fs.statSync(project_file).isFile()) { + project_dir = path.dirname(project_file); + } + } + } + return project_dir; } -export async function find_file(file: string): Promise { +export function find_project_file(start: string, depth: number = 20) { + // TODO: rename this, it's actually more like "find_parent_project_file" + // This function appears to be fast enough, but if speed is ever an issue, + // memoizing the result should be straightforward + const folder = path.dirname(start); + if (start == folder) { + return null; + } + const project_file = path.join(folder, "project.godot"); + + if (fs.existsSync(project_file) && fs.statSync(project_file).isFile()) { + return project_file; + } else { + if (depth === 0) { + return null; + } + return find_project_file(folder, depth - 1); + } +} + +export async function find_file(file: string): Promise { if (fs.existsSync(file)) { return vscode.Uri.file(file); } else { @@ -56,7 +113,7 @@ export async function find_file(file: string): Promise { return null; } -export async function convert_resource_path_to_uri(resPath: string): Promise { +export async function convert_resource_path_to_uri(resPath: string): Promise { const files = await vscode.workspace.findFiles("**/project.godot"); if (!files) { return null; @@ -64,3 +121,13 @@ export async function convert_resource_path_to_uri(resPath: string): Promise { + return new Promise(res => { + const srv = createServer(); + srv.listen(0, () => { + const port = (srv.address() as AddressInfo).port; + srv.close((err) => res(port)); + }); + }); +} diff --git a/src/utils/subspawn.ts b/src/utils/subspawn.ts new file mode 100644 index 000000000..2e633729d --- /dev/null +++ b/src/utils/subspawn.ts @@ -0,0 +1,52 @@ +/* +Copied from https://github.com/craigwardman/subspawn +Original library copyright (c) 2022 Craig Wardman + +I had to vendor this library to fix the API in a couple places. +*/ + +import { ChildProcess, execSync, spawn, SpawnOptions } from 'child_process'; + +interface DictionaryOfStringChildProcessArray { + [key: string]: ChildProcess[]; +} +const children: DictionaryOfStringChildProcessArray = {}; + +export function killSubProcesses(owner: string) { + if (!(owner in children)) { + return; + } + + children[owner].forEach((c) => { + try { + if (c.pid) { + if (process.platform === 'win32') { + execSync(`taskkill /pid ${c.pid} /T /F`); + } else { + process.kill(-c.pid); + } + } + } catch { } + }); +} + +process.on('exit', () => { + Object.keys(children).forEach((owner) => killSubProcesses(owner)); +}); + +function gracefulExitHandler() { + process.exit(); +} + +process.on('SIGINT', gracefulExitHandler); +process.on('SIGTERM', gracefulExitHandler); +process.on('SIGQUIT', gracefulExitHandler); + +export function subProcess(owner: string, command: string, options?: SpawnOptions) { + const childProcess = spawn(command, options); + + children[owner] = children[owner] || []; + children[owner].push(childProcess); + + return childProcess; +} diff --git a/tsconfig.json b/tsconfig.json index c8140d666..d5b58a735 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "module": "commonjs", - "target": "es6", + "target": "es2020", "outDir": "out", "lib": [ "es2020",