From 71e9f2cb0815cf6fc0c47bc45625c3ece7853a1e Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Wed, 11 Jan 2023 06:02:10 +0300 Subject: [PATCH 1/6] feat: Now we ship support for Volar (.vue SFC files) out of the box! For the first time, it will configure `volar.vueserver.configFilePath` setting, to disable this support use `"tsEssentialPlugins.enableVueSupport": true` setting. This also makes plugin work in takeover mode! feat: rework `replaceSuggestions` feature. Main property now support `*` to match word with any length (0 included, transforms to `.*` regex), also more configuration values to filter & patch were added and add config fixes fix: a lot of fixes were rules of replaceSuggestions were applied incorrectly. Skip processing completions that were already processed by previous rules. Clone each completion deeply to ensure patching applies doesnt mutate others. --- README.MD | 10 + buildTsPlugin.mjs | 16 +- package.json | 4 +- pnpm-lock.yaml | 486 +++++++++++++++--- src/configurationType.ts | 45 +- src/extension.ts | 2 + src/vueVolarSupport.ts | 26 + .../completions/objectLiteralCompletions.ts | 5 +- typescript/src/completionsAtPosition.ts | 88 +++- typescript/src/decorateProxy.ts | 119 +++++ typescript/src/index.ts | 136 +---- typescript/src/libMethods.ts | 5 + typescript/src/semanticDiagnostics.ts | 2 +- typescript/src/specialCommands/handle.ts | 2 +- typescript/src/volarConfig.ts | 68 +++ typescript/test/completions.spec.ts | 11 +- 16 files changed, 799 insertions(+), 226 deletions(-) create mode 100644 src/vueVolarSupport.ts create mode 100644 typescript/src/decorateProxy.ts create mode 100644 typescript/src/libMethods.ts create mode 100644 typescript/src/volarConfig.ts diff --git a/README.MD b/README.MD index bb02d03e..ca6d12f0 100644 --- a/README.MD +++ b/README.MD @@ -88,6 +88,16 @@ Removes import statements from references when symbol has usages in the same fil You can quickly disable this plugin functionality by setting this setting to false. Useful for debugging a problem for example. +> Note: this setting doesn't disable Vue support. + +### Vue Support + +`.vue` SFC files support is enabled out of the box when [Vue Language Features (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) is installed. + +For the first time, it will configure `volar.vueserver.configFilePath` setting, to disable Vue support use `"tsEssentialPlugins.enableVueSupport": true` setting. + +This also makes plugin work in Volar's takeover mode! + ### Web Support > Note: when you open TS/JS file in the web for the first time you currently need to switch editors to make everything work! diff --git a/buildTsPlugin.mjs b/buildTsPlugin.mjs index f16f02b3..4989d4b1 100644 --- a/buildTsPlugin.mjs +++ b/buildTsPlugin.mjs @@ -1,6 +1,20 @@ //@ts-check import buildTsPlugin from '@zardoy/vscode-utils/build/buildTypescriptPlugin.js' -import { analyzeMetafile } from 'esbuild' +import { build, analyzeMetafile } from 'esbuild' + +build({ + // bundle: true, + // minify: !watch, + entryPoints: ['./typescript/src/volarConfig.ts'], + outfile: './out/volarConfig.js', + format: 'cjs', + logLevel: 'info', + platform: 'node', + // banner: { + // js: 'let ts, tsFull;', + // }, + // treeShaking: true, +}) const result = await buildTsPlugin('typescript', undefined, undefined, { minify: !process.argv.includes('--watch'), diff --git a/package.json b/package.json index e9904ba5..74364fd4 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "@types/semver": "^7.3.13", "@types/vscode": "^1.63.1", "@zardoy/tsconfig": "^1.3.1", - "esbuild": "^0.15.15", + "esbuild": "^0.16.16", "fs-extra": "^10.1.0", "got": "^12.5.3", "type-fest": "^2.13.1", @@ -118,6 +118,8 @@ "@types/lodash": "^4.14.182", "@types/mocha": "^9.1.1", "@types/pluralize": "^0.0.29", + "@volar/language-server": "^1.0.24", + "@volar/language-service": "^1.0.24", "@vscode/emmet-helper": "^2.8.4", "@vscode/test-electron": "^2.1.5", "@zardoy/utils": "^0.0.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b942dd19..aae0e586 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,8 @@ importers: '@types/pluralize': ^0.0.29 '@types/semver': ^7.3.13 '@types/vscode': ^1.63.1 + '@volar/language-server': ^1.0.24 + '@volar/language-service': ^1.0.24 '@vscode/emmet-helper': ^2.8.4 '@vscode/test-electron': ^2.1.5 '@zardoy/tsconfig': ^1.3.1 @@ -26,7 +28,7 @@ importers: chokidar: ^3.5.3 chokidar-cli: ^3.0.0 delay: ^5.0.0 - esbuild: ^0.15.15 + esbuild: ^0.16.16 escape-string-regexp: ^5.0.0 eslint: ^8.7.0 eslint-config-zardoy: ^0.2.12 @@ -60,10 +62,12 @@ importers: '@types/lodash': 4.14.182 '@types/mocha': 9.1.1 '@types/pluralize': 0.0.29 + '@volar/language-server': 1.0.24 + '@volar/language-service': 1.0.24 '@vscode/emmet-helper': 2.8.4 '@vscode/test-electron': 2.1.5 '@zardoy/utils': 0.0.9 - '@zardoy/vscode-utils': 0.0.47_wuodti7e77enk5whyk5rob4yre + '@zardoy/vscode-utils': 0.0.47_m6uty6iwlw6f6kdb72kgot4taq chai: 4.3.6 chokidar: 3.5.3 chokidar-cli: 3.0.0 @@ -95,7 +99,7 @@ importers: '@types/semver': 7.3.13 '@types/vscode': 1.63.1 '@zardoy/tsconfig': 1.3.1_typescript@4.9.3 - esbuild: 0.15.15 + esbuild: 0.16.16 fs-extra: 10.1.0 got: 12.5.3 type-fest: 2.13.1 @@ -373,22 +377,198 @@ packages: resolution: {integrity: sha512-8HqW8EVqjnCmWXVpqAOZf+EGESdkR27odcMMMGefgKXtar00SoYNSryGv//TELI4T3QFsECo78p+0lmalk/CFA==} dev: false - /@esbuild/android-arm/0.15.15: - resolution: {integrity: sha512-JJjZjJi2eBL01QJuWjfCdZxcIgot+VoK6Fq7eKF9w4YHm9hwl7nhBR1o2Wnt/WcANk5l9SkpvrldW1PLuXxcbw==} + /@esbuild/android-arm/0.15.18: + resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} engines: {node: '>=12'} cpu: [arm] os: [android] requiresBuild: true optional: true - /@esbuild/linux-loong64/0.15.15: - resolution: {integrity: sha512-lhz6UNPMDXUhtXSulw8XlFAtSYO26WmHQnCi2Lg2p+/TMiJKNLtZCYUxV4wG6rZMzXmr8InGpNwk+DLT2Hm0PA==} + /@esbuild/android-arm/0.16.16: + resolution: {integrity: sha512-BUuWMlt4WSXod1HSl7aGK8fJOsi+Tab/M0IDK1V1/GstzoOpqc/v3DqmN8MkuapPKQ9Br1WtLAN4uEgWR8x64A==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-arm64/0.16.16: + resolution: {integrity: sha512-hFHVAzUKp9Tf8psGq+bDVv+6hTy1bAOoV/jJMUWwhUnIHsh6WbFMhw0ZTkqDuh7TdpffFoHOiIOIxmHc7oYRBQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-x64/0.16.16: + resolution: {integrity: sha512-9WhxJpeb6XumlfivldxqmkJepEcELekmSw3NkGrs+Edq6sS5KRxtUBQuKYDD7KqP59dDkxVbaoPIQFKWQG0KLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/darwin-arm64/0.16.16: + resolution: {integrity: sha512-8Z+wld+vr/prHPi2O0X7o1zQOfMbXWGAw9hT0jEyU/l/Yrg+0Z3FO9pjPho72dVkZs4ewZk0bDOFLdZHm8jEfw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/darwin-x64/0.16.16: + resolution: {integrity: sha512-CYkxVvkZzGCqFrt7EgjFxQKhlUPyDkuR9P0Y5wEcmJqVI8ncerOIY5Kej52MhZyzOBXkYrJgZeVZC9xXXoEg9A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/freebsd-arm64/0.16.16: + resolution: {integrity: sha512-fxrw4BYqQ39z/3Ja9xj/a1gMsVq0xEjhSyI4a9MjfvDDD8fUV8IYliac96i7tzZc3+VytyXX+XNsnpEk5sw5Wg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/freebsd-x64/0.16.16: + resolution: {integrity: sha512-8p3v1D+du2jiDvSoNVimHhj7leSfST9YlKsAEO7etBfuqjaBMndo0fmjNLp0JCMld+XIx9L80tooOkyUv1a1PQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/linux-arm/0.16.16: + resolution: {integrity: sha512-bYaocE1/PTMRmkgSckZ0D0Xn2nox8v2qlk+MVVqm+VECNKDdZvghVZtH41dNtBbwADSvA6qkCHGYeWm9LrNCBw==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-arm64/0.16.16: + resolution: {integrity: sha512-N3u6BBbCVY3xeP2D8Db7QY8I+nZ+2AgOopUIqk+5yCoLnsWkcVxD2ay5E9iIdvApFi1Vg1lZiiwaVp8bOpAc4A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ia32/0.16.16: + resolution: {integrity: sha512-dxjqLKUW8GqGemoRT9v8IgHk+T4tRm1rn1gUcArsp26W9EkK/27VSjBVUXhEG5NInHZ92JaQ3SSMdTwv/r9a2A==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-loong64/0.15.18: + resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} engines: {node: '>=12'} cpu: [loong64] os: [linux] requiresBuild: true optional: true + /@esbuild/linux-loong64/0.16.16: + resolution: {integrity: sha512-MdUFggHjRiCCwNE9+1AibewoNq6wf94GLB9Q9aXwl+a75UlRmbRK3h6WJyrSGA6ZstDJgaD2wiTSP7tQNUYxwA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-mips64el/0.16.16: + resolution: {integrity: sha512-CO3YmO7jYMlGqGoeFeKzdwx/bx8Vtq/SZaMAi+ZLDUnDUdfC7GmGwXzIwDJ70Sg+P9pAemjJyJ1icKJ9R3q/Fg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ppc64/0.16.16: + resolution: {integrity: sha512-DSl5Czh5hCy/7azX0Wl9IdzPHX2H8clC6G87tBnZnzUpNgRxPFhfmArbaHoAysu4JfqCqbB/33u/GL9dUgCBAw==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-riscv64/0.16.16: + resolution: {integrity: sha512-sSVVMEXsqf1fQu0j7kkhXMViroixU5XoaJXl1u/u+jbXvvhhCt9YvA/B6VM3aM/77HuRQ94neS5bcisijGnKFQ==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-s390x/0.16.16: + resolution: {integrity: sha512-jRqBCre9gZGoCdCN/UWCCMwCMsOg65IpY9Pyj56mKCF5zXy9d60kkNRdDN6YXGjr3rzcC4DXnS/kQVCGcC4yPQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-x64/0.16.16: + resolution: {integrity: sha512-G1+09TopOzo59/55lk5Q0UokghYLyHTKKzD5lXsAOOlGDbieGEFJpJBr3BLDbf7cz89KX04sBeExAR/pL/26sA==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/netbsd-x64/0.16.16: + resolution: {integrity: sha512-xwjGJB5wwDEujLaJIrSMRqWkbigALpBNcsF9SqszoNKc+wY4kPTdKrSxiY5ik3IatojePP+WV108MvF6q6np4w==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + /@esbuild/openbsd-x64/0.16.16: + resolution: {integrity: sha512-yeERkoxG2nR2oxO5n+Ms7MsCeNk23zrby2GXCqnfCpPp7KNc0vxaaacIxb21wPMfXXRhGBrNP4YLIupUBrWdlg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + optional: true + + /@esbuild/sunos-x64/0.16.16: + resolution: {integrity: sha512-nHfbEym0IObXPhtX6Va3H5GaKBty2kdhlAhKmyCj9u255ktAj0b1YACUs9j5H88NRn9cJCthD1Ik/k9wn8YKVg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + optional: true + + /@esbuild/win32-arm64/0.16.16: + resolution: {integrity: sha512-pdD+M1ZOFy4hE15ZyPX09fd5g4DqbbL1wXGY90YmleVS6Y5YlraW4BvHjim/X/4yuCpTsAFvsT4Nca2lbyDH/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + /@esbuild/win32-ia32/0.16.16: + resolution: {integrity: sha512-IPEMfU9p0c3Vb8PqxaPX6BM9rYwlTZGYOf9u+kMdhoILZkVKEjq6PKZO0lB+isojWwAnAqh4ZxshD96njTXajg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + /@esbuild/win32-x64/0.16.16: + resolution: {integrity: sha512-1YYpoJ39WV/2bnShPwgdzJklc+XS0bysN6Tpnt1cWPdeoKOG4RMEY1g7i534QxXX/rPvNx/NLJQTTCeORYzipg==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + /@eslint/eslintrc/1.0.5: resolution: {integrity: sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -818,6 +998,61 @@ packages: resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} dev: false + /@volar/language-core/1.0.24: + resolution: {integrity: sha512-vTN+alJiWwK0Pax6POqrmevbtFW2dXhjwWiW/MW4f48eDYPLdyURWcr8TixO7EN/nHsUBj2udT7igFKPtjyAKg==} + dependencies: + '@volar/source-map': 1.0.24 + muggle-string: 0.1.0 + dev: false + + /@volar/language-server/1.0.24: + resolution: {integrity: sha512-F5T8ZYXGSSfzCtx8Yv02iRs0N4i1ddhFynTA6nS0axADDISklcwW5LTt9A4pO45/6yujyGj84+Kmxhtwa0+X6g==} + dependencies: + '@volar/language-core': 1.0.24 + '@volar/language-service': 1.0.24 + '@volar/shared': 1.0.24 + request-light: 0.6.0 + typesafe-path: 0.2.2 + vscode-html-languageservice: 5.0.3 + vscode-languageserver: 8.0.2 + vscode-languageserver-protocol: 3.17.2 + vscode-languageserver-textdocument: 1.0.8 + vscode-uri: 3.0.7 + dev: false + + /@volar/language-service/1.0.24: + resolution: {integrity: sha512-Y37lzNRVM2xDY1kFXn88n9nkXUD1H0ZffXXLbsFbkUhMM1pKBgcJGEuRXoATXu62R0NmrcGXrktjTPQ4VjKQuA==} + dependencies: + '@volar/language-core': 1.0.24 + '@volar/shared': 1.0.24 + '@volar/source-map': 1.0.24 + '@volar/typescript-faster': 1.0.24 + vscode-html-languageservice: 5.0.3 + vscode-json-languageservice: 5.1.3 + vscode-languageserver-protocol: 3.17.2 + vscode-languageserver-textdocument: 1.0.8 + vscode-uri: 3.0.7 + dev: false + + /@volar/shared/1.0.24: + resolution: {integrity: sha512-30mqmNsw49xlGhziL59z6kP6/TlBatkeOzMImUSWmn1QtqV7r2onDGgNNdCqSa1esTo4UtGup6yqqM2oUwrMSQ==} + dependencies: + typesafe-path: 0.2.2 + vscode-uri: 3.0.7 + dev: false + + /@volar/source-map/1.0.24: + resolution: {integrity: sha512-Qsv/tkplx18pgBr8lKAbM1vcDqgkGKQzbChg6NW+v0CZc3G7FLmK+WrqEPzKlN7Cwdc6XVL559Nod8WKAfKr4A==} + dependencies: + muggle-string: 0.1.0 + dev: false + + /@volar/typescript-faster/1.0.24: + resolution: {integrity: sha512-8JtPkR3p2EVpBrD5puuP4y4CA7LVIkMV/+O2a/biD5zHyfqwN+s5j1/perp0D/5RgyxLJWhWIIYo1HR5ac5jlA==} + dependencies: + semver: 7.3.8 + dev: false + /@vscode/emmet-helper/2.8.4: resolution: {integrity: sha512-lUki5QLS47bz/U8IlG9VQ+1lfxMtxMZENmU5nu4Z71eOD5j9FK0SmYGL5NiVJg9WBWeAU0VxRADMY2Qpq7BfVg==} dependencies: @@ -829,6 +1064,10 @@ packages: vscode-uri: 2.1.2 dev: false + /@vscode/l10n/0.0.10: + resolution: {integrity: sha512-E1OCmDcDWa0Ya7vtSjp/XfHFGqYJfh+YPC1RkATU71fTac+j1JjCcB3qwSzmlKAighx2WxhLlfhS0RwAN++PFQ==} + dev: false + /@vscode/test-electron/2.1.5: resolution: {integrity: sha512-O/ioqFpV+RvKbRykX2ItYPnbcZ4Hk5V0rY4uhQjQTLhGL9WZUvS7exzuYQCCI+ilSqJpctvxq2llTfGXf9UnnA==} engines: {node: '>=8.9.3'} @@ -895,7 +1134,7 @@ packages: type-fest: 2.19.0 dev: false - /@zardoy/vscode-utils/0.0.47_wuodti7e77enk5whyk5rob4yre: + /@zardoy/vscode-utils/0.0.47_m6uty6iwlw6f6kdb72kgot4taq: resolution: {integrity: sha512-0xsdTonXFxcBdsHcWgkSfJSpP9VOvOiT6oo/LuA5FOGJJI/5W6e6EDwN6Y9FahRWdrYmOfliekEMGZGk/eEWcQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true @@ -919,7 +1158,7 @@ packages: '@zardoy/utils': 0.0.4 chokidar: 3.5.3 commander: 9.4.1 - esbuild: 0.15.15 + esbuild: 0.16.16 execa: 5.1.1 fs-extra: 10.1.0 lodash.throttle: 4.1.1 @@ -1876,194 +2115,223 @@ packages: is-symbol: 1.0.4 dev: false - /esbuild-android-64/0.15.15: - resolution: {integrity: sha512-F+WjjQxO+JQOva3tJWNdVjouFMLK6R6i5gjDvgUthLYJnIZJsp1HlF523k73hELY20WPyEO8xcz7aaYBVkeg5Q==} + /esbuild-android-64/0.15.18: + resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} engines: {node: '>=12'} cpu: [x64] os: [android] requiresBuild: true optional: true - /esbuild-android-arm64/0.15.15: - resolution: {integrity: sha512-attlyhD6Y22jNyQ0fIIQ7mnPvDWKw7k6FKnsXlBvQE6s3z6s6cuEHcSgoirquQc7TmZgVCK5fD/2uxmRN+ZpcQ==} + /esbuild-android-arm64/0.15.18: + resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} engines: {node: '>=12'} cpu: [arm64] os: [android] requiresBuild: true optional: true - /esbuild-darwin-64/0.15.15: - resolution: {integrity: sha512-ohZtF8W1SHJ4JWldsPVdk8st0r9ExbAOSrBOh5L+Mq47i696GVwv1ab/KlmbUoikSTNoXEhDzVpxUR/WIO19FQ==} + /esbuild-darwin-64/0.15.18: + resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} engines: {node: '>=12'} cpu: [x64] os: [darwin] requiresBuild: true optional: true - /esbuild-darwin-arm64/0.15.15: - resolution: {integrity: sha512-P8jOZ5zshCNIuGn+9KehKs/cq5uIniC+BeCykvdVhx/rBXSxmtj3CUIKZz4sDCuESMbitK54drf/2QX9QHG5Ag==} + /esbuild-darwin-arm64/0.15.18: + resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] requiresBuild: true optional: true - /esbuild-freebsd-64/0.15.15: - resolution: {integrity: sha512-KkTg+AmDXz1IvA9S1gt8dE24C8Thx0X5oM0KGF322DuP+P3evwTL9YyusHAWNsh4qLsR80nvBr/EIYs29VSwuA==} + /esbuild-freebsd-64/0.15.18: + resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] requiresBuild: true optional: true - /esbuild-freebsd-arm64/0.15.15: - resolution: {integrity: sha512-FUcML0DRsuyqCMfAC+HoeAqvWxMeq0qXvclZZ/lt2kLU6XBnDA5uKTLUd379WYEyVD4KKFctqWd9tTuk8C/96g==} + /esbuild-freebsd-arm64/0.15.18: + resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] requiresBuild: true optional: true - /esbuild-linux-32/0.15.15: - resolution: {integrity: sha512-q28Qn5pZgHNqug02aTkzw5sW9OklSo96b5nm17Mq0pDXrdTBcQ+M6Q9A1B+dalFeynunwh/pvfrNucjzwDXj+Q==} + /esbuild-linux-32/0.15.18: + resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] requiresBuild: true optional: true - /esbuild-linux-64/0.15.15: - resolution: {integrity: sha512-217KPmWMirkf8liO+fj2qrPwbIbhNTGNVtvqI1TnOWJgcMjUWvd677Gq3fTzXEjilkx2yWypVnTswM2KbXgoAg==} + /esbuild-linux-64/0.15.18: + resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} engines: {node: '>=12'} cpu: [x64] os: [linux] requiresBuild: true optional: true - /esbuild-linux-arm/0.15.15: - resolution: {integrity: sha512-RYVW9o2yN8yM7SB1yaWr378CwrjvGCyGybX3SdzPHpikUHkME2AP55Ma20uNwkNyY2eSYFX9D55kDrfQmQBR4w==} + /esbuild-linux-arm/0.15.18: + resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} engines: {node: '>=12'} cpu: [arm] os: [linux] requiresBuild: true optional: true - /esbuild-linux-arm64/0.15.15: - resolution: {integrity: sha512-/ltmNFs0FivZkYsTzAsXIfLQX38lFnwJTWCJts0IbCqWZQe+jjj0vYBNbI0kmXLb3y5NljiM5USVAO1NVkdh2g==} + /esbuild-linux-arm64/0.15.18: + resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} engines: {node: '>=12'} cpu: [arm64] os: [linux] requiresBuild: true optional: true - /esbuild-linux-mips64le/0.15.15: - resolution: {integrity: sha512-PksEPb321/28GFFxtvL33yVPfnMZihxkEv5zME2zapXGp7fA1X2jYeiTUK+9tJ/EGgcNWuwvtawPxJG7Mmn86A==} + /esbuild-linux-mips64le/0.15.18: + resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] requiresBuild: true optional: true - /esbuild-linux-ppc64le/0.15.15: - resolution: {integrity: sha512-ek8gJBEIhcpGI327eAZigBOHl58QqrJrYYIZBWQCnH3UnXoeWMrMZLeeZL8BI2XMBhP+sQ6ERctD5X+ajL/AIA==} + /esbuild-linux-ppc64le/0.15.18: + resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] requiresBuild: true optional: true - /esbuild-linux-riscv64/0.15.15: - resolution: {integrity: sha512-H5ilTZb33/GnUBrZMNJtBk7/OXzDHDXjIzoLXHSutwwsLxSNaLxzAaMoDGDd/keZoS+GDBqNVxdCkpuiRW4OSw==} + /esbuild-linux-riscv64/0.15.18: + resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] requiresBuild: true optional: true - /esbuild-linux-s390x/0.15.15: - resolution: {integrity: sha512-jKaLUg78mua3rrtrkpv4Or2dNTJU7bgHN4bEjT4OX4GR7nLBSA9dfJezQouTxMmIW7opwEC5/iR9mpC18utnxQ==} + /esbuild-linux-s390x/0.15.18: + resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} engines: {node: '>=12'} cpu: [s390x] os: [linux] requiresBuild: true optional: true - /esbuild-netbsd-64/0.15.15: - resolution: {integrity: sha512-aOvmF/UkjFuW6F36HbIlImJTTx45KUCHJndtKo+KdP8Dhq3mgLRKW9+6Ircpm8bX/RcS3zZMMmaBLkvGY06Gvw==} + /esbuild-netbsd-64/0.15.18: + resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] requiresBuild: true optional: true - /esbuild-openbsd-64/0.15.15: - resolution: {integrity: sha512-HFFX+WYedx1w2yJ1VyR1Dfo8zyYGQZf1cA69bLdrHzu9svj6KH6ZLK0k3A1/LFPhcEY9idSOhsB2UyU0tHPxgQ==} + /esbuild-openbsd-64/0.15.18: + resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] requiresBuild: true optional: true - /esbuild-sunos-64/0.15.15: - resolution: {integrity: sha512-jOPBudffG4HN8yJXcK9rib/ZTFoTA5pvIKbRrt3IKAGMq1EpBi4xoVoSRrq/0d4OgZLaQbmkHp8RO9eZIn5atA==} + /esbuild-sunos-64/0.15.18: + resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} engines: {node: '>=12'} cpu: [x64] os: [sunos] requiresBuild: true optional: true - /esbuild-windows-32/0.15.15: - resolution: {integrity: sha512-MDkJ3QkjnCetKF0fKxCyYNBnOq6dmidcwstBVeMtXSgGYTy8XSwBeIE4+HuKiSsG6I/mXEb++px3IGSmTN0XiA==} + /esbuild-windows-32/0.15.18: + resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} engines: {node: '>=12'} cpu: [ia32] os: [win32] requiresBuild: true optional: true - /esbuild-windows-64/0.15.15: - resolution: {integrity: sha512-xaAUIB2qllE888SsMU3j9nrqyLbkqqkpQyWVkfwSil6BBPgcPk3zOFitTTncEKCLTQy3XV9RuH7PDj3aJDljWA==} + /esbuild-windows-64/0.15.18: + resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} engines: {node: '>=12'} cpu: [x64] os: [win32] requiresBuild: true optional: true - /esbuild-windows-arm64/0.15.15: - resolution: {integrity: sha512-ttuoCYCIJAFx4UUKKWYnFdrVpoXa3+3WWkXVI6s09U+YjhnyM5h96ewTq/WgQj9LFSIlABQvadHSOQyAVjW5xQ==} + /esbuild-windows-arm64/0.15.18: + resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} engines: {node: '>=12'} cpu: [arm64] os: [win32] requiresBuild: true optional: true - /esbuild/0.15.15: - resolution: {integrity: sha512-TEw/lwK4Zzld9x3FedV6jy8onOUHqcEX3ADFk4k+gzPUwrxn8nWV62tH0udo8jOtjFodlEfc4ypsqX3e+WWO6w==} + /esbuild/0.15.18: + resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.15.18 + '@esbuild/linux-loong64': 0.15.18 + esbuild-android-64: 0.15.18 + esbuild-android-arm64: 0.15.18 + esbuild-darwin-64: 0.15.18 + esbuild-darwin-arm64: 0.15.18 + esbuild-freebsd-64: 0.15.18 + esbuild-freebsd-arm64: 0.15.18 + esbuild-linux-32: 0.15.18 + esbuild-linux-64: 0.15.18 + esbuild-linux-arm: 0.15.18 + esbuild-linux-arm64: 0.15.18 + esbuild-linux-mips64le: 0.15.18 + esbuild-linux-ppc64le: 0.15.18 + esbuild-linux-riscv64: 0.15.18 + esbuild-linux-s390x: 0.15.18 + esbuild-netbsd-64: 0.15.18 + esbuild-openbsd-64: 0.15.18 + esbuild-sunos-64: 0.15.18 + esbuild-windows-32: 0.15.18 + esbuild-windows-64: 0.15.18 + esbuild-windows-arm64: 0.15.18 + + /esbuild/0.16.16: + resolution: {integrity: sha512-24JyKq10KXM5EBIgPotYIJ2fInNWVVqflv3gicIyQqfmUqi4HvDW1VR790cBgLJHCl96Syy7lhoz7tLFcmuRmg==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.15.15 - '@esbuild/linux-loong64': 0.15.15 - esbuild-android-64: 0.15.15 - esbuild-android-arm64: 0.15.15 - esbuild-darwin-64: 0.15.15 - esbuild-darwin-arm64: 0.15.15 - esbuild-freebsd-64: 0.15.15 - esbuild-freebsd-arm64: 0.15.15 - esbuild-linux-32: 0.15.15 - esbuild-linux-64: 0.15.15 - esbuild-linux-arm: 0.15.15 - esbuild-linux-arm64: 0.15.15 - esbuild-linux-mips64le: 0.15.15 - esbuild-linux-ppc64le: 0.15.15 - esbuild-linux-riscv64: 0.15.15 - esbuild-linux-s390x: 0.15.15 - esbuild-netbsd-64: 0.15.15 - esbuild-openbsd-64: 0.15.15 - esbuild-sunos-64: 0.15.15 - esbuild-windows-32: 0.15.15 - esbuild-windows-64: 0.15.15 - esbuild-windows-arm64: 0.15.15 + '@esbuild/android-arm': 0.16.16 + '@esbuild/android-arm64': 0.16.16 + '@esbuild/android-x64': 0.16.16 + '@esbuild/darwin-arm64': 0.16.16 + '@esbuild/darwin-x64': 0.16.16 + '@esbuild/freebsd-arm64': 0.16.16 + '@esbuild/freebsd-x64': 0.16.16 + '@esbuild/linux-arm': 0.16.16 + '@esbuild/linux-arm64': 0.16.16 + '@esbuild/linux-ia32': 0.16.16 + '@esbuild/linux-loong64': 0.16.16 + '@esbuild/linux-mips64el': 0.16.16 + '@esbuild/linux-ppc64': 0.16.16 + '@esbuild/linux-riscv64': 0.16.16 + '@esbuild/linux-s390x': 0.16.16 + '@esbuild/linux-x64': 0.16.16 + '@esbuild/netbsd-x64': 0.16.16 + '@esbuild/openbsd-x64': 0.16.16 + '@esbuild/sunos-x64': 0.16.16 + '@esbuild/win32-arm64': 0.16.16 + '@esbuild/win32-ia32': 0.16.16 + '@esbuild/win32-x64': 0.16.16 /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -3365,12 +3633,16 @@ packages: /jsonc-parser/3.0.0: resolution: {integrity: sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==} + /jsonc-parser/3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: false + /jsonfile/6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} dependencies: universalify: 2.0.0 optionalDependencies: - graceful-fs: 4.2.10 + graceful-fs: 4.2.9 /jsonify/0.0.0: resolution: {integrity: sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=} @@ -3785,6 +4057,10 @@ packages: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: false + /muggle-string/0.1.0: + resolution: {integrity: sha512-Tr1knR3d2mKvvWthlk7202rywKbiOm4rVFLsfAaSIhJ6dt9o47W4S+JMtWhd/PW9Wrdew2/S2fSvhz3E2gkfEg==} + dev: false + /multimap/1.1.0: resolution: {integrity: sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==} dev: false @@ -4370,6 +4646,10 @@ packages: engines: {node: '>=8'} dev: false + /request-light/0.6.0: + resolution: {integrity: sha512-D3TyWnzX4Kej7ZomWbD+ZqnmzKw/otLHU4tsuhsnF3CoIBo9y0JsxkQXGAqBC4FH/y1hm/ry0/hrsVaKMCkljA==} + dev: false + /require-directory/2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -5031,6 +5311,10 @@ packages: resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=} dev: false + /typesafe-path/0.2.2: + resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==} + dev: false + /typescript-json-schema/0.51.0: resolution: {integrity: sha512-POhWbUNs2oaBti1W9k/JwS+uDsaZD9J/KQiZ/iXRQEOD0lTn9VmshIls9tn+A9X6O+smPjeEz5NEy6WTkCCzrQ==} hasBin: true @@ -5195,7 +5479,7 @@ packages: optional: true dependencies: '@types/node': 16.18.3 - esbuild: 0.15.15 + esbuild: 0.15.18 postcss: 8.4.19 resolve: 1.22.1 rollup: 2.79.1 @@ -5279,7 +5563,7 @@ packages: commander: 8.3.0 cosmiconfig: 7.0.1 del: 6.0.0 - esbuild: 0.15.15 + esbuild: 0.15.18 escape-string-regexp: 4.0.0 execa: 5.1.1 exit-hook: 2.2.1 @@ -5309,14 +5593,60 @@ packages: - utf-8-validate dev: false + /vscode-html-languageservice/5.0.3: + resolution: {integrity: sha512-6rfrtcHhXDMXmC5pR2WXrx02HiNCzQDynOBMn+53zLxr2hvZrDzoc0QgC0FaFGfcglf7GeOsfhkWvJBFC/a70g==} + dependencies: + '@vscode/l10n': 0.0.10 + vscode-languageserver-textdocument: 1.0.8 + vscode-languageserver-types: 3.17.2 + vscode-uri: 3.0.7 + dev: false + + /vscode-json-languageservice/5.1.3: + resolution: {integrity: sha512-p0O1Ql5+zyWFIBU4cSxnDcuq9OnbE0MmvNKDYYvz4EPsZ9EHBT3I6KJb5Gk3snkj+jQTFILEZ06cfY7WZxxqPw==} + dependencies: + '@vscode/l10n': 0.0.10 + jsonc-parser: 3.2.0 + vscode-languageserver-textdocument: 1.0.8 + vscode-languageserver-types: 3.17.2 + vscode-uri: 3.0.7 + dev: false + + /vscode-jsonrpc/8.0.2: + resolution: {integrity: sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==} + engines: {node: '>=14.0.0'} + dev: false + + /vscode-languageserver-protocol/3.17.2: + resolution: {integrity: sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==} + dependencies: + vscode-jsonrpc: 8.0.2 + vscode-languageserver-types: 3.17.2 + dev: false + /vscode-languageserver-textdocument/1.0.4: resolution: {integrity: sha512-/xhqXP/2A2RSs+J8JNXpiiNVvvNM0oTosNVmQnunlKvq9o4mupHOBAnnzH0lwIPKazXKvAKsVp1kr+H/K4lgoQ==} dev: false + /vscode-languageserver-textdocument/1.0.8: + resolution: {integrity: sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==} + dev: false + /vscode-languageserver-types/3.16.0: resolution: {integrity: sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==} dev: false + /vscode-languageserver-types/3.17.2: + resolution: {integrity: sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==} + dev: false + + /vscode-languageserver/8.0.2: + resolution: {integrity: sha512-bpEt2ggPxKzsAOZlXmCJ50bV7VrxwCS5BI4+egUmure/oI/t4OlFzi/YNtVvY24A2UDOZAgwFGgnZPwqSJubkA==} + hasBin: true + dependencies: + vscode-languageserver-protocol: 3.17.2 + dev: false + /vscode-manifest/0.0.4: resolution: {integrity: sha512-DqeCLPd+rXIH3LQGICI6ZjW6aiNwQP7Kf1T+OUOa+G0288WizpEf9EYoQs0RSbq+b/LH0MlNmIrdM8Ea3bUsLA==} dependencies: @@ -5345,6 +5675,10 @@ packages: resolution: {integrity: sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ==} dev: false + /vscode-uri/3.0.7: + resolution: {integrity: sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==} + dev: false + /vue-eslint-parser/8.3.0_eslint@8.7.0: resolution: {integrity: sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} diff --git a/src/configurationType.ts b/src/configurationType.ts index 337333e1..b8895bc6 100644 --- a/src/configurationType.ts +++ b/src/configurationType.ts @@ -1,14 +1,20 @@ -import { ScriptElementKind } from 'typescript/lib/tsserverlibrary' +import { ScriptElementKind, ScriptKind } from 'typescript/lib/tsserverlibrary' type ReplaceRule = { - /** e.g. `readFile`, `^readFile` (global) or `fs.readFile` */ + /** + * Name of completion + * e.g. `readFile`, `^readFile` (global) or `fs.readFile` + */ suggestion: string filter?: { - // package?: string - // TODO - kind?: keyof typeof ScriptElementKind + kind?: keyof Record + /** doesn't support globs and not generally recommended */ + sourceDisplay?: boolean + fileNamePattern?: string + languageMode?: keyof typeof ScriptKind } - // action + /** by default only one entry is being proccessed */ + processMany?: boolean delete?: boolean duplicateOriginal?: boolean | 'above' patch?: Partial<{ @@ -16,9 +22,14 @@ type ReplaceRule = { kind: keyof typeof ScriptElementKind /** Might be useless when `correntSorting.enable` is true */ sortText: string - /** Generally not recommended */ - // kindModifiers: string - insertText: string + insertText: string | true + /** Wether insertText differs from completion name */ + snippetLike: boolean + labelDetails: { + /** on the right */ + detail?: string + description?: string + } }> /** Works only with `correntSorting.enable` set to true (default) */ // movePos?: number @@ -36,9 +47,25 @@ type ReplaceRule = { export type Configuration = { /** * Controls wether TypeScript Essentials plugin is enabled or not. + * Does not affect Vue support enablement * @default true */ enablePlugin: boolean + /** + * Wether to enable support in Vue SFC files via Volar config file. + * Changing setting requires volar server restart + * Experimental. + * @default true + */ + enableVueSupport: boolean + /** + * @default true + */ + vueSpecificImprovements: boolean + /** + * Temporary setting to enable loading config from other locations (also to expose plugin) + */ + // volarLoadConfigPaths: string[] /** * Removes `Symbol`, `caller`, `prototype` everywhere * @default true diff --git a/src/extension.ts b/src/extension.ts index 3311a1ce..afcff6f2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -13,6 +13,7 @@ import figIntegration from './figIntegration' import apiCommands from './apiCommands' import onCompletionAccepted from './onCompletionAccepted' import specialCommands from './specialCommands' +import vueVolarSupport from './vueVolarSupport' export const activateTsPlugin = (tsApi: { configurePlugin; onCompletionAccepted }) => { let webWaitingForConfigSync = false @@ -70,6 +71,7 @@ export const activateTsPlugin = (tsApi: { configurePlugin; onCompletionAccepted specialCommands() figIntegration() + vueVolarSupport() } export const activate = async () => { diff --git a/src/vueVolarSupport.ts b/src/vueVolarSupport.ts new file mode 100644 index 00000000..294c0cbc --- /dev/null +++ b/src/vueVolarSupport.ts @@ -0,0 +1,26 @@ +import * as vscode from 'vscode' +import { watchExtensionSettings } from '@zardoy/vscode-utils/build/settings' +import { extensionCtx, getExtensionSetting } from 'vscode-framework' + +export default () => { + const handler = () => { + const config = vscode.workspace.getConfiguration('') + if ( + !getExtensionSetting('enableVueSupport') || + !vscode.extensions.getExtension('Vue.volar') || + isConfigValueChanged('volar.vueserver.configFilePath') + ) { + return + } + + void config.update('volar.vueserver.configFilePath', extensionCtx.asAbsolutePath('./volarConfig.js'), vscode.ConfigurationTarget.Global) + } + + handler() + watchExtensionSettings(['enableVueSupport'], handler) +} + +const isConfigValueChanged = (id: string) => { + const config = vscode.workspace.getConfiguration('') + return config.get(id) !== config.inspect(id)!.defaultValue +} diff --git a/typescript/src/completions/objectLiteralCompletions.ts b/typescript/src/completions/objectLiteralCompletions.ts index 6b13d97f..ca52f7db 100644 --- a/typescript/src/completions/objectLiteralCompletions.ts +++ b/typescript/src/completions/objectLiteralCompletions.ts @@ -99,14 +99,15 @@ const isArrayCompletion = (type: ts.Type, checker: ts.TypeChecker) => { return false } -const isObjectCompletion = (type: ts.Type) => { +const isObjectCompletion = (type: ts.Type, checker: ts.TypeChecker) => { if (type.flags & ts.TypeFlags.Undefined) return true + if (checker['isArrayLikeType'](type)) return false if (type.flags & ts.TypeFlags.Object) { if ((type as ts.ObjectType).objectFlags & ts.ObjectFlags.Class) return false // complete with regexp? if (type.symbol?.escapedName === 'RegExp') return false return true } - if (type.isUnion()) return type.types.every(type => isObjectCompletion(type)) + if (type.isUnion()) return type.types.every(type => isObjectCompletion(type, checker)) return false } diff --git a/typescript/src/completionsAtPosition.ts b/typescript/src/completionsAtPosition.ts index 16935e74..2f3e397e 100644 --- a/typescript/src/completionsAtPosition.ts +++ b/typescript/src/completionsAtPosition.ts @@ -22,6 +22,7 @@ import filterJsxElements from './completions/filterJsxComponents' import markOrRemoveGlobalCompletions from './completions/markOrRemoveGlobalLibCompletions' import { oneOf } from '@zardoy/utils' import filterWIthIgnoreAutoImports from './completions/ignoreAutoImports' +import escapeStringRegexp from 'escape-string-regexp' export type PrevCompletionMap = Record @@ -32,7 +33,8 @@ export const getCompletionsAtPosition = ( c: GetConfig, languageService: ts.LanguageService, scriptSnapshot: ts.IScriptSnapshot, - formatOptions?: ts.FormatCodeSettings, + formatOptions: ts.FormatCodeSettings | undefined, + additionalData: { scriptKind: ts.ScriptKind }, ): | { completions: ts.CompletionInfo @@ -199,24 +201,84 @@ export const getCompletionsAtPosition = ( prior.entries = arrayMethods(prior.entries, position, sourceFile, c) ?? prior.entries prior.entries = jsdocDefault(prior.entries, position, sourceFile, languageService) ?? prior.entries + if ((fileName.endsWith('.vue.ts') || fileName.endsWith('.vue.js')) && c('vueSpecificImprovements') && exactNode) { + let node = ts.isIdentifier(exactNode) ? exactNode.parent : exactNode + if (ts.isPropertyAssignment(node)) node = node.parent + if ( + ts.isObjectLiteralExpression(node) && + ts.isCallExpression(node.parent) && + ts.isIdentifier(node.parent.expression) && + node.parent.expression.text === 'defineComponent' + ) { + prior.entries = prior.entries.filter(({ name, kind }) => kind === ts.ScriptElementKind.warning || !name.startsWith('__')) + } + } + if (c('improveJsxCompletions') && leftNode) prior.entries = improveJsxCompletions(prior.entries, leftNode, position, sourceFile, c('jsxCompletionsMap')) + const processedEntryIdxs: number[] = [] for (const rule of c('replaceSuggestions')) { - let foundIndex!: number - const suggestion = prior.entries.find(({ name, kind }, index) => { - if (rule.suggestion !== name) return false - if (rule.filter?.kind && kind !== rule.filter.kind) return false - foundIndex = index - return true - }) - if (!suggestion) continue + if (rule.filter?.fileNamePattern) { + // todo replace with something better + const fileRegex = tsFull.getRegexFromPattern(tsFull.getPatternFromSpec(rule.filter.fileNamePattern, program.getCurrentDirectory(), 'files')!, false) + if (fileRegex && !fileRegex.test(fileName)) continue + } + if (rule.filter?.languageMode && ts.ScriptKind[rule.filter.languageMode] !== additionalData.scriptKind) continue + let nameComparator: (n: string) => boolean + if (rule.suggestion.includes('*')) { + const regex = new RegExp(`^${escapeStringRegexp(rule.suggestion).replaceAll('\\*', '.*')}$`) + nameComparator = n => regex.test(n) + } else { + nameComparator = n => n === rule.suggestion + } - if (rule.delete) prior.entries.splice(foundIndex, 1) + const entryIndexesToRemove: number[] = [] + const processEntryWithRule = (entryIndex: number) => { + if (rule.delete) { + entryIndexesToRemove.push(entryIndex) + return + } - if (rule.duplicateOriginal) prior.entries.splice(rule.duplicateOriginal === 'above' ? foundIndex : foundIndex + 1, 0, { ...suggestion }) + // todo-low (perf debt) clone probably should be used this + const entry = prior!.entries[entryIndex]! + if (rule.duplicateOriginal) { + processedEntryIdxs.push(entryIndex + 1) + prior!.entries.splice(rule.duplicateOriginal === 'above' ? entryIndex : entryIndex + 1, 0, { ...entry }) + } - Object.assign(suggestion, rule.patch ?? {}) - if (rule.patch?.insertText) suggestion.isSnippet = true + const { patch } = rule + if (patch) { + const { labelDetails, ...justPatch } = patch + if (labelDetails) { + entry.labelDetails ??= {} + Object.assign(entry.labelDetails, labelDetails) + } + Object.assign(entry, justPatch) + } + if (patch?.insertText === true) { + entry.insertText = entry.name + } + if (rule.patch?.insertText) entry.isSnippet = true + processedEntryIdxs.push(entryIndex) + prior!.entries.splice(entryIndex, 1, entry) + } + + entry: for (const [i, entry] of prior!.entries.entries()) { + if (processedEntryIdxs.includes(i)) continue + const { name } = entry + if (!nameComparator(name)) continue + const { fileNamePattern, languageMode, ...simpleEntryFilters } = rule.filter ?? {} + for (const [filterKey, filterValue] of Object.entries(simpleEntryFilters)) { + if (entry[filterKey] !== filterValue) continue entry + } + processEntryWithRule(i) + if (!rule.processMany) break + } + + let iStep = 0 + for (const i of entryIndexesToRemove) { + prior.entries.splice(i - iStep++, 1) + } } // prevent vscode-builtin wrong insertText with methods snippets enabled diff --git a/typescript/src/decorateProxy.ts b/typescript/src/decorateProxy.ts new file mode 100644 index 00000000..6a90e05e --- /dev/null +++ b/typescript/src/decorateProxy.ts @@ -0,0 +1,119 @@ +import { getCompletionsAtPosition, PrevCompletionMap } from './completionsAtPosition' +import { TriggerCharacterCommand } from './ipcTypes' +import { getNavTreeItems } from './getPatchedNavTree' +import decorateCodeActions from './codeActions/decorateProxy' +import decorateSemanticDiagnostics from './semanticDiagnostics' +import decorateCodeFixes from './codeFixes' +import decorateReferences from './references' +import handleSpecialCommand from './specialCommands/handle' +import decorateDefinitions from './definitions' +import decorateDocumentHighlights from './documentHighlights' +import completionEntryDetails from './completionEntryDetails' +import { GetConfig } from './types' +import lodashGet from 'lodash.get' + +/** @internal */ +export const thisPluginMarker = '__essentialPluginsMarker__' + +export const getInitialProxy = (languageService: ts.LanguageService, proxy = Object.create(null)): ts.LanguageService => { + for (const k of Object.keys(languageService)) { + const x = languageService[k]! + // @ts-expect-error - JS runtime trickery which is tricky to type tersely + proxy[k] = (...args: Array>) => x.apply(languageService, args) + } + return proxy +} + +export const decorateLanguageService = ( + info: ts.server.PluginCreateInfo, + existingProxy: ts.LanguageService | undefined, + config: { config: any }, + { pluginSpecificSyntaxServerConfigCheck = true }: { pluginSpecificSyntaxServerConfigCheck?: boolean } = {}, +) => { + const c: GetConfig = key => lodashGet(config.config, key) + const { languageService, languageServiceHost } = info + + // Set up decorator object + const proxy = getInitialProxy(languageService, existingProxy) + + let prevCompletionsMap: PrevCompletionMap + // eslint-disable-next-line complexity + proxy.getCompletionsAtPosition = (fileName, position, options, formatOptions) => { + const updateConfigCommand = 'updateConfig' + if (options?.triggerCharacter?.startsWith(updateConfigCommand)) { + config.config = JSON.parse(options.triggerCharacter.slice(updateConfigCommand.length)) + return { entries: [] } + } + const specialCommandResult = options?.triggerCharacter + ? handleSpecialCommand( + info, + fileName, + position, + options.triggerCharacter as TriggerCharacterCommand, + languageService, + config.config, + options, + formatOptions, + ) + : undefined + // handled specialCommand request + if (specialCommandResult !== undefined) return specialCommandResult as any + prevCompletionsMap = {} + const scriptSnapshot = languageServiceHost.getScriptSnapshot(fileName) + const scriptKind = languageServiceHost.getScriptKind!(fileName) + // have no idea in which cases its possible, but we can't work without it + if (!scriptSnapshot) return + const result = getCompletionsAtPosition(fileName, position, options, c, languageService, scriptSnapshot, formatOptions, { scriptKind }) + if (!result) return + prevCompletionsMap = result.prevCompletionsMap + return result.completions + } + + proxy.getCompletionEntryDetails = (fileName, position, entryName, formatOptions, source, preferences, data) => { + const program = languageService.getProgram() + const sourceFile = program?.getSourceFile(fileName) + if (!program || !sourceFile) return + const { documentationOverride } = prevCompletionsMap[entryName] ?? {} + if (documentationOverride) { + return { + name: entryName, + kind: ts.ScriptElementKind.alias, + kindModifiers: '', + displayParts: typeof documentationOverride === 'string' ? [{ kind: 'text', text: documentationOverride }] : documentationOverride, + } + } + const prior = languageService.getCompletionEntryDetails( + fileName, + position, + prevCompletionsMap[entryName]?.originalName || entryName, + formatOptions, + source, + preferences, + data, + ) + if (!prior) return + return completionEntryDetails(languageService, c, fileName, position, sourceFile, prior) + } + + decorateCodeActions(proxy, languageService, c) + decorateCodeFixes(proxy, languageService, c, languageServiceHost) + decorateSemanticDiagnostics(proxy, info, c) + decorateDefinitions(proxy, info, c) + decorateReferences(proxy, languageService, c) + decorateDocumentHighlights(proxy, languageService, c) + + if (pluginSpecificSyntaxServerConfigCheck) { + if (!__WEB__) { + // dedicated syntax server (which is enabled by default), which fires navtree doesn't seem to receive onConfigurationChanged + // so we forced to communicate via fs + const config = JSON.parse(ts.sys.readFile(require('path').join(__dirname, '../../plugin-config.json'), 'utf8') ?? '{}') + proxy.getNavigationTree = fileName => { + if (c('patchOutline') || config.patchOutline) return getNavTreeItems(info, fileName) + return languageService.getNavigationTree(fileName) + } + } + } + + languageService[thisPluginMarker] = true + return proxy +} diff --git a/typescript/src/index.ts b/typescript/src/index.ts index 6dd44ff5..add035dc 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -1,119 +1,10 @@ -import get from 'lodash.get' - // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-ignore import type { Configuration } from '../../src/configurationType' -import _ from 'lodash' -import { GetConfig } from './types' -import { getCompletionsAtPosition, PrevCompletionMap } from './completionsAtPosition' -import { TriggerCharacterCommand } from './ipcTypes' -import { getNavTreeItems } from './getPatchedNavTree' -import decorateCodeActions from './codeActions/decorateProxy' -import decorateSemanticDiagnostics from './semanticDiagnostics' -import decorateCodeFixes from './codeFixes' -import decorateReferences from './references' -import handleSpecialCommand from './specialCommands/handle' -import decorateDefinitions from './definitions' -import decorateDocumentHighlights from './documentHighlights' -import completionEntryDetails from './completionEntryDetails' - -const thisPluginMarker = '__essentialPluginsMarker__' - -let _configuration: Configuration -const c: GetConfig = key => get(_configuration, key) - -const getInitialProxy = (languageService: ts.LanguageService, proxy = Object.create(null)): ts.LanguageService => { - for (const k of Object.keys(languageService)) { - const x = languageService[k]! - // @ts-expect-error - JS runtime trickery which is tricky to type tersely - proxy[k] = (...args: Array>) => x.apply(languageService, args) - } - return proxy -} - -const decorateLanguageService = (info: ts.server.PluginCreateInfo, existingProxy?: ts.LanguageService) => { - // Set up decorator object - const proxy = getInitialProxy(info.languageService, existingProxy) - - const { languageService } = info - - let prevCompletionsMap: PrevCompletionMap - // eslint-disable-next-line complexity - proxy.getCompletionsAtPosition = (fileName, position, options, formatOptions) => { - const updateConfigCommand = 'updateConfig' - if (options?.triggerCharacter?.startsWith(updateConfigCommand)) { - _configuration = JSON.parse(options.triggerCharacter.slice(updateConfigCommand.length)) - return { entries: [] } - } - const specialCommandResult = options?.triggerCharacter - ? handleSpecialCommand( - info, - fileName, - position, - options.triggerCharacter as TriggerCharacterCommand, - languageService, - _configuration, - options, - formatOptions, - ) - : undefined - // handled specialCommand request - if (specialCommandResult !== undefined) return specialCommandResult as any - prevCompletionsMap = {} - const scriptSnapshot = info.project.getScriptSnapshot(fileName) - // have no idea in which cases its possible, but we can't work without it - if (!scriptSnapshot) return - const result = getCompletionsAtPosition(fileName, position, options, c, info.languageService, scriptSnapshot, formatOptions) - if (!result) return - prevCompletionsMap = result.prevCompletionsMap - return result.completions - } - - proxy.getCompletionEntryDetails = (fileName, position, entryName, formatOptions, source, preferences, data) => { - const program = languageService.getProgram() - const sourceFile = program?.getSourceFile(fileName) - if (!program || !sourceFile) return - const { documentationOverride } = prevCompletionsMap[entryName] ?? {} - if (documentationOverride) { - return { - name: entryName, - kind: ts.ScriptElementKind.alias, - kindModifiers: '', - displayParts: typeof documentationOverride === 'string' ? [{ kind: 'text', text: documentationOverride }] : documentationOverride, - } - } - const prior = languageService.getCompletionEntryDetails( - fileName, - position, - prevCompletionsMap[entryName]?.originalName || entryName, - formatOptions, - source, - preferences, - data, - ) - if (!prior) return - return completionEntryDetails(languageService, c, fileName, position, sourceFile, prior) - } - - decorateCodeActions(proxy, info.languageService, c) - decorateCodeFixes(proxy, info.languageService, c, info.languageServiceHost) - decorateSemanticDiagnostics(proxy, info, c) - decorateDefinitions(proxy, info, c) - decorateReferences(proxy, info.languageService, c) - decorateDocumentHighlights(proxy, info.languageService, c) - - if (!__WEB__) { - // dedicated syntax server (which is enabled by default), which fires navtree doesn't seem to receive onConfigurationChanged - // so we forced to communicate via fs - const config = JSON.parse(ts.sys.readFile(require('path').join(__dirname, '../../plugin-config.json'), 'utf8') ?? '{}') - proxy.getNavigationTree = fileName => { - if (c('patchOutline') || config.patchOutline) return getNavTreeItems(info, fileName) - return info.languageService.getNavigationTree(fileName) - } - } +import { decorateLanguageService, getInitialProxy, thisPluginMarker } from './decorateProxy' - info.languageService[thisPluginMarker] = true - return proxy +let _configObj = { + config: undefined! as Configuration, } const updateConfigListeners: Array<() => void> = [] @@ -123,25 +14,28 @@ const plugin: ts.server.PluginModuleFactory = ({ typescript }) => { return { create(info) { // receive fresh config - _configuration = info.config - console.log('receive config', JSON.stringify(_configuration)) + _configObj.config = info.config + console.log('receive config', JSON.stringify(_configObj.config)) if (info.languageService[thisPluginMarker]) return info.languageService - const proxy = _configuration.enablePlugin === false ? getInitialProxy(info.languageService) : decorateLanguageService(info, undefined) + const proxy = + _configObj.config.enablePlugin === false + ? getInitialProxy(info.languageService) + : decorateLanguageService(info, undefined, _configObj, _configObj.config?.['_additionalPluginOptions']) // #region watch enablePlugin setting - let prevPluginEnabledSetting = _configuration.enablePlugin + let prevPluginEnabledSetting = _configObj.config.enablePlugin updateConfigListeners.push(() => { - if ((prevPluginEnabledSetting === true || prevPluginEnabledSetting === undefined) && !_configuration.enablePlugin) { + if ((prevPluginEnabledSetting === true || prevPluginEnabledSetting === undefined) && !_configObj.config.enablePlugin) { // plugin got disabled, restore original languageService methods // todo resetting doesn't work after tsconfig changes getInitialProxy(info.languageService, proxy) - } else if (prevPluginEnabledSetting === false && _configuration.enablePlugin) { + } else if (prevPluginEnabledSetting === false && _configObj.config.enablePlugin) { // plugin got enabled - decorateLanguageService(info, proxy) + decorateLanguageService(info, proxy, _configObj, _configObj.config?.['_additionalPluginOptions']) } - prevPluginEnabledSetting = _configuration.enablePlugin + prevPluginEnabledSetting = _configObj.config.enablePlugin }) // #endregion @@ -149,7 +43,7 @@ const plugin: ts.server.PluginModuleFactory = ({ typescript }) => { }, onConfigurationChanged(config) { console.log('update config', JSON.stringify(config)) - _configuration = config + _configObj.config = config for (const updateConfigListener of updateConfigListeners) { updateConfigListener() } diff --git a/typescript/src/libMethods.ts b/typescript/src/libMethods.ts new file mode 100644 index 00000000..291dbcdd --- /dev/null +++ b/typescript/src/libMethods.ts @@ -0,0 +1,5 @@ +// exposed ts essentials plugins lib methods for external usage from npm + +export const initTypeScriptEssentialsPlugins = (typescript: typeof ts) => { + ts = tsFull = typescript as any +} diff --git a/typescript/src/semanticDiagnostics.ts b/typescript/src/semanticDiagnostics.ts index f2a9e9be..6917beab 100644 --- a/typescript/src/semanticDiagnostics.ts +++ b/typescript/src/semanticDiagnostics.ts @@ -5,7 +5,7 @@ export default (proxy: ts.LanguageService, info: ts.server.PluginCreateInfo, c: proxy.getSemanticDiagnostics = fileName => { let prior = info.languageService.getSemanticDiagnostics(fileName) if (c('supportTsDiagnosticDisableComment')) { - const scriptSnapshot = info.project.getScriptSnapshot(fileName)! + const scriptSnapshot = info.languageServiceHost.getScriptSnapshot(fileName)! const firstLine = scriptSnapshot.getText(0, scriptSnapshot.getLength()).split(/\r?\n/)[0]! if (firstLine.startsWith('//')) { const match = firstLine.match(/@ts-diagnostic-disable ((\d+, )*(\d+))/) diff --git a/typescript/src/specialCommands/handle.ts b/typescript/src/specialCommands/handle.ts index 6310dbd1..2899a5fe 100644 --- a/typescript/src/specialCommands/handle.ts +++ b/typescript/src/specialCommands/handle.ts @@ -66,7 +66,7 @@ export default ( } } if (specialCommand === 'getPostfixes') { - const scriptSnapshot = info.project.getScriptSnapshot(fileName) + const scriptSnapshot = info.languageServiceHost.getScriptSnapshot(fileName) if (!scriptSnapshot) return return { entries: [], diff --git a/typescript/src/volarConfig.ts b/typescript/src/volarConfig.ts new file mode 100644 index 00000000..7b979f76 --- /dev/null +++ b/typescript/src/volarConfig.ts @@ -0,0 +1,68 @@ +// will be required from ./node_modules/typescript-essential-plugins/index.js +const originalPluginFactory = require('typescript-essential-plugins') + +const plugin = (context => { + const typescript = context.typescript + const { configurationHost } = context.env + const patchConfig = config => { + return { + ...config, + _additionalPluginOptions: { + pluginSpecificSyntaxServerConfigCheck: false, + }, + enablePlugin: config.enableVueSupport, + } + } + + if (typescript && configurationHost) { + const plugin = originalPluginFactory({ + typescript: typescript.module, + }) + // todo support vue-specific settings + const originalLsMethods = { ...typescript.languageService } + + configurationHost.getConfiguration('tsEssentialPlugins').then(_configuration => { + // if (typescript.languageService[thisPluginMarker]) return + const config = patchConfig(_configuration) + if (!config.enablePlugin) return + const proxy = plugin.create({ + ...typescript, + config: config, + languageService: originalLsMethods as any, + } as any) + console.log('TS Essentials Plugins activated!') + // const methodToReassign = ['getCompletionsAtPosition', 'getCompletionEntryDetails'] + for (const method of Object.keys(proxy)) { + typescript.languageService[method] = proxy[method] as any + } + }) + + configurationHost.onDidChangeConfiguration(() => { + configurationHost.getConfiguration('tsEssentialPlugins').then(config => { + config = patchConfig(config) + plugin.onConfigurationChanged?.(config) + // temporary workaround + if (!config.enablePlugin) { + typescript.languageService = originalLsMethods + } + }) + }) + // typescript.languageService[thisPluginMarker] = true + } else { + console.warn('Failed to activate tsEssentialPlugins, because of no typescript or configurationHost context') + } + return {} +}) satisfies import('@volar/language-service').LanguageServicePlugin + +module.exports = { + plugins: [ + c => { + try { + return plugin(c) + } catch (err) { + console.log('TS Essentials error', err) + return {} + } + }, + ], +} satisfies import('@volar/language-server/out/common/utils/serverConfig').ServerConfig diff --git a/typescript/test/completions.spec.ts b/typescript/test/completions.spec.ts index 53526b80..752fa815 100644 --- a/typescript/test/completions.spec.ts +++ b/typescript/test/completions.spec.ts @@ -76,7 +76,16 @@ const defaultConfigFunc = await getDefaultConfigFunc(settingsOverride) const getCompletionsAtPosition = (pos: number, { fileName = entrypoint, shouldHave }: { fileName?: string; shouldHave?: boolean } = {}) => { if (pos === undefined) throw new Error('getCompletionsAtPosition: pos is undefined') - const result = getCompletionsAtPositionRaw(fileName, pos, {}, defaultConfigFunc, languageService, ts.ScriptSnapshot.fromString(files[entrypoint])) + const result = getCompletionsAtPositionRaw( + fileName, + pos, + {}, + defaultConfigFunc, + languageService, + ts.ScriptSnapshot.fromString(files[entrypoint]), + undefined, + { scriptKind: ts.ScriptKind.TSX }, + ) if (shouldHave) expect(result).not.toBeUndefined() if (!result) return return { From 5e2c192a3b4e6078c42d11fafd0cbf09bc5b574a Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Wed, 11 Jan 2023 06:03:20 +0300 Subject: [PATCH 2/6] add vue activation event for just write into config check --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 74364fd4..2b7f3efd 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,8 @@ "onLanguage:javascript", "onLanguage:javascriptreact", "onLanguage:typescript", - "onLanguage:typescriptreact" + "onLanguage:typescriptreact", + "onLanguage:vue" ], "scripts": { "start": "vscode-framework start --skip-launching", From ccbdca7189a632d916cf7a7d40790ee70741da23 Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Wed, 11 Jan 2023 06:19:01 +0300 Subject: [PATCH 3/6] fix: ban method snippets for export {...} --- pnpm-lock.yaml | 217 +----------------- .../isGoodPositionMethodCompletion.ts | 1 + typescript/test/completions.spec.ts | 1 + 3 files changed, 8 insertions(+), 211 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aae0e586..f71054e5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,7 +28,7 @@ importers: chokidar: ^3.5.3 chokidar-cli: ^3.0.0 delay: ^5.0.0 - esbuild: ^0.16.16 + esbuild: ^0.15.15 escape-string-regexp: ^5.0.0 eslint: ^8.7.0 eslint-config-zardoy: ^0.2.12 @@ -67,7 +67,7 @@ importers: '@vscode/emmet-helper': 2.8.4 '@vscode/test-electron': 2.1.5 '@zardoy/utils': 0.0.9 - '@zardoy/vscode-utils': 0.0.47_m6uty6iwlw6f6kdb72kgot4taq + '@zardoy/vscode-utils': 0.0.47_ai5wishe5ovkyp5mm2oyhrbtcu chai: 4.3.6 chokidar: 3.5.3 chokidar-cli: 3.0.0 @@ -99,7 +99,7 @@ importers: '@types/semver': 7.3.13 '@types/vscode': 1.63.1 '@zardoy/tsconfig': 1.3.1_typescript@4.9.3 - esbuild: 0.16.16 + esbuild: 0.15.18 fs-extra: 10.1.0 got: 12.5.3 type-fest: 2.13.1 @@ -385,86 +385,6 @@ packages: requiresBuild: true optional: true - /@esbuild/android-arm/0.16.16: - resolution: {integrity: sha512-BUuWMlt4WSXod1HSl7aGK8fJOsi+Tab/M0IDK1V1/GstzoOpqc/v3DqmN8MkuapPKQ9Br1WtLAN4uEgWR8x64A==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/android-arm64/0.16.16: - resolution: {integrity: sha512-hFHVAzUKp9Tf8psGq+bDVv+6hTy1bAOoV/jJMUWwhUnIHsh6WbFMhw0ZTkqDuh7TdpffFoHOiIOIxmHc7oYRBQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/android-x64/0.16.16: - resolution: {integrity: sha512-9WhxJpeb6XumlfivldxqmkJepEcELekmSw3NkGrs+Edq6sS5KRxtUBQuKYDD7KqP59dDkxVbaoPIQFKWQG0KLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - optional: true - - /@esbuild/darwin-arm64/0.16.16: - resolution: {integrity: sha512-8Z+wld+vr/prHPi2O0X7o1zQOfMbXWGAw9hT0jEyU/l/Yrg+0Z3FO9pjPho72dVkZs4ewZk0bDOFLdZHm8jEfw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@esbuild/darwin-x64/0.16.16: - resolution: {integrity: sha512-CYkxVvkZzGCqFrt7EgjFxQKhlUPyDkuR9P0Y5wEcmJqVI8ncerOIY5Kej52MhZyzOBXkYrJgZeVZC9xXXoEg9A==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@esbuild/freebsd-arm64/0.16.16: - resolution: {integrity: sha512-fxrw4BYqQ39z/3Ja9xj/a1gMsVq0xEjhSyI4a9MjfvDDD8fUV8IYliac96i7tzZc3+VytyXX+XNsnpEk5sw5Wg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - optional: true - - /@esbuild/freebsd-x64/0.16.16: - resolution: {integrity: sha512-8p3v1D+du2jiDvSoNVimHhj7leSfST9YlKsAEO7etBfuqjaBMndo0fmjNLp0JCMld+XIx9L80tooOkyUv1a1PQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - - /@esbuild/linux-arm/0.16.16: - resolution: {integrity: sha512-bYaocE1/PTMRmkgSckZ0D0Xn2nox8v2qlk+MVVqm+VECNKDdZvghVZtH41dNtBbwADSvA6qkCHGYeWm9LrNCBw==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-arm64/0.16.16: - resolution: {integrity: sha512-N3u6BBbCVY3xeP2D8Db7QY8I+nZ+2AgOopUIqk+5yCoLnsWkcVxD2ay5E9iIdvApFi1Vg1lZiiwaVp8bOpAc4A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-ia32/0.16.16: - resolution: {integrity: sha512-dxjqLKUW8GqGemoRT9v8IgHk+T4tRm1rn1gUcArsp26W9EkK/27VSjBVUXhEG5NInHZ92JaQ3SSMdTwv/r9a2A==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-loong64/0.15.18: resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} engines: {node: '>=12'} @@ -473,102 +393,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-loong64/0.16.16: - resolution: {integrity: sha512-MdUFggHjRiCCwNE9+1AibewoNq6wf94GLB9Q9aXwl+a75UlRmbRK3h6WJyrSGA6ZstDJgaD2wiTSP7tQNUYxwA==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-mips64el/0.16.16: - resolution: {integrity: sha512-CO3YmO7jYMlGqGoeFeKzdwx/bx8Vtq/SZaMAi+ZLDUnDUdfC7GmGwXzIwDJ70Sg+P9pAemjJyJ1icKJ9R3q/Fg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-ppc64/0.16.16: - resolution: {integrity: sha512-DSl5Czh5hCy/7azX0Wl9IdzPHX2H8clC6G87tBnZnzUpNgRxPFhfmArbaHoAysu4JfqCqbB/33u/GL9dUgCBAw==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-riscv64/0.16.16: - resolution: {integrity: sha512-sSVVMEXsqf1fQu0j7kkhXMViroixU5XoaJXl1u/u+jbXvvhhCt9YvA/B6VM3aM/77HuRQ94neS5bcisijGnKFQ==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-s390x/0.16.16: - resolution: {integrity: sha512-jRqBCre9gZGoCdCN/UWCCMwCMsOg65IpY9Pyj56mKCF5zXy9d60kkNRdDN6YXGjr3rzcC4DXnS/kQVCGcC4yPQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/linux-x64/0.16.16: - resolution: {integrity: sha512-G1+09TopOzo59/55lk5Q0UokghYLyHTKKzD5lXsAOOlGDbieGEFJpJBr3BLDbf7cz89KX04sBeExAR/pL/26sA==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@esbuild/netbsd-x64/0.16.16: - resolution: {integrity: sha512-xwjGJB5wwDEujLaJIrSMRqWkbigALpBNcsF9SqszoNKc+wY4kPTdKrSxiY5ik3IatojePP+WV108MvF6q6np4w==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - optional: true - - /@esbuild/openbsd-x64/0.16.16: - resolution: {integrity: sha512-yeERkoxG2nR2oxO5n+Ms7MsCeNk23zrby2GXCqnfCpPp7KNc0vxaaacIxb21wPMfXXRhGBrNP4YLIupUBrWdlg==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - optional: true - - /@esbuild/sunos-x64/0.16.16: - resolution: {integrity: sha512-nHfbEym0IObXPhtX6Va3H5GaKBty2kdhlAhKmyCj9u255ktAj0b1YACUs9j5H88NRn9cJCthD1Ik/k9wn8YKVg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - optional: true - - /@esbuild/win32-arm64/0.16.16: - resolution: {integrity: sha512-pdD+M1ZOFy4hE15ZyPX09fd5g4DqbbL1wXGY90YmleVS6Y5YlraW4BvHjim/X/4yuCpTsAFvsT4Nca2lbyDH/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/win32-ia32/0.16.16: - resolution: {integrity: sha512-IPEMfU9p0c3Vb8PqxaPX6BM9rYwlTZGYOf9u+kMdhoILZkVKEjq6PKZO0lB+isojWwAnAqh4ZxshD96njTXajg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/win32-x64/0.16.16: - resolution: {integrity: sha512-1YYpoJ39WV/2bnShPwgdzJklc+XS0bysN6Tpnt1cWPdeoKOG4RMEY1g7i534QxXX/rPvNx/NLJQTTCeORYzipg==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - /@eslint/eslintrc/1.0.5: resolution: {integrity: sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1134,7 +958,7 @@ packages: type-fest: 2.19.0 dev: false - /@zardoy/vscode-utils/0.0.47_m6uty6iwlw6f6kdb72kgot4taq: + /@zardoy/vscode-utils/0.0.47_ai5wishe5ovkyp5mm2oyhrbtcu: resolution: {integrity: sha512-0xsdTonXFxcBdsHcWgkSfJSpP9VOvOiT6oo/LuA5FOGJJI/5W6e6EDwN6Y9FahRWdrYmOfliekEMGZGk/eEWcQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true @@ -1158,7 +982,7 @@ packages: '@zardoy/utils': 0.0.4 chokidar: 3.5.3 commander: 9.4.1 - esbuild: 0.16.16 + esbuild: 0.15.18 execa: 5.1.1 fs-extra: 10.1.0 lodash.throttle: 4.1.1 @@ -2304,35 +2128,6 @@ packages: esbuild-windows-64: 0.15.18 esbuild-windows-arm64: 0.15.18 - /esbuild/0.16.16: - resolution: {integrity: sha512-24JyKq10KXM5EBIgPotYIJ2fInNWVVqflv3gicIyQqfmUqi4HvDW1VR790cBgLJHCl96Syy7lhoz7tLFcmuRmg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.16.16 - '@esbuild/android-arm64': 0.16.16 - '@esbuild/android-x64': 0.16.16 - '@esbuild/darwin-arm64': 0.16.16 - '@esbuild/darwin-x64': 0.16.16 - '@esbuild/freebsd-arm64': 0.16.16 - '@esbuild/freebsd-x64': 0.16.16 - '@esbuild/linux-arm': 0.16.16 - '@esbuild/linux-arm64': 0.16.16 - '@esbuild/linux-ia32': 0.16.16 - '@esbuild/linux-loong64': 0.16.16 - '@esbuild/linux-mips64el': 0.16.16 - '@esbuild/linux-ppc64': 0.16.16 - '@esbuild/linux-riscv64': 0.16.16 - '@esbuild/linux-s390x': 0.16.16 - '@esbuild/linux-x64': 0.16.16 - '@esbuild/netbsd-x64': 0.16.16 - '@esbuild/openbsd-x64': 0.16.16 - '@esbuild/sunos-x64': 0.16.16 - '@esbuild/win32-arm64': 0.16.16 - '@esbuild/win32-ia32': 0.16.16 - '@esbuild/win32-x64': 0.16.16 - /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -3642,7 +3437,7 @@ packages: dependencies: universalify: 2.0.0 optionalDependencies: - graceful-fs: 4.2.9 + graceful-fs: 4.2.10 /jsonify/0.0.0: resolution: {integrity: sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=} diff --git a/typescript/src/completions/isGoodPositionMethodCompletion.ts b/typescript/src/completions/isGoodPositionMethodCompletion.ts index 7a3f8bb4..1eaf0f12 100644 --- a/typescript/src/completions/isGoodPositionMethodCompletion.ts +++ b/typescript/src/completions/isGoodPositionMethodCompletion.ts @@ -12,6 +12,7 @@ export const isGoodPositionBuiltinMethodCompletion = (ts: typeof tslib, sourceFi // type A = typeof obj["|"] if (ts.isStringLiteralLike(currentNode)) return false if (ts.isIdentifier(currentNode)) currentNode = currentNode.parent + if (ts.isExportSpecifier(currentNode)) return false if (ts.isJsxSelfClosingElement(currentNode) || ts.isJsxOpeningElement(currentNode)) return false if (ts.isBindingElement(currentNode) || ts.isShorthandPropertyAssignment(currentNode)) currentNode = currentNode.parent if (ts.isObjectBindingPattern(currentNode) || ts.isObjectLiteralExpression(currentNode)) return false diff --git a/typescript/test/completions.spec.ts b/typescript/test/completions.spec.ts index 752fa815..9d8da1e1 100644 --- a/typescript/test/completions.spec.ts +++ b/typescript/test/completions.spec.ts @@ -115,6 +115,7 @@ test('Banned positions', () => { test('Banned positions for all method snippets', () => { const cursorPositions = newFileContents(/* tsx */ ` import {/*|*/} from 'test' + export {/*|*/} from 'test' const obj = { m$1e$2thod() {}, arrow: () => {} } type A = typeof obj["/*|*/"]; a(({ a/*|*/ }) => {}) From cea2bb906f185e8bc4214d754eabe8b06d3c6946 Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Wed, 11 Jan 2023 06:22:26 +0300 Subject: [PATCH 4/6] fix: don't activate Volar (.vue) support from out of the box to not break default behavior of loading local config files (`./volar.config.js`). You should enable Vue support it if you're not using aforementioned local config file with `"tsEssentialPlugins.enableVueSupport": true` --- src/configurationType.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/configurationType.ts b/src/configurationType.ts index b8895bc6..502b818f 100644 --- a/src/configurationType.ts +++ b/src/configurationType.ts @@ -53,9 +53,9 @@ export type Configuration = { enablePlugin: boolean /** * Wether to enable support in Vue SFC files via Volar config file. - * Changing setting requires volar server restart + * Changing setting false->true->false requires volar server restart * Experimental. - * @default true + * @default false */ enableVueSupport: boolean /** From 5e0bc7ad94321568370c2c05dd2c1cd9e73f10c7 Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Wed, 11 Jan 2023 06:23:39 +0300 Subject: [PATCH 5/6] make test happy --- typescript/src/completions/isGoodPositionMethodCompletion.ts | 1 + typescript/test/completions.spec.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/typescript/src/completions/isGoodPositionMethodCompletion.ts b/typescript/src/completions/isGoodPositionMethodCompletion.ts index 1eaf0f12..9f5a91bb 100644 --- a/typescript/src/completions/isGoodPositionMethodCompletion.ts +++ b/typescript/src/completions/isGoodPositionMethodCompletion.ts @@ -11,6 +11,7 @@ export const isGoodPositionBuiltinMethodCompletion = (ts: typeof tslib, sourceFi // const obj = { method() {}, arrow: () => {} } // type A = typeof obj["|"] if (ts.isStringLiteralLike(currentNode)) return false + if (ts.isNamedExports(currentNode)) return false if (ts.isIdentifier(currentNode)) currentNode = currentNode.parent if (ts.isExportSpecifier(currentNode)) return false if (ts.isJsxSelfClosingElement(currentNode) || ts.isJsxOpeningElement(currentNode)) return false diff --git a/typescript/test/completions.spec.ts b/typescript/test/completions.spec.ts index 9d8da1e1..b1c0330c 100644 --- a/typescript/test/completions.spec.ts +++ b/typescript/test/completions.spec.ts @@ -115,9 +115,9 @@ test('Banned positions', () => { test('Banned positions for all method snippets', () => { const cursorPositions = newFileContents(/* tsx */ ` import {/*|*/} from 'test' - export {/*|*/} from 'test' const obj = { m$1e$2thod() {}, arrow: () => {} } type A = typeof obj["/*|*/"]; + export {/*|*/} from 'test' a(({ a/*|*/ }) => {}) const test = () => ({ method() {} }) const {/*|*/} = test() From 75fe403c53f22ec71e1a3bb036755c0a8b6f64e0 Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Wed, 11 Jan 2023 07:43:57 +0300 Subject: [PATCH 6/6] minor fixes docs + replaceSuggestions --- README.MD | 6 ++++-- src/configurationType.ts | 11 ++++++++--- typescript/src/completionsAtPosition.ts | 12 ++++++------ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/README.MD b/README.MD index ca6d12f0..90279f9d 100644 --- a/README.MD +++ b/README.MD @@ -92,9 +92,11 @@ You can quickly disable this plugin functionality by setting this setting to fal ### Vue Support -`.vue` SFC files support is enabled out of the box when [Vue Language Features (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) is installed. +`.vue` SFC files support is disabled, but can be enabled with setting and when [Vue Language Features (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) is installed. -For the first time, it will configure `volar.vueserver.configFilePath` setting, to disable Vue support use `"tsEssentialPlugins.enableVueSupport": true` setting. +Enable now: `"tsEssentialPlugins.enableVueSupport": true` (if you're not using local `./volar.config.js`) + +For the first time, it will configure `volar.vueserver.configFilePath` setting. This also makes plugin work in Volar's takeover mode! diff --git a/src/configurationType.ts b/src/configurationType.ts index 502b818f..a87d0557 100644 --- a/src/configurationType.ts +++ b/src/configurationType.ts @@ -6,16 +6,21 @@ type ReplaceRule = { * e.g. `readFile`, `^readFile` (global) or `fs.readFile` */ suggestion: string + /** + * Also its possible to specify any other completion properties. For example: + * - sourceDisplay + */ filter?: { kind?: keyof Record - /** doesn't support globs and not generally recommended */ - sourceDisplay?: boolean fileNamePattern?: string languageMode?: keyof typeof ScriptKind } - /** by default only one entry is being proccessed */ + /** by default only first entry is proccessed */ processMany?: boolean delete?: boolean + /** + * - true - original suggestion will be shown below current + */ duplicateOriginal?: boolean | 'above' patch?: Partial<{ name: string diff --git a/typescript/src/completionsAtPosition.ts b/typescript/src/completionsAtPosition.ts index 2f3e397e..192f85d4 100644 --- a/typescript/src/completionsAtPosition.ts +++ b/typescript/src/completionsAtPosition.ts @@ -216,7 +216,7 @@ export const getCompletionsAtPosition = ( if (c('improveJsxCompletions') && leftNode) prior.entries = improveJsxCompletions(prior.entries, leftNode, position, sourceFile, c('jsxCompletionsMap')) - const processedEntryIdxs: number[] = [] + const processedEntries = new Set() for (const rule of c('replaceSuggestions')) { if (rule.filter?.fileNamePattern) { // todo replace with something better @@ -242,8 +242,9 @@ export const getCompletionsAtPosition = ( // todo-low (perf debt) clone probably should be used this const entry = prior!.entries[entryIndex]! if (rule.duplicateOriginal) { - processedEntryIdxs.push(entryIndex + 1) - prior!.entries.splice(rule.duplicateOriginal === 'above' ? entryIndex : entryIndex + 1, 0, { ...entry }) + const duplicateEntry = { ...entry } + prior!.entries.splice(rule.duplicateOriginal === 'above' ? entryIndex : entryIndex + 1, 0, duplicateEntry) + processedEntries.add(duplicateEntry) } const { patch } = rule @@ -259,12 +260,11 @@ export const getCompletionsAtPosition = ( entry.insertText = entry.name } if (rule.patch?.insertText) entry.isSnippet = true - processedEntryIdxs.push(entryIndex) - prior!.entries.splice(entryIndex, 1, entry) + processedEntries.add(entry) } entry: for (const [i, entry] of prior!.entries.entries()) { - if (processedEntryIdxs.includes(i)) continue + if (processedEntries.has(entry)) continue const { name } = entry if (!nameComparator(name)) continue const { fileNamePattern, languageMode, ...simpleEntryFilters } = rule.filter ?? {}