diff --git a/.gitignore b/.gitignore index 90456bc..8523edb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ **/out/ *.vsix /server/lib/isclexer.node +/server/lib/ascot.core*.wasm **/tsconfig.tsbuildinfo diff --git a/.vscodeignore b/.vscodeignore index ae09c7a..2319f42 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -12,7 +12,7 @@ client/webpack.config.js server/node_modules/** server/src/** server/webpack.config.js -server/lib/** +server/lib/*-isclexer.node node_modules/** images/*.gif **/*.vsix diff --git a/client/package-lock.json b/client/package-lock.json index a59400d..a170cf6 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,12 +1,12 @@ { "name": "language-server-client", - "version": "2.8.4-SNAPSHOT", + "version": "2.9.0-LOCAL", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "language-server-client", - "version": "2.8.4-SNAPSHOT", + "version": "2.9.0-LOCAL", "dependencies": { "axios": "^1.19.0", "vscode-languageclient": "^9.0.1" @@ -38,7 +38,8 @@ "version": "1.93.0", "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.93.0.tgz", "integrity": "sha512-kUK6jAHSR5zY8ps42xuW89NLcBpw1kOabah7yv38J8MyiYuOHxLQBi0e7zeXbQgVefDy/mZZetqEFC+Fl5eIEQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/agent-base": { "version": "6.0.2", @@ -59,9 +60,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", - "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz", + "integrity": "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==", "license": "MIT", "dependencies": { "follow-redirects": "^1.16.0", @@ -494,9 +495,9 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "axios": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", - "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz", + "integrity": "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==", "requires": { "follow-redirects": "^1.16.0", "form-data": "^4.0.6", diff --git a/client/package.json b/client/package.json index c936b29..4811729 100644 --- a/client/package.json +++ b/client/package.json @@ -1,7 +1,7 @@ { "name": "language-server-client", "author": "InterSystems Corporation", - "version": "2.8.5-SNAPSHOT", + "version": "2.9.0-LOCAL", "private": true, "engines": { "vscode": "^1.93.0" diff --git a/eslint.config.mjs b/eslint.config.mjs index 4fc8daa..5bc7480 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -10,6 +10,7 @@ export default tseslint.config( "server/out/**", "common/out/**", "**/*.config.{mjs,js}", + "server/src/ascot/generated/**", ], }, eslint.configs.recommended, diff --git a/package-lock.json b/package-lock.json index 78aae22..d9e4b20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,21 @@ { "name": "language-server", - "version": "2.8.4-SNAPSHOT", + "version": "2.9.0-LOCAL", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "language-server", - "version": "2.8.4-SNAPSHOT", + "version": "2.9.0-LOCAL", "hasInstallScript": true, "license": "SEE LICENSE IN LICENSE.txt", "devDependencies": { "@eslint/js": "^10.0.1", + "@types/eslint": "^9.6.1", "@types/node": "^22.15.33", "@types/turndown": "^5.0.6", "@vscode/vsce": "^3.9.2", + "copy-webpack-plugin": "^14.0.0", "eslint": "^10.2.1", "merge-options": "^3.0.4", "node-loader": "^2.1.0", @@ -27,9 +29,14 @@ "webpack-cli": "^7.0.2" }, "engines": { - "vscode": "^1.93.0" + "vscode": "^1.103.0" } }, + "../iris-class/pkg": { + "name": "iris-class", + "version": "0.1.0", + "extraneous": true + }, "node_modules/@azu/format-text": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@azu/format-text/-/format-text-1.0.2.tgz", @@ -259,40 +266,6 @@ "node": ">=14.17.0" } }, - "node_modules/@emnapi/core": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", - "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.0.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", - "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", @@ -1208,19 +1181,6 @@ "node": ">= 10" } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz", - "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.9.0" - } - }, "node_modules/@node-rs/crc32": { "version": "1.10.6", "resolved": "https://registry.npmjs.org/@node-rs/crc32/-/crc32-1.10.6.tgz", @@ -1251,40 +1211,6 @@ "@node-rs/crc32-win32-x64-msvc": "1.10.6" } }, - "node_modules/@node-rs/crc32-android-arm-eabi": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-android-arm-eabi/-/crc32-android-arm-eabi-1.10.6.tgz", - "integrity": "sha512-vZAMuJXm3TpWPOkkhxdrofWDv+Q+I2oO7ucLRbXyAPmXFNDhHtBxbO1rk9Qzz+M3eep8ieS4/+jCL1Q0zacNMQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/crc32-android-arm64": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-android-arm64/-/crc32-android-arm64-1.10.6.tgz", - "integrity": "sha512-Vl/JbjCinCw/H9gEpZveWCMjxjcEChDcDBM8S4hKay5yyoRCUHJPuKr4sjVDBeOm+1nwU3oOm6Ca8dyblwp4/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@node-rs/crc32-darwin-arm64": { "version": "1.10.6", "resolved": "https://registry.npmjs.org/@node-rs/crc32-darwin-arm64/-/crc32-darwin-arm64-1.10.6.tgz", @@ -1302,193 +1228,6 @@ "node": ">= 10" } }, - "node_modules/@node-rs/crc32-darwin-x64": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-darwin-x64/-/crc32-darwin-x64-1.10.6.tgz", - "integrity": "sha512-Q99bevJVMfLTISpkpKBlXgtPUItrvTWKFyiqoKH5IvscZmLV++NH4V13Pa17GTBmv9n18OwzgQY4/SRq6PQNVA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/crc32-freebsd-x64": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-freebsd-x64/-/crc32-freebsd-x64-1.10.6.tgz", - "integrity": "sha512-66hpawbNjrgnS9EDMErta/lpaqOMrL6a6ee+nlI2viduVOmRZWm9Rg9XdGTK/+c4bQLdtC6jOd+Kp4EyGRYkAg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/crc32-linux-arm-gnueabihf": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm-gnueabihf/-/crc32-linux-arm-gnueabihf-1.10.6.tgz", - "integrity": "sha512-E8Z0WChH7X6ankbVm8J/Yym19Cq3otx6l4NFPS6JW/cWdjv7iw+Sps2huSug+TBprjbcEA+s4TvEwfDI1KScjg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/crc32-linux-arm64-gnu": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm64-gnu/-/crc32-linux-arm64-gnu-1.10.6.tgz", - "integrity": "sha512-LmWcfDbqAvypX0bQjQVPmQGazh4dLiVklkgHxpV4P0TcQ1DT86H/SWpMBMs/ncF8DGuCQ05cNyMv1iddUDugoQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/crc32-linux-arm64-musl": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm64-musl/-/crc32-linux-arm64-musl-1.10.6.tgz", - "integrity": "sha512-k8ra/bmg0hwRrIEE8JL1p32WfaN9gDlUUpQRWsbxd1WhjqvXea7kKO6K4DwVxyxlPhBS9Gkb5Urq7Y4mXANzaw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/crc32-linux-x64-gnu": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-x64-gnu/-/crc32-linux-x64-gnu-1.10.6.tgz", - "integrity": "sha512-IfjtqcuFK7JrSZ9mlAFhb83xgium30PguvRjIMI45C3FJwu18bnLk1oR619IYb/zetQT82MObgmqfKOtgemEKw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/crc32-linux-x64-musl": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-x64-musl/-/crc32-linux-x64-musl-1.10.6.tgz", - "integrity": "sha512-LbFYsA5M9pNunOweSt6uhxenYQF94v3bHDAQRPTQ3rnjn+mK6IC7YTAYoBjvoJP8lVzcvk9hRj8wp4Jyh6Y80g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/crc32-wasm32-wasi": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-wasm32-wasi/-/crc32-wasm32-wasi-1.10.6.tgz", - "integrity": "sha512-KaejdLgHMPsRaxnM+OG9L9XdWL2TabNx80HLdsCOoX9BVhEkfh39OeahBo8lBmidylKbLGMQoGfIKDjq0YMStw==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.5" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@node-rs/crc32-win32-arm64-msvc": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-arm64-msvc/-/crc32-win32-arm64-msvc-1.10.6.tgz", - "integrity": "sha512-x50AXiSxn5Ccn+dCjLf1T7ZpdBiV1Sp5aC+H2ijhJO4alwznvXgWbopPRVhbp2nj0i+Gb6kkDUEyU+508KAdGQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/crc32-win32-ia32-msvc": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-ia32-msvc/-/crc32-win32-ia32-msvc-1.10.6.tgz", - "integrity": "sha512-DpDxQLaErJF9l36aghe1Mx+cOnYLKYo6qVPqPL9ukJ5rAGLtCdU0C+Zoi3gs9ySm8zmbFgazq/LvmsZYU42aBw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/crc32-win32-x64-msvc": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-x64-msvc/-/crc32-win32-x64-msvc-1.10.6.tgz", - "integrity": "sha512-5B1vXosIIBw1m2Rcnw62IIfH7W9s9f7H7Ma0rRuhT8HR4Xh8QCgw6NJSI2S2MCngsGktYnAhyUvs81b7efTyQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1820,37 +1559,17 @@ "@textlint/ast-node-types": "15.5.0" } }, - "node_modules/@tybys/wasm-util": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", - "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/eslint": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/esrecurse": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", @@ -2203,32 +1922,6 @@ "@vscode/vsce-sign-win32-x64": "2.0.2" } }, - "node_modules/@vscode/vsce-sign-alpine-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.2.tgz", - "integrity": "sha512-E80YvqhtZCLUv3YAf9+tIbbqoinWLCO/B3j03yQPbjT3ZIHCliKZlsy1peNc4XNZ5uIb87Jn0HWx/ZbPXviuAQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "alpine" - ] - }, - "node_modules/@vscode/vsce-sign-alpine-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.2.tgz", - "integrity": "sha512-n1WC15MSMvTaeJ5KjWCzo0nzjydwxLyoHiMJHu1Ov0VWTZiddasmOQHekA47tFRycnt4FsQrlkSCTdgHppn6bw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "alpine" - ] - }, "node_modules/@vscode/vsce-sign-darwin-arm64": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.2.tgz", @@ -2242,84 +1935,6 @@ "darwin" ] }, - "node_modules/@vscode/vsce-sign-darwin-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.2.tgz", - "integrity": "sha512-MCjPrQ5MY/QVoZ6n0D92jcRb7eYvxAujG/AH2yM6lI0BspvJQxp0o9s5oiAM9r32r9tkLpiy5s2icsbwefAQIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@vscode/vsce-sign-linux-arm": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.2.tgz", - "integrity": "sha512-Fkb5jpbfhZKVw3xwR6t7WYfwKZktVGNXdg1m08uEx1anO0oUPUkoQRsNm4QniL3hmfw0ijg00YA6TrxCRkPVOQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@vscode/vsce-sign-linux-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.2.tgz", - "integrity": "sha512-Ybeu7cA6+/koxszsORXX0OJk9N0GgfHq70Wqi4vv2iJCZvBrOWwcIrxKjvFtwyDgdeQzgPheH5nhLVl5eQy7WA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@vscode/vsce-sign-linux-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.2.tgz", - "integrity": "sha512-NsPPFVtLaTlVJKOiTnO8Cl78LZNWy0Q8iAg+LlBiCDEgC12Gt4WXOSs2pmcIjDYzj2kY4NwdeN1mBTaujYZaPg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@vscode/vsce-sign-win32-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.2.tgz", - "integrity": "sha512-wPs848ymZ3Ny+Y1Qlyi7mcT6VSigG89FWQnp2qRYCyMhdJxOpA4lDwxzlpL8fG6xC8GjQjGDkwbkWUcCobvksQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@vscode/vsce-sign-win32-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.2.tgz", - "integrity": "sha512-pAiRN6qSAhDM5SVOIxgx+2xnoVUePHbRNC7OD2aOR3WltTKxxF25OfpK8h8UQ7A0BuRkSgREbB59DBlFk4iAeg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@vscode/vsce/node_modules/commander": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", @@ -3099,6 +2714,43 @@ "dev": true, "license": "MIT" }, + "node_modules/copy-webpack-plugin": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-14.0.0.tgz", + "integrity": "sha512-3JLW90aBGeaTLpM7mYQKpnVdgsUZRExY55giiZgLuX/xTQRUs1dOCwbBnWnvY6Q6rfZoXMNwzOQJCSZPppfqXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-parent": "^6.0.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.2.0", + "serialize-javascript": "^7.0.3", + "tinyglobby": "^0.2.12" + }, + "engines": { + "node": ">= 20.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/cross-keychain": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/cross-keychain/-/cross-keychain-1.1.0.tgz", @@ -5389,6 +5041,16 @@ "dev": true, "license": "ISC" }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -6142,6 +5804,16 @@ "node": ">=10" } }, + "node_modules/serialize-javascript": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.1.1.tgz", + "integrity": "sha512-k3CMsaIvvdSwm8oLB4MXSl0wH2/cwlH7xGcnRd2DaeRmBkbzYmyT8j0tsX60DwD1eRwHTpNpH8ljKu9oUT1MeQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -7258,6 +6930,17 @@ "node": ">=10.13.0" } }, + "node_modules/webpack/node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7668,37 +7351,6 @@ "integrity": "sha512-dDlz3W405VMFO4w5kIP9DOmELBcvFQGmLoKSdIRstBDubKFYwaNHV1NnlzMCQpXQFGWVALmeMORAuiLx18AvZQ==", "dev": true }, - "@emnapi/core": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", - "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", - "dev": true, - "optional": true, - "requires": { - "@emnapi/wasi-threads": "1.0.2", - "tslib": "^2.4.0" - } - }, - "@emnapi/runtime": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", - "dev": true, - "optional": true, - "requires": { - "tslib": "^2.4.0" - } - }, - "@emnapi/wasi-threads": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", - "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", - "dev": true, - "optional": true, - "requires": { - "tslib": "^2.4.0" - } - }, "@eslint-community/eslint-utils": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", @@ -8199,18 +7851,6 @@ "dev": true, "optional": true }, - "@napi-rs/wasm-runtime": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz", - "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", - "dev": true, - "optional": true, - "requires": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.9.0" - } - }, "@node-rs/crc32": { "version": "1.10.6", "resolved": "https://registry.npmjs.org/@node-rs/crc32/-/crc32-1.10.6.tgz", @@ -8233,20 +7873,6 @@ "@node-rs/crc32-win32-x64-msvc": "1.10.6" } }, - "@node-rs/crc32-android-arm-eabi": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-android-arm-eabi/-/crc32-android-arm-eabi-1.10.6.tgz", - "integrity": "sha512-vZAMuJXm3TpWPOkkhxdrofWDv+Q+I2oO7ucLRbXyAPmXFNDhHtBxbO1rk9Qzz+M3eep8ieS4/+jCL1Q0zacNMQ==", - "dev": true, - "optional": true - }, - "@node-rs/crc32-android-arm64": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-android-arm64/-/crc32-android-arm64-1.10.6.tgz", - "integrity": "sha512-Vl/JbjCinCw/H9gEpZveWCMjxjcEChDcDBM8S4hKay5yyoRCUHJPuKr4sjVDBeOm+1nwU3oOm6Ca8dyblwp4/w==", - "dev": true, - "optional": true - }, "@node-rs/crc32-darwin-arm64": { "version": "1.10.6", "resolved": "https://registry.npmjs.org/@node-rs/crc32-darwin-arm64/-/crc32-darwin-arm64-1.10.6.tgz", @@ -8254,86 +7880,6 @@ "dev": true, "optional": true }, - "@node-rs/crc32-darwin-x64": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-darwin-x64/-/crc32-darwin-x64-1.10.6.tgz", - "integrity": "sha512-Q99bevJVMfLTISpkpKBlXgtPUItrvTWKFyiqoKH5IvscZmLV++NH4V13Pa17GTBmv9n18OwzgQY4/SRq6PQNVA==", - "dev": true, - "optional": true - }, - "@node-rs/crc32-freebsd-x64": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-freebsd-x64/-/crc32-freebsd-x64-1.10.6.tgz", - "integrity": "sha512-66hpawbNjrgnS9EDMErta/lpaqOMrL6a6ee+nlI2viduVOmRZWm9Rg9XdGTK/+c4bQLdtC6jOd+Kp4EyGRYkAg==", - "dev": true, - "optional": true - }, - "@node-rs/crc32-linux-arm-gnueabihf": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm-gnueabihf/-/crc32-linux-arm-gnueabihf-1.10.6.tgz", - "integrity": "sha512-E8Z0WChH7X6ankbVm8J/Yym19Cq3otx6l4NFPS6JW/cWdjv7iw+Sps2huSug+TBprjbcEA+s4TvEwfDI1KScjg==", - "dev": true, - "optional": true - }, - "@node-rs/crc32-linux-arm64-gnu": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm64-gnu/-/crc32-linux-arm64-gnu-1.10.6.tgz", - "integrity": "sha512-LmWcfDbqAvypX0bQjQVPmQGazh4dLiVklkgHxpV4P0TcQ1DT86H/SWpMBMs/ncF8DGuCQ05cNyMv1iddUDugoQ==", - "dev": true, - "optional": true - }, - "@node-rs/crc32-linux-arm64-musl": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm64-musl/-/crc32-linux-arm64-musl-1.10.6.tgz", - "integrity": "sha512-k8ra/bmg0hwRrIEE8JL1p32WfaN9gDlUUpQRWsbxd1WhjqvXea7kKO6K4DwVxyxlPhBS9Gkb5Urq7Y4mXANzaw==", - "dev": true, - "optional": true - }, - "@node-rs/crc32-linux-x64-gnu": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-x64-gnu/-/crc32-linux-x64-gnu-1.10.6.tgz", - "integrity": "sha512-IfjtqcuFK7JrSZ9mlAFhb83xgium30PguvRjIMI45C3FJwu18bnLk1oR619IYb/zetQT82MObgmqfKOtgemEKw==", - "dev": true, - "optional": true - }, - "@node-rs/crc32-linux-x64-musl": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-x64-musl/-/crc32-linux-x64-musl-1.10.6.tgz", - "integrity": "sha512-LbFYsA5M9pNunOweSt6uhxenYQF94v3bHDAQRPTQ3rnjn+mK6IC7YTAYoBjvoJP8lVzcvk9hRj8wp4Jyh6Y80g==", - "dev": true, - "optional": true - }, - "@node-rs/crc32-wasm32-wasi": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-wasm32-wasi/-/crc32-wasm32-wasi-1.10.6.tgz", - "integrity": "sha512-KaejdLgHMPsRaxnM+OG9L9XdWL2TabNx80HLdsCOoX9BVhEkfh39OeahBo8lBmidylKbLGMQoGfIKDjq0YMStw==", - "dev": true, - "optional": true, - "requires": { - "@napi-rs/wasm-runtime": "^0.2.5" - } - }, - "@node-rs/crc32-win32-arm64-msvc": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-arm64-msvc/-/crc32-win32-arm64-msvc-1.10.6.tgz", - "integrity": "sha512-x50AXiSxn5Ccn+dCjLf1T7ZpdBiV1Sp5aC+H2ijhJO4alwznvXgWbopPRVhbp2nj0i+Gb6kkDUEyU+508KAdGQ==", - "dev": true, - "optional": true - }, - "@node-rs/crc32-win32-ia32-msvc": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-ia32-msvc/-/crc32-win32-ia32-msvc-1.10.6.tgz", - "integrity": "sha512-DpDxQLaErJF9l36aghe1Mx+cOnYLKYo6qVPqPL9ukJ5rAGLtCdU0C+Zoi3gs9ySm8zmbFgazq/LvmsZYU42aBw==", - "dev": true, - "optional": true - }, - "@node-rs/crc32-win32-x64-msvc": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-x64-msvc/-/crc32-win32-x64-msvc-1.10.6.tgz", - "integrity": "sha512-5B1vXosIIBw1m2Rcnw62IIfH7W9s9f7H7Ma0rRuhT8HR4Xh8QCgw6NJSI2S2MCngsGktYnAhyUvs81b7efTyQw==", - "dev": true, - "optional": true - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -8585,16 +8131,6 @@ "@textlint/ast-node-types": "15.5.0" } }, - "@tybys/wasm-util": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", - "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", - "dev": true, - "optional": true, - "requires": { - "tslib": "^2.4.0" - } - }, "@types/eslint": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", @@ -8605,16 +8141,6 @@ "@types/json-schema": "*" } }, - "@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "@types/esrecurse": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", @@ -8860,20 +8386,6 @@ "@vscode/vsce-sign-win32-x64": "2.0.2" } }, - "@vscode/vsce-sign-alpine-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.2.tgz", - "integrity": "sha512-E80YvqhtZCLUv3YAf9+tIbbqoinWLCO/B3j03yQPbjT3ZIHCliKZlsy1peNc4XNZ5uIb87Jn0HWx/ZbPXviuAQ==", - "dev": true, - "optional": true - }, - "@vscode/vsce-sign-alpine-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.2.tgz", - "integrity": "sha512-n1WC15MSMvTaeJ5KjWCzo0nzjydwxLyoHiMJHu1Ov0VWTZiddasmOQHekA47tFRycnt4FsQrlkSCTdgHppn6bw==", - "dev": true, - "optional": true - }, "@vscode/vsce-sign-darwin-arm64": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.2.tgz", @@ -8881,48 +8393,6 @@ "dev": true, "optional": true }, - "@vscode/vsce-sign-darwin-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.2.tgz", - "integrity": "sha512-MCjPrQ5MY/QVoZ6n0D92jcRb7eYvxAujG/AH2yM6lI0BspvJQxp0o9s5oiAM9r32r9tkLpiy5s2icsbwefAQIw==", - "dev": true, - "optional": true - }, - "@vscode/vsce-sign-linux-arm": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.2.tgz", - "integrity": "sha512-Fkb5jpbfhZKVw3xwR6t7WYfwKZktVGNXdg1m08uEx1anO0oUPUkoQRsNm4QniL3hmfw0ijg00YA6TrxCRkPVOQ==", - "dev": true, - "optional": true - }, - "@vscode/vsce-sign-linux-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.2.tgz", - "integrity": "sha512-Ybeu7cA6+/koxszsORXX0OJk9N0GgfHq70Wqi4vv2iJCZvBrOWwcIrxKjvFtwyDgdeQzgPheH5nhLVl5eQy7WA==", - "dev": true, - "optional": true - }, - "@vscode/vsce-sign-linux-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.2.tgz", - "integrity": "sha512-NsPPFVtLaTlVJKOiTnO8Cl78LZNWy0Q8iAg+LlBiCDEgC12Gt4WXOSs2pmcIjDYzj2kY4NwdeN1mBTaujYZaPg==", - "dev": true, - "optional": true - }, - "@vscode/vsce-sign-win32-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.2.tgz", - "integrity": "sha512-wPs848ymZ3Ny+Y1Qlyi7mcT6VSigG89FWQnp2qRYCyMhdJxOpA4lDwxzlpL8fG6xC8GjQjGDkwbkWUcCobvksQ==", - "dev": true, - "optional": true - }, - "@vscode/vsce-sign-win32-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.2.tgz", - "integrity": "sha512-pAiRN6qSAhDM5SVOIxgx+2xnoVUePHbRNC7OD2aOR3WltTKxxF25OfpK8h8UQ7A0BuRkSgREbB59DBlFk4iAeg==", - "dev": true, - "optional": true - }, "@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -9459,6 +8929,30 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "copy-webpack-plugin": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-14.0.0.tgz", + "integrity": "sha512-3JLW90aBGeaTLpM7mYQKpnVdgsUZRExY55giiZgLuX/xTQRUs1dOCwbBnWnvY6Q6rfZoXMNwzOQJCSZPppfqXA==", + "dev": true, + "requires": { + "glob-parent": "^6.0.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.2.0", + "serialize-javascript": "^7.0.3", + "tinyglobby": "^0.2.12" + }, + "dependencies": { + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + } + } + }, "cross-keychain": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/cross-keychain/-/cross-keychain-1.1.0.tgz", @@ -10999,6 +10493,12 @@ } } }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -11502,6 +11002,12 @@ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true }, + "serialize-javascript": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.1.1.tgz", + "integrity": "sha512-k3CMsaIvvdSwm8oLB4MXSl0wH2/cwlH7xGcnRd2DaeRmBkbzYmyT8j0tsX60DwD1eRwHTpNpH8ljKu9oUT1MeQ==", + "dev": true + }, "shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -12174,6 +11680,18 @@ "terser-webpack-plugin": "^5.3.17", "watchpack": "^2.5.1", "webpack-sources": "^3.3.4" + }, + "dependencies": { + "@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + } } }, "webpack-cli": { diff --git a/package.json b/package.json index 718d2bf..055ccc5 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "A language server for InterSystems ObjectScript.", "author": "InterSystems Corporation", "license": "SEE LICENSE IN LICENSE.txt", - "version": "2.8.5-SNAPSHOT", + "version": "2.9.0-LOCAL", "publisher": "intersystems", "repository": { "type": "github", @@ -27,7 +27,7 @@ "multi-root ready" ], "engines": { - "vscode": "^1.93.0" + "vscode": "^1.103.0" }, "activationEvents": [ "workspaceContains:**/*.cls", @@ -1797,9 +1797,11 @@ }, "devDependencies": { "@eslint/js": "^10.0.1", + "@types/eslint": "^9.6.1", "@types/node": "^22.15.33", "@types/turndown": "^5.0.6", "@vscode/vsce": "^3.9.2", + "copy-webpack-plugin": "^14.0.0", "eslint": "^10.2.1", "merge-options": "^3.0.4", "node-loader": "^2.1.0", diff --git a/server/package-lock.json b/server/package-lock.json index 0233843..8e2129b 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,13 +1,14 @@ { "name": "language-server-server", - "version": "2.8.4-SNAPSHOT", + "version": "2.9.0-LOCAL", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "language-server-server", - "version": "2.8.4-SNAPSHOT", + "version": "2.9.0-LOCAL", "dependencies": { + "@intersystems-community/ascot": "file:../../objectscript-analyzer/bindings/js/intersystems-community-ascot-0.1.0.tgz", "node-html-parser": "^7.1.0", "turndown": "^7.2.4", "vscode-languageserver": "^9.0.1", @@ -18,6 +19,15 @@ "node": "*" } }, + "node_modules/@intersystems-community/ascot": { + "version": "0.1.0", + "resolved": "file:../../objectscript-analyzer/bindings/js/intersystems-community-ascot-0.1.0.tgz", + "integrity": "sha512-nChA0zlxk/ZWRsvhYD+wQCxcTiItUhhKBg10MVFRKsl5sz6DuTRyMknJvmRpY/wNYkqXDHRaO3bF+Zmi4/0oCg==", + "license": "MIT OR Apache-2.0", + "engines": { + "node": ">=18" + } + }, "node_modules/@mixmark-io/domino": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", @@ -203,6 +213,10 @@ } }, "dependencies": { + "@intersystems-community/ascot": { + "version": "file:../../objectscript-analyzer/bindings/js/intersystems-community-ascot-0.1.0.tgz", + "integrity": "sha512-nChA0zlxk/ZWRsvhYD+wQCxcTiItUhhKBg10MVFRKsl5sz6DuTRyMknJvmRpY/wNYkqXDHRaO3bF+Zmi4/0oCg==" + }, "@mixmark-io/domino": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", diff --git a/server/package.json b/server/package.json index 2dcecf3..d2dd5fd 100644 --- a/server/package.json +++ b/server/package.json @@ -1,12 +1,13 @@ { "name": "language-server-server", - "version": "2.8.5-SNAPSHOT", + "version": "2.9.0-LOCAL", "author": "InterSystems Corporation", "private": true, "engines": { "node": "*" }, "dependencies": { + "@intersystems-community/ascot": "file:../../objectscript-analyzer/bindings/js/intersystems-community-ascot-0.1.0.tgz", "node-html-parser": "^7.1.0", "turndown": "^7.2.4", "vscode-languageserver": "^9.0.1", diff --git a/server/src/ascot/index.ts b/server/src/ascot/index.ts new file mode 100644 index 0000000..32a1fe3 --- /dev/null +++ b/server/src/ascot/index.ts @@ -0,0 +1,406 @@ +import * as Ascot from "@intersystems-community/ascot"; +import { + Diagnostic, + DiagnosticSeverity, + DocumentSymbol, + SymbolInformation, + SymbolKind, + SymbolTag, +} from "vscode-languageserver"; +import { connection } from "../utils/variables"; +import { getServerSpec, makeRESTRequest } from "../utils/functions"; + +const ORIGIN: Ascot.Position = { line: 0, character: 0 }; +const CACHE_TTL_MS = 60 * 60 * 1000; + +interface MemberMetadataRow { + MemberType: "method" | "property" | "parameter"; + Description: string; + FormalSpec: string; + ReturnType: string; + Stub: string; + ClassMethod: "0" | "1" | 0 | 1; + Deprecated: "0" | "1" | 0 | 1; +} + +// Resolves members/superclasses/datatype-ness for out-of-workspace classes via REST; +// in-workspace classes are served from ascot's own memory and never reach here. +class IrisConnection implements Ascot.Imported { + constructor( + private readonly folderURI: string, + private readonly memCache = new Map(), + private readonly superCache = new Map(), + private readonly datatypeCache = new Map(), + private readonly includeCache = new Map(), + ) {} + + // ascot declares this sync; jspi's WebAssembly.Suspending lets this async body await + // a REST call while ascot itself still sees a plain sync return. + public async getMem(cls: string, mem: string): Promise { + const key = `${cls}||${mem}`; + const cached = this.memCache.get(key); + if (cached && Date.now() - cached[0] < CACHE_TTL_MS) return cached[1]; + const server = await getServerSpec(this.folderURI); + if (server === undefined) return undefined; + const nospace = mem.replace(/\s+/g, ""); + // Search all three tables since the kind isn't known up front; columns line up so + // rows read as a uniform MemberMetadataRow regardless of which table matched. + const respdata = await makeRESTRequest("POST", 1, "/action/query", server, { + query: + "SELECT 'method' AS MemberType, Description, FormalSpec, ReturnType, Stub, ClassMethod, Deprecated " + + "FROM %Dictionary.CompiledMethod WHERE Parent = ? AND Name = ? UNION ALL " + + "SELECT 'property' AS MemberType, Description, NULL AS FormalSpec, " + + "CASE WHEN Collection IS NOT NULL THEN Collection||' Of '||Type ELSE Type END AS ReturnType, " + + "NULL AS Stub, 0 AS ClassMethod, Deprecated " + + "FROM %Dictionary.CompiledProperty WHERE Parent = ? AND (Name = ? OR ? %INLIST $LISTFROMSTRING($TRANSLATE(Aliases,' '))) UNION ALL " + + "SELECT 'parameter' AS MemberType, Description, NULL AS FormalSpec, Type AS ReturnType, " + + "NULL AS Stub, 0 AS ClassMethod, Deprecated FROM %Dictionary.CompiledParameter WHERE Parent = ? AND Name = ?", + parameters: [cls, mem, cls, mem, nospace, cls, mem], + }); + const rows: MemberMetadataRow[] | undefined = respdata?.data?.result?.content; + if (!Array.isArray(rows) || rows.length === 0) return undefined; + let row = rows[0]; + if (row.MemberType === "method" && row.Stub) { + // Stub-generated methods (member inheritance) have their real metadata in a + // subtable keyed by the Stub's i/q/a/n segments. + const [origin, subname, kindchar] = row.Stub.split("."); + const table = { i: "Index", q: "Query", a: "Property", n: "Constraint" }[kindchar]; + if (table) { + const stubdata = await makeRESTRequest("POST", 1, "/action/query", server, { + query: + `SELECT 'method' AS MemberType, Description, FormalSpec, ReturnType, '' AS Stub, ClassMethod, Deprecated ` + + `FROM %Dictionary.Compiled${table}Method WHERE Name = ? AND parent->Parent = ? AND parent->Name = ?`, + parameters: [subname, cls, origin], + }); + const stubrows = stubdata?.data?.result?.content; + if (Array.isArray(stubrows) && stubrows.length > 0) row = stubrows[0]; + } + } + const info: Ascot.MemberInfo = { + doc: row.Description ?? "", + before: ORIGIN, + name: { before: ORIGIN, content: mem, after: ORIGIN }, + deprecated: row.Deprecated == "1", + kind: rowToMemberKind(row), + after: ORIGIN, + }; + this.memCache.set(key, [Date.now(), info]); + return info; + + function rowToMemberKind(row: MemberMetadataRow): Ascot.MemberKind { + const type = row.ReturnType || undefined; + switch (row.MemberType) { + case "property": + return { tag: "property", val: type }; + case "parameter": + return { tag: "parameter", val: { t: type } }; + default: { + const { normal, variadic } = parseFormalSpec(row.FormalSpec ?? ""); + const val: Ascot.MethodInfo = { normal, variadic, t: type, body: { start: ORIGIN, end: ORIGIN } }; + return { tag: row.ClassMethod == "1" ? "class-method" : "method", val }; + } + } + } + + // Parse IRIS's minified FormalSpec (e.g. `*out:%String,&ref:%Integer,x...`) into the + // structured args ascot expects. Prefixes: `*` output, `&` by-ref; `:` starts the + // type, `=` the default; a trailing `...` marks the variadic arg. Types and defaults + // may contain commas/parens/quotes, so split respecting quote and paren nesting. + function parseFormalSpec(spec: string): { normal: Ascot.NormalArg[]; variadic?: Ascot.VariadicArg } { + const normal: Ascot.NormalArg[] = []; + let variadic: Ascot.VariadicArg | undefined; + for (const raw of splitTopLevel(spec)) { + let s = raw.trim(); + if (s === "") continue; + let mode: Ascot.ArgMode = "default"; + if (s.startsWith("*")) { + mode = "output"; + s = s.slice(1); + } else if (s.startsWith("&")) { + mode = "by-ref"; + s = s.slice(1); + } + + let name = "", + type = "", + def = ""; + let stage: "name" | "type" | "default" = "name"; + let depth = 0, + inQuote = false; + for (const c of s) { + if (inQuote) { + if (c === '"') inQuote = false; + } else if (c === '"') { + inQuote = true; + } else if (c === "(") { + depth++; + } else if (c === ")") { + depth--; + } else if (depth === 0 && stage === "name" && c === ":") { + stage = "type"; + continue; + } else if (depth === 0 && stage !== "default" && c === "=") { + stage = "default"; + continue; + } + if (stage === "name") name += c; + else if (stage === "type") type += c; + else def += c; + } + + const t = type || undefined; + if (name.endsWith("...")) { + variadic = { mode, name: name.slice(0, -3), t }; + } else { + normal.push({ mode, name, t, default: def || undefined }); + } + } + return { normal, variadic }; + } + + function splitTopLevel(spec: string): string[] { + const out: string[] = []; + let cur = "", + depth = 0, + inQuote = false; + for (const c of spec) { + if (inQuote) { + cur += c; + if (c === '"') inQuote = false; + } else if (c === '"') { + inQuote = true; + cur += c; + } else if (c === "(") { + depth++; + cur += c; + } else if (c === ")") { + depth--; + cur += c; + } else if (c === "," && depth === 0) { + out.push(cur); + cur = ""; + } else { + cur += c; + } + } + if (cur.trim() !== "") out.push(cur); + return out; + } + } + + // Direct superclasses, nearest first. + public async getSupers(cls: string): Promise { + const cached = this.superCache.get(cls); + if (cached && Date.now() - cached[0] < CACHE_TTL_MS) return cached[1]; + const server = await getServerSpec(this.folderURI); + if (server === undefined) return []; + const respdata = await makeRESTRequest("POST", 1, "/action/query", server, { + query: "SELECT Super FROM %Dictionary.CompiledClass WHERE Name = ?", + parameters: [cls], + }); + const rows = respdata?.data?.result?.content; + const supers: string[] = + Array.isArray(rows) && typeof rows[0]?.Super === "string" && rows[0].Super.length + ? rows[0].Super.split(",") + .map((s: string) => s.trim()) + .filter(Boolean) + : []; + this.superCache.set(cls, [Date.now(), supers]); + return supers; + } + + // IRIS's compiled ClassType already resolves both the [ ClassType = datatype ] keyword + // and inheritance from %Library.DataType; undefined means unknown (no server, or not found). + public async isDatatype(cls: string): Promise { + const cached = this.datatypeCache.get(cls); + if (cached && Date.now() - cached[0] < CACHE_TTL_MS) return cached[1]; + const server = await getServerSpec(this.folderURI); + if (server === undefined) return undefined; + const respdata = await makeRESTRequest("POST", 1, "/action/query", server, { + query: "SELECT ClassType FROM %Dictionary.CompiledClass WHERE Name = ?", + parameters: [cls], + }); + const rows = respdata?.data?.result?.content; + const isDatatype = Array.isArray(rows) && rows.length > 0 ? rows[0]?.ClassType === "datatype" : undefined; + this.datatypeCache.set(cls, [Date.now(), isDatatype]); + return isDatatype; + } + + // Only for includes outside the workspace (e.g. %occInclude); in-workspace ones are + // already open in ascot's own document store. + public async getInclude(name: string): Promise { + const cached = this.includeCache.get(name); + if (cached && Date.now() - cached[0] < CACHE_TTL_MS) return cached[1]; + const server = await getServerSpec(this.folderURI); + if (server === undefined) return undefined; + const respdata = await makeRESTRequest("GET", 1, `/doc/${encodeURIComponent(name)}.inc`, server); + const lines: string[] | undefined = respdata?.data?.result?.content; + const content = Array.isArray(lines) ? lines.join("\n") : undefined; + this.includeCache.set(name, [Date.now(), content]); + return content; + } +} + +export type NormalArg = Ascot.NormalArg; +export type MemberInfo = Ascot.MemberInfo; + +/** Prefix marking a hover/completion/symbol result as sourced from ascot rather than a REST query. */ +export const ascot = `[👔] `; + +const workspaces = new Map(); + +const severityMap: Record = { + error: DiagnosticSeverity.Error, + warning: DiagnosticSeverity.Warning, + information: DiagnosticSeverity.Information, + hint: DiagnosticSeverity.Hint, +}; + +const symbolKindMap: Record = { + class: SymbolKind.Class, + module: SymbolKind.Module, + method: SymbolKind.Method, + property: SymbolKind.Property, + interface: SymbolKind.Interface, + function: SymbolKind.Function, + constant: SymbolKind.Constant, + array: SymbolKind.Array, + object: SymbolKind.Object, + key: SymbolKind.Key, + struct: SymbolKind.Struct, + event: SymbolKind.Event, +}; + +// Stores the raw source; no parsing happens here (kind is inferred from `docURI`'s +// extension). Doubles as both open and edit. +export async function openDoc(docURI: string, src: string, folderURI?: string): Promise { + try { + const workspace = + typeof folderURI === "string" ? await rootURIToWorkspace(folderURI) : await filePathToWorkspace(docURI); + await workspace.open(docURI, src); + } catch (rawError) { + console.log(rawError); + } +} + +/** Run `fn` against `docURI`'s workspace, logging and falling back to `empty` on any error. */ +async function withWorkspace( + docURI: string, + empty: T, + fn: (workspace: Ascot.Workspace) => Promise | T, +): Promise { + try { + return await fn(await filePathToWorkspace(docURI)); + } catch (rawError) { + console.log(rawError); + return empty; + } +} + +export const closeDoc = (docURI: string) => withWorkspace(docURI, undefined, (w) => void w.close(docURI)); + +export const getDiagnostics = (docURI: string) => + withWorkspace(docURI, [] as Diagnostic[], async (w) => + (await w.diagnostics(docURI)).map((d) => ({ + message: d.message, + range: d.range, + severity: severityMap[d.severity], + source: "Ascot via InterSystems Language Server", + })), + ); + +export const inlayHint = (docURI: string, range: Ascot.Range) => + withWorkspace(docURI, [] as Ascot.InlayHint[], (w) => w.inlayHint(docURI, range)); + +export const getDefinition = (docURI: string, position: Ascot.Position) => + withWorkspace(docURI, undefined, (w) => w.definition(docURI, position)); + +export const getReferences = (docURI: string, position: Ascot.Position, includeDeclaration: boolean) => + withWorkspace(docURI, [] as Ascot.Location[], (w) => w.references(docURI, position, includeDeclaration)); + +export const getHover = (docURI: string, position: Ascot.Position) => + withWorkspace(docURI, undefined, (w) => w.hover(docURI, position)); + +async function filePathToWorkspace(docURI: string): Promise { + const folders = await connection.workspace.getWorkspaceFolders(); + const folder = folders?.find((f) => docURI.startsWith(f.uri)); + return rootURIToWorkspace(folder?.uri ?? docURI); +} + +async function rootURIToWorkspace(folderURI: string): Promise { + let workspace = workspaces.get(folderURI); + if (!workspace) { + workspace = await Ascot.createWorkspace(new IrisConnection(folderURI)); + workspaces.set(folderURI, workspace); + } + return workspace; +} + +async function findByName( + entries: AsyncGenerator<[string, T]>, + name: string, +): Promise<[string, T] | null> { + for await (const [uri, item] of entries) { + if (item.name.content === name) return [uri, item]; + } + return null; +} + +const getClass = (docURI: string, name: string) => findByName(getClasses(docURI), name); + +export async function* getClasses(docURI: string): AsyncGenerator<[string, Ascot.ClassInfo]> { + const workspace = await filePathToWorkspace(docURI); + const classes = await workspace.queryCls(""); + for (const x of classes) { + yield x; + } +} + +export const getClassMember = (docURI: string, clsName: string, memName: string) => + findByName(getClassMembers(docURI, clsName, memName), memName); + +export async function* getClassMembers( + docURI: string, + clsName: string, + memQuery: string = "", +): AsyncGenerator<[string, Ascot.MemberInfo]> { + const workspace = await filePathToWorkspace(docURI); + for (const x of await workspace.queryMem(clsName, memQuery)) { + yield x; + } + const result = await getClass(docURI, clsName); + if (result) { + const cls = result[1]; + for (const sup of cls.extends) { + yield* getClassMembers(docURI, sup, memQuery); + } + } +} + +export const getDocumentSymbol = (docURI: string) => + withWorkspace(docURI, [] as DocumentSymbol[], async (w) => { + const classSymbol = await w.documentSymbol(docURI); + return classSymbol + ? [{ ...convertSymbolInfo(classSymbol.root), children: classSymbol.members.map(convertSymbolInfo) }] + : []; + + function convertSymbolInfo(info: Ascot.SymbolInfo): DocumentSymbol { + return { + name: info.name, + kind: symbolKindMap[info.kind], + tags: info.deprecated ? [SymbolTag.Deprecated] : [], + range: info.range, + selectionRange: info.selectionRange, + }; + } + }); + +export const getWorkspaceSymbol = (folderURI: string, query: string) => + withWorkspace(folderURI, [] as SymbolInformation[], async (w) => + (await w.workspaceSymbol(query)).map((symbol) => ({ + name: symbol.name, + kind: symbolKindMap[symbol.kind], + tags: symbol.deprecated ? [SymbolTag.Deprecated] : [], + location: symbol.location, + })), + ); diff --git a/server/src/providers/completion.ts b/server/src/providers/completion.ts index beae50a..e1bea7b 100644 --- a/server/src/providers/completion.ts +++ b/server/src/providers/completion.ts @@ -37,6 +37,7 @@ import { LanguageServerConfiguration, } from "../utils/types"; import { documents, corePropertyParams, mppContinue } from "../utils/variables"; +import { ascot, getClassMembers, getClasses, MemberInfo } from "../ascot"; import * as ld from "../utils/languageDefinitions"; import structuredSystemVariables from "../documentation/structuredSystemVariables.json"; @@ -577,6 +578,18 @@ async function completionFullClassName( const imports = await getImports(doc, parsed, line, server); // Get all classes + const added = new Set(); + for await (const [uri, cls] of getClasses(doc.uri)) { + added.add(cls.name.content); + const item = makeFullPrettyClassCompletionItem(imports, cls.name.content, uri, cls.deprecated); + item.documentation = { + kind: MarkupKind.Markdown, + value: documaticHtmlToMarkdown(cls.doc), + }; + item.insertText = item.label; + item.label = ascot + item.label; + result.push(item); + } const querydata = { query: `SELECT dcd.Name, dcd.Deprecated FROM %Library.RoutineMgr_StudioOpenDialog(?,?,?,?,?,?,?) AS sod, %Dictionary.ClassDefinition AS dcd WHERE sod.Name = dcd.Name||'.cls'${ !settings.completion.showDeprecated ? " AND dcd.Deprecated = 0" : "" @@ -586,43 +599,8 @@ async function completionFullClassName( const respdata = await makeRESTRequest("POST", 1, "/action/query", server, querydata); if (respdata !== undefined && respdata.data.result.content.length > 0) { for (const clsobj of respdata.data.result.content) { - let displayname: string = clsobj.Name; - let compItem: CompletionItem; - if (imports.length > 0) { - // Resolve import - let sortText: string | undefined; - for (const imp of imports) { - if (displayname.indexOf(imp) === 0 && displayname.slice(imp.length + 1).indexOf(".") === -1) { - displayname = displayname.slice(imp.length + 1); - sortText = "%%%" + displayname; - break; - } - } - if (displayname.startsWith("%Library.")) { - // Use short form for %Library classes - displayname = "%" + displayname.slice(9); - } - compItem = { - label: displayname, - kind: CompletionItemKind.Class, - data: ["class", clsobj.Name, doc.uri], - sortText, - }; - } else { - if (displayname.startsWith("%Library.")) { - // Use short form for %Library classes - displayname = "%" + displayname.slice(9); - } - compItem = { - label: displayname, - kind: CompletionItemKind.Class, - data: ["class", clsobj.Name, doc.uri], - }; - } - if (clsobj.Deprecated) { - compItem.tags = [CompletionItemTag.Deprecated]; - } - result.push(compItem); + if (added.has(clsobj.Name)) continue; + result.push(makeFullPrettyClassCompletionItem(imports, clsobj.Name, doc.uri, clsobj.Deprecated)); } } return result; @@ -1140,7 +1118,6 @@ export async function onCompletion(params: CompletionParams): Promise(); + for await (const [, cls] of getClasses(doc.uri)) { + if (!cls.name.content.startsWith(filter)) { + continue; + } + added.add(cls.name.content); + result.push({ + label: cls.name.content.slice(filter.length), + kind: CompletionItemKind.Class, + data: ["class", cls.name.content.slice(filter.length), doc.uri], + tags: cls.deprecated ? [CompletionItemTag.Deprecated] : undefined, + documentation: { + kind: MarkupKind.Markdown, + value: documaticHtmlToMarkdown(cls.doc), + }, + }); + } + // Get all classes that match the filter const querydata = { query: `SELECT dcd.Name, dcd.Deprecated FROM %Library.RoutineMgr_StudioOpenDialog(?,?,?,?,?,?,?,?) AS sod, %Dictionary.ClassDefinition AS dcd WHERE sod.Name = dcd.Name||'.cls'${ @@ -1269,6 +1264,7 @@ export async function onCompletion(params: CompletionParams): Promise(); + for await (const [, mem] of getClassMembers(params.textDocument.uri, membercontext.baseclass)) { + if (mem.kind.tag === "parameter") { + const name = quoteUDLIdentifier(mem.name.content, 1); + added.add(name); + const item = makeMemberCompletionItem(mem, name, params.position); + // "#" is already typed, so don't insert it again + item.insertText = name; + result.push(item); + } + } // Query the server to get the names and descriptions of all parameters const data: QueryData = { query: `SELECT Name, Description, Origin, Type, Deprecated FROM %Dictionary.CompiledParameter WHERE Parent = ?${ @@ -1318,6 +1325,7 @@ export async function onCompletion(params: CompletionParams): Promise(); + for await (const [, mem] of getClassMembers(params.textDocument.uri, membercontext.baseclass)) { + const name = quoteUDLIdentifier(mem.name.content, 1); + added.add(name); + result.push(makeMemberCompletionItem(mem, name, params.position)); + } + // Query the server to get the metadata of all appropriate class members const data: QueryData = { query: "", @@ -1420,6 +1435,7 @@ export async function onCompletion(params: CompletionParams): Promise { + if (item.documentation) return item; if (Array.isArray(item.data) && item.data[0] === "class") { // Get the description for this class from the server const server = await getServerSpec(item.data[2]); diff --git a/server/src/providers/definition.ts b/server/src/providers/definition.ts index e108a05..2321a2b 100644 --- a/server/src/providers/definition.ts +++ b/server/src/providers/definition.ts @@ -20,6 +20,7 @@ import { } from "../utils/functions"; import { ServerSpec, QueryData, compressedline } from "../utils/types"; import { documents, corePropertyParams, classMemberTypes, mppContinue } from "../utils/variables"; +import { getDefinition } from "../ascot"; import * as ld from "../utils/languageDefinitions"; /** @@ -228,6 +229,19 @@ export async function onDefinition(params: TextDocumentPositionParams): Promise< return null; } + // ascot's own reference table covers cases the REST-based lookups below don't + // (self-references, same-routine label calls/gotos) — prefer it whenever it has an answer. + const ascotTarget = await getDefinition(params.textDocument.uri, params.position); + if (ascotTarget) { + return [ + { + targetUri: ascotTarget.uri, + targetRange: ascotTarget.range, + targetSelectionRange: ascotTarget.range, + }, + ]; + } + if (parsed[params.position.line] === undefined) { // This is the blank last line of the file return null; diff --git a/server/src/providers/diagnostic.ts b/server/src/providers/diagnostic.ts index 8eec696..058de97 100644 --- a/server/src/providers/diagnostic.ts +++ b/server/src/providers/diagnostic.ts @@ -25,6 +25,7 @@ import { StudioOpenDialogFile, QueryData } from "../utils/types"; import * as ld from "../utils/languageDefinitions"; import parameterTypes from "../documentation/parameterTypes.json"; import sqlReservedWords from "../documentation/sqlReservedWords.json"; +import * as ascot from "../ascot"; /** * Helper method that appends `range` to value of `key` in `map` @@ -62,7 +63,7 @@ export async function onDiagnostics(params: DocumentDiagnosticParams): Promise { diff --git a/server/src/providers/documentSymbol.ts b/server/src/providers/documentSymbol.ts index d7aa6bb..45ef25d 100644 --- a/server/src/providers/documentSymbol.ts +++ b/server/src/providers/documentSymbol.ts @@ -11,6 +11,7 @@ import { findFullRange, getParsedDocument, isClassMember, labelIsProcedureBlock, import { documents, mppContinue } from "../utils/variables"; import * as ld from "../utils/languageDefinitions"; import { compressedline } from "../utils/types"; +import { getDocumentSymbol } from "../ascot"; /** Loop through the class from this line until the next class member or the end of the class */ function processMember( @@ -75,6 +76,13 @@ export async function onDocumentSymbol(params: DocumentSymbolParams) { } const result: DocumentSymbol[] = []; + if (["objectscript-class", "objectscript-macros", "objectscript", "objectscript-int"].includes(doc.languageId)) { + const symbols = await getDocumentSymbol(params.textDocument.uri); + if (symbols.length > 0) { + return symbols; + } + } + if (doc.languageId === "objectscript-class") { // Loop through the file and look for the class definition and class members diff --git a/server/src/providers/hover.ts b/server/src/providers/hover.ts index d0f7dc2..9170bde 100644 --- a/server/src/providers/hover.ts +++ b/server/src/providers/hover.ts @@ -22,6 +22,7 @@ import { } from "../utils/functions"; import { ServerSpec, QueryData, CommandDoc, KeywordDoc } from "../utils/types"; import { documents, corePropertyParams, mppContinue } from "../utils/variables"; +import { getHover } from "../ascot"; import * as ld from "../utils/languageDefinitions"; import commands from "../documentation/commands.json"; @@ -66,6 +67,11 @@ export async function onHover(params: TextDocumentPositionParams): Promise { + return ascot.inlayHint(params.textDocument.uri, params.range); +} diff --git a/server/src/providers/references.ts b/server/src/providers/references.ts new file mode 100644 index 0000000..0953e3b --- /dev/null +++ b/server/src/providers/references.ts @@ -0,0 +1,11 @@ +import { Location, ReferenceParams } from "vscode-languageserver/node"; +import { documents } from "../utils/variables"; +import { getReferences } from "../ascot"; + +export async function onReferences(params: ReferenceParams): Promise { + const doc = documents.get(params.textDocument.uri); + if (doc === undefined) { + return []; + } + return getReferences(params.textDocument.uri, params.position, params.context.includeDeclaration); +} diff --git a/server/src/providers/signatureHelp.ts b/server/src/providers/signatureHelp.ts index ed6156e..5f4a9da 100644 --- a/server/src/providers/signatureHelp.ts +++ b/server/src/providers/signatureHelp.ts @@ -25,6 +25,7 @@ import { import { SignatureHelpDocCache, SignatureHelpMacroContext } from "../utils/types"; import { documents } from "../utils/variables"; import * as ld from "../utils/languageDefinitions"; +import { getClassMember, NormalArg } from "../ascot"; /** * Cache of the macro context info required to do a macro expansion when the selected parameter changes. @@ -365,6 +366,18 @@ export async function onSignatureHelp(params: SignatureHelpParams): Promise { + const uri_mem = + (await getClassMember(docURI, clsName, memName)) ?? + (memName != "%New" ? null : await getClassMember(docURI, clsName, "%OnNew")); + if (!uri_mem) { + return null; + } + const [, mem] = uri_mem; + if (mem.kind.tag === "method" || mem.kind.tag === "class-method" || mem.kind.tag === "client-method") { + const method = mem.kind.val; + const out = ["%Open", "%OpenId"].includes(memName) ? clsName : method.t; + const sig: SignatureInformation = { + label: "(" + method.normal.map(prettifyNormalArg).join(", ") + ")" + (out ? " As " + out : ""), + parameters: method.normal.map( + (arg): ParameterInformation => ({ + label: arg.name, + }), + ), + }; + if (showingDoc) { + signatureHelpDocumentationCache = { + type: "method", + doc: { + kind: MarkupKind.Markdown, + value: documaticHtmlToMarkdown(mem.doc), + }, + }; + sig.documentation = signatureHelpDocumentationCache.doc; + } + return { + signatures: [sig], + activeSignature: 0, + }; + } + return null; + + function prettifyNormalArg(arg: NormalArg): string { + let string = ""; + if (arg.mode != "default") { + string += "&"; + } + string += arg.name; + if (arg.t) { + string += ` As ${arg.t}`; + } + return string; + } +} diff --git a/server/src/providers/workspaceSymbol.ts b/server/src/providers/workspaceSymbol.ts new file mode 100644 index 0000000..19347bd --- /dev/null +++ b/server/src/providers/workspaceSymbol.ts @@ -0,0 +1,11 @@ +import { WorkspaceSymbolParams, SymbolInformation } from "vscode-languageserver"; +import { connection } from "../utils/variables"; +import { getWorkspaceSymbol } from "../ascot"; + +export const onWorkspaceSymbol = async (params: WorkspaceSymbolParams): Promise => { + const output: SymbolInformation[] = []; + for (const folder of (await connection.workspace.getWorkspaceFolders()) ?? []) { + output.push(...(await getWorkspaceSymbol(folder.uri, params.query))); + } + return output; +}; diff --git a/server/src/server.ts b/server/src/server.ts index 9a40d80..99b4d76 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,3 +1,5 @@ +import * as fs from "fs"; +import * as path from "path"; import { DidChangeConfigurationNotification, TextDocumentSyncKind, CodeActionKind } from "vscode-languageserver/node"; import { URI } from "vscode-uri"; @@ -27,7 +29,10 @@ import { onSignatureHelp } from "./providers/signatureHelp"; import { onDocumentFormatting, onDocumentRangeFormatting } from "./providers/formatting"; import { onDiagnostics } from "./providers/diagnostic"; import { onSemanticTokens, onSemanticTokensDelta } from "./providers/semanticTokens"; - +import { onReferences } from "./providers/references"; +import { onWorkspaceSymbol } from "./providers/workspaceSymbol"; +import { onInlayHint } from "./providers/inlayHint"; +import { openDoc, closeDoc } from "./ascot"; import { LanguageServerConfiguration, ServerSpec } from "./utils/types"; import { connection, @@ -40,7 +45,22 @@ import { import { parseDocument, getLegend } from "./parse/parse"; import { isolateEmbeddedLanguage, languageAtPosition } from "./providers/requestForwarding"; -connection.onInitialize(() => { +connection.onInitialize((params) => { + (async () => { + for (const folder of params.workspaceFolders ?? []) { + const folderURI = URI.parse(folder.uri); + if (folderURI.scheme !== "file") continue; + for (const file of fs.readdirSync(folderURI.fsPath, { recursive: true, withFileTypes: true })) { + if (!(file.isFile() && /\.(cls|mac|int|inc)$/i.test(file.name))) { + continue; + } + const filePath = path.join(file.parentPath, file.name); + const fileURI = URI.file(filePath).toString(); + const fileString = fs.readFileSync(filePath, "utf-8"); + await openDoc(fileURI, fileString, folder.uri); + } + } + })(); return { capabilities: { textDocumentSync: TextDocumentSyncKind.Full, @@ -50,6 +70,7 @@ connection.onInitialize(() => { }, hoverProvider: true, definitionProvider: true, + referencesProvider: true, signatureHelpProvider: { triggerCharacters: ["(", ","], retriggerCharacters: [","], @@ -63,6 +84,7 @@ connection.onInitialize(() => { }, }, documentSymbolProvider: true, + workspaceSymbolProvider: true, foldingRangeProvider: true, renameProvider: { prepareProvider: true, @@ -81,6 +103,7 @@ connection.onInitialize(() => { interFileDependencies: false, workspaceDiagnostics: false, }, + inlayHintProvider: true, }, }; }); @@ -116,12 +139,15 @@ connection.onDidChangeConfiguration(async () => { connection.languages.diagnostics.refresh(); }); -documents.onDidClose((e) => { +documents.onDidClose(async (e) => { parsedDocuments.delete(e.document.uri); tokenBuilders.delete(e.document.uri); serverSpecs.delete(e.document.uri); languageServerSettings.delete(e.document.uri); - connection.sendDiagnostics({ uri: e.document.uri, diagnostics: [] }); + await closeDoc(e.document.uri); + // Pull-model diagnostics: ask the client to re-pull so the closed + // document's diagnostics are recomputed (and dropped from the workspace report). + connection.languages.diagnostics.refresh(); }); // The content of a text document has changed. This event is emitted @@ -130,14 +156,13 @@ documents.onDidChangeContent(async (change) => { // Clear the parsedDocuments value so we know to wait for an update elsewhere parsedDocuments.set(change.document.uri, undefined); const path = URI.parse(change.document.uri).path; + const fileText = change.document.getText(); parsedDocuments.set( change.document.uri, - parseDocument( - change.document.languageId, - path.slice(path.lastIndexOf(".") + 1).toLowerCase(), - change.document.getText(), - ).compressedlinearray, + parseDocument(change.document.languageId, path.slice(path.lastIndexOf(".") + 1).toLowerCase(), fileText) + .compressedlinearray, ); + await openDoc(change.document.uri, fileText); }); connection.onDocumentFormatting(onDocumentFormatting); @@ -154,6 +179,8 @@ connection.onHover(onHover); connection.onDefinition(onDefinition); +connection.onReferences(onReferences); + connection.languages.semanticTokens.on(onSemanticTokens); connection.languages.semanticTokens.onDelta(onSemanticTokensDelta); @@ -188,6 +215,8 @@ connection.onNotification("intersystems/server/connectionChange", () => { connection.onDocumentSymbol(onDocumentSymbol); +connection.onWorkspaceSymbol(onWorkspaceSymbol); + connection.onFoldingRanges(onFoldingRanges); connection.onPrepareRename(onPrepareRename); @@ -234,6 +263,8 @@ connection.onRequest("intersystems/embedded/isolateEmbeddedLanguage", isolateEmb connection.languages.diagnostics.on(onDiagnostics); +connection.languages.inlayHint.on(onInlayHint); + documents.listen(connection); connection.listen(); diff --git a/server/webpack.config.js b/server/webpack.config.js index a9d96d6..3b3af3e 100644 --- a/server/webpack.config.js +++ b/server/webpack.config.js @@ -4,6 +4,7 @@ const withDefaults = require('../shared.webpack.config'); const path = require('path'); +const CopyPlugin = require('copy-webpack-plugin'); module.exports = withDefaults({ context: path.join(__dirname), @@ -13,5 +14,22 @@ module.exports = withDefaults({ output: { filename: 'server.js', path: path.join(__dirname, 'out') - } + }, + plugins: [ + // @intersystems-community/ascot's own JS gets bundled into out/ alongside ours + // (node.__dirname is left un-faked -- see shared.webpack.config.js), so its + // `__dirname`-relative "../lib" wasm lookup resolves to server/lib/, a sibling of + // out/, not to node_modules/@intersystems-community/ascot/lib/ where the files + // actually ship. Mirror them here so that lookup keeps finding them -- as part of + // the build itself, so there's no separate install-time step to forget or skip. + new CopyPlugin({ + patterns: [ + { + context: path.join(__dirname, 'node_modules/@intersystems-community/ascot/lib'), + from: '*.core*.wasm', + to: path.join(__dirname, 'lib'), + }, + ], + }), + ], });