diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml new file mode 100644 index 000000000000..0ad187981e37 --- /dev/null +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -0,0 +1,21 @@ +## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details. + +pipelines: + 111: + retail: + source: + credscan: + lastModifiedDate: 2024-09-10 + eslint: + lastModifiedDate: 2024-09-10 + psscriptanalyzer: + lastModifiedDate: 2024-09-10 + armory: + lastModifiedDate: 2024-09-10 + binary: + credscan: + lastModifiedDate: 2025-02-04 + binskim: + lastModifiedDate: 2025-02-04 + spotbugs: + lastModifiedDate: 2025-02-04 diff --git a/.config/guardian/.gdnbaselines b/.config/guardian/.gdnbaselines new file mode 100644 index 000000000000..55412ff93e56 --- /dev/null +++ b/.config/guardian/.gdnbaselines @@ -0,0 +1,255 @@ +{ + "properties": { + "helpUri": "https://eng.ms/docs/microsoft-security/security/azure-security/cloudai-security-fundamentals-engineering/security-integration/guardian-wiki/microsoft-guardian/general/baselines" + }, + "version": "1.0.0", + "baselines": { + "default": { + "name": "default", + "createdDate": "2025-01-28 06:29:05Z", + "lastUpdatedDate": "2025-01-28 06:29:05Z" + } + }, + "results": { + "ea3b2bf4f5b3d0bd8a6ad35cc61e49f2a1596660fd66d17d740e4806e7ed7dcc": { + "signature": "ea3b2bf4f5b3d0bd8a6ad35cc61e49f2a1596660fd66d17d740e4806e7ed7dcc", + "alternativeSignatures": [ + "ff528c0b5a010ae7b5e9178b004a8b816a429a28ba98ce8336466b490a09dcef" + ], + "target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.97.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2009", + "createdDate": "2025-01-30 19:19:49Z", + "expirationDate": "2025-07-19 21:12:48Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z" + }, + "12babbc85192ed1c8d927693da788537c1eef199bbecbe226f940a2d0e97637c": { + "signature": "12babbc85192ed1c8d927693da788537c1eef199bbecbe226f940a2d0e97637c", + "alternativeSignatures": [ + "35b0519e201e56fb87fc6fb085e6fb1df5b89715142bb9086a5b2006e0fd4ced" + ], + "target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.97.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2018", + "createdDate": "2025-01-30 19:19:49Z", + "expirationDate": "2025-07-19 21:12:48Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z" + }, + "49163bd1dc9d965d3baced1694dc8c43305b8bf96e884f478d8e4bd124454ba0": { + "signature": "49163bd1dc9d965d3baced1694dc8c43305b8bf96e884f478d8e4bd124454ba0", + "alternativeSignatures": [ + "aa80bcf44aa8ddd20fb9802e9032c1257048b973896a944ded70bb195f060b2a" + ], + "target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.97.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2009", + "createdDate": "2025-01-30 19:21:17Z", + "expirationDate": "2025-07-19 21:12:48Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z" + }, + "c405af02e021c3a473d4e45ec4daa658db1527ea7430c6be968d182e7b50fbd1": { + "signature": "c405af02e021c3a473d4e45ec4daa658db1527ea7430c6be968d182e7b50fbd1", + "alternativeSignatures": [ + "619d2a1a77f55b4181493b8cfdf09be5261e539115752af2e4938f5ac04af132" + ], + "target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.97.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2018", + "createdDate": "2025-01-30 19:21:17Z", + "expirationDate": "2025-07-19 21:12:48Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z" + }, + "71b8515b2eb51cfd5eace11cedb15189d51ce9e479095a5938334416088cbc03": { + "signature": "71b8515b2eb51cfd5eace11cedb15189d51ce9e479095a5938334416088cbc03", + "alternativeSignatures": [ + "b34279fc5fec828b8dcd9ca873804e85d7d9cd78554ec109d2dd493351a7a244" + ], + "target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.97.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2009", + "createdDate": "2025-01-30 19:51:51Z", + "expirationDate": "2025-07-19 21:12:48Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z" + }, + "9238de77a5320039def14694d1b6f501cc2288f13c9c688d2e0501fc5a56ee61": { + "signature": "9238de77a5320039def14694d1b6f501cc2288f13c9c688d2e0501fc5a56ee61", + "alternativeSignatures": [ + "1d17616a549e9f36d814c4e802d651b1af453ce0a23d4478eef39be81adcc16b" + ], + "target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.97.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2018", + "createdDate": "2025-01-30 19:51:51Z", + "expirationDate": "2025-07-19 21:12:48Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z" + }, + "bad8b698b48c1da9ece953903581c66bf98bc829ae1a6adcd3b5c2056a6fcd01": { + "signature": "bad8b698b48c1da9ece953903581c66bf98bc829ae1a6adcd3b5c2056a6fcd01", + "alternativeSignatures": [ + "057376d31b97e8ce3ecf6a180a553b932d7e5be6e2b07a08027d5dfabe35e82c" + ], + "target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.97.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2009", + "createdDate": "2025-01-30 19:53:13Z", + "expirationDate": "2025-07-19 21:12:48Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z" + }, + "cc7c248b0fd4c105e9a393ae232bf0d314ec50e65357a5e7e7d68f6f10c77077": { + "signature": "cc7c248b0fd4c105e9a393ae232bf0d314ec50e65357a5e7e7d68f6f10c77077", + "alternativeSignatures": [ + "f3867098aff3368682df9926e85a35ec05cf905f27d0c157430021c3169f899d" + ], + "target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.97.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2018", + "createdDate": "2025-01-30 19:53:13Z", + "expirationDate": "2025-07-19 21:12:48Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z" + }, + "8c53250a171412b84dedcbb22cdab9ec365d9b52d74b09c070097fff45372de0": { + "signature": "8c53250a171412b84dedcbb22cdab9ec365d9b52d74b09c070097fff45372de0", + "alternativeSignatures": [ + "314267784b0ea867006e00b809a93498fae3264e42d1a3a7745ab13180a5b6ef" + ], + "target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.98.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2009", + "createdDate": "2025-02-04 06:16:33Z", + "expirationDate": "2025-07-24 07:25:17Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z" + }, + "a6a58d971da858f4af219672cef73ffd0aacc47f1e2c12b8b44a428e1330d3de": { + "signature": "a6a58d971da858f4af219672cef73ffd0aacc47f1e2c12b8b44a428e1330d3de", + "alternativeSignatures": [ + "4e40f2f1683f0bf2245f35d0ebbcf2f446274d84b1db09d8e76ddfdcad5d4479" + ], + "target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.98.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2018", + "createdDate": "2025-02-04 06:16:33Z", + "expirationDate": "2025-07-24 07:25:17Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z" + }, + "90e0f060e01e4a55620f609ac3241b62e8f54a059e9f4d292e93a4305fd3c39e": { + "signature": "90e0f060e01e4a55620f609ac3241b62e8f54a059e9f4d292e93a4305fd3c39e", + "alternativeSignatures": [ + "377fe43ff8404d07f4a6ca763175004f360397ded6cf5d55b655646ada90e39c" + ], + "target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.98.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2009", + "createdDate": "2025-02-04 06:17:54Z", + "expirationDate": "2025-07-24 07:25:17Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z" + }, + "f36c3dc19566098a923877d16d6ebfcbd971f8fcd8210afb8f5558fb5ba1f203": { + "signature": "f36c3dc19566098a923877d16d6ebfcbd971f8fcd8210afb8f5558fb5ba1f203", + "alternativeSignatures": [ + "1af1f475c1617701e3d7a8fd465916bcc60c3125b8807af5d47d49137d9d468c" + ], + "target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.98.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2018", + "createdDate": "2025-02-04 06:17:54Z", + "expirationDate": "2025-07-24 07:25:17Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z" + }, + "71193d108c53bb802f5c491276365bcff0645fb380be57288f3fbd6896166d3a": { + "signature": "71193d108c53bb802f5c491276365bcff0645fb380be57288f3fbd6896166d3a", + "alternativeSignatures": [ + "420cae2e6e34b93d7b74fc1ffddfdf23b57650ae989d838bb2d67f28e4e1db0e" + ], + "target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.98.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2009", + "createdDate": "2025-02-04 07:11:19Z", + "expirationDate": "2025-07-24 07:25:17Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z" + }, + "444c302f49bdedcafe772322a09727b2279e3265d99deb2e307defeae3ef200b": { + "signature": "444c302f49bdedcafe772322a09727b2279e3265d99deb2e307defeae3ef200b", + "alternativeSignatures": [ + "4ff6ccbdb0745d43d3b61f82fb2f4d8a64fe9787525df81a6d7b825e79282085" + ], + "target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.98.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2018", + "createdDate": "2025-02-04 07:11:19Z", + "expirationDate": "2025-07-24 07:25:17Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z" + }, + "4670c7c096a69ca428429ffa1f5250aac9f2e07beac0ffe587ffb37bdb1da4d4": { + "signature": "4670c7c096a69ca428429ffa1f5250aac9f2e07beac0ffe587ffb37bdb1da4d4", + "alternativeSignatures": [ + "7cead96cb508ab6e37e27bcc0f8b7ed8d0761b77f4793958c46c5ff3892ab1b6" + ], + "target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.98.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2009", + "createdDate": "2025-02-04 07:13:22Z", + "expirationDate": "2025-07-24 07:25:17Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z" + }, + "a359b4a5ed2378a73f3bba93e3fb1c595db7423c3082635d12d101bbeb0a51b8": { + "signature": "a359b4a5ed2378a73f3bba93e3fb1c595db7423c3082635d12d101bbeb0a51b8", + "alternativeSignatures": [ + "125b52a21ef619a95e695085deb9492280bcf2c1decdd5e87e6416af5982d02d" + ], + "target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.98.0-insider.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2018", + "createdDate": "2025-02-04 07:13:22Z", + "expirationDate": "2025-07-24 07:25:17Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z" + } + } +} \ No newline at end of file diff --git a/.eslint-ignore b/.eslint-ignore index 6fbdf94696e6..233c9b3e6146 100644 --- a/.eslint-ignore +++ b/.eslint-ignore @@ -12,7 +12,9 @@ **/extensions/markdown-math/notebook-out/** **/extensions/notebook-renderers/renderer-out/index.js **/extensions/simple-browser/media/index.js -**/extensions/terminal-suggest/src/completions/** +**/extensions/terminal-suggest/src/completions/upstream/** +**/extensions/terminal-suggest/src/shell/zshBuiltinsCache.ts +**/extensions/terminal-suggest/third_party/** **/extensions/typescript-language-features/test-workspace/** **/extensions/typescript-language-features/extension.webpack.config.js **/extensions/typescript-language-features/extension-browser.webpack.config.js diff --git a/.eslint-plugin-local/vscode-dts-region-comments.ts b/.eslint-plugin-local/vscode-dts-region-comments.ts deleted file mode 100644 index b08dc6357bbf..000000000000 --- a/.eslint-plugin-local/vscode-dts-region-comments.ts +++ /dev/null @@ -1,40 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as eslint from 'eslint'; - -export = new class ApiEventNaming implements eslint.Rule.RuleModule { - - readonly meta: eslint.Rule.RuleMetaData = { - messages: { - comment: 'region comments should start with a camel case identifier, `:`, then either a GH issue link or owner, e.g #region myProposalName: https://github.com/microsoft/vscode/issues/', - }, - schema: false, - }; - - create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - - const sourceCode = context.getSourceCode(); - - return { - ['Program']: (_node: any) => { - for (const comment of sourceCode.getAllComments()) { - if (comment.type !== 'Line') { - continue; - } - if (!/^\s*#region /.test(comment.value)) { - continue; - } - if (!/^\s*#region ([a-z]+): (@[a-z]+|https:\/\/github.com\/microsoft\/vscode\/issues\/\d+)/i.test(comment.value)) { - context.report({ - node: comment, - messageId: 'comment', - }); - } - } - } - }; - } -}; diff --git a/.github/classifier.json b/.github/classifier.json index 6240035d8085..93ca6f3293c3 100644 --- a/.github/classifier.json +++ b/.github/classifier.json @@ -199,9 +199,9 @@ "sash-widget": {"assign": ["joaomoreno"]}, "scm": {"assign": ["lszomoru"]}, "screencast-mode": {"assign": ["joaomoreno"]}, - "search": {"assign": ["roblourens"]}, - "search-api": {"assign": ["roblourens"]}, - "search-editor": {"assign": ["roblourens"]}, + "search": {"assign": ["osortega"]}, + "search-api": {"assign": ["osortega"]}, + "search-editor": {"assign": ["osortega"]}, "search-replace": {"assign": ["sandy081"]}, "semantic-tokens": {"assign": ["alexdima", "aeschli"]}, "server": {"assign": ["alexdima"]}, diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5ace4600a1f2..a49bf40fff10 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,4 @@ updates: directory: "/" schedule: interval: "weekly" + diff --git a/.github/workflows/basic.yml b/.github/workflows/basic.yml deleted file mode 100644 index d5f166a4aae8..000000000000 --- a/.github/workflows/basic.yml +++ /dev/null @@ -1,176 +0,0 @@ -name: Basic checks - -on: workflow_dispatch - -# on: -# push: -# branches: -# - main -# pull_request: -# branches: -# - main - -jobs: - main: - if: github.ref != 'refs/heads/main' - name: Compilation, Unit and Integration Tests - runs-on: ubuntu-latest - timeout-minutes: 40 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - - name: Setup Build Environment - run: | - sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start - - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - - name: Compute node modules cache key - id: nodeModulesCacheKey - run: echo "value=$(node build/azure-pipelines/common/computeNodeModulesCacheKey.js)" >> $GITHUB_OUTPUT - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v4 - with: - path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModulesLinux-${{ steps.nodeModulesCacheKey.outputs.value }} - - name: Get npm cache directory path - id: npmCacheDirPath - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - - name: Cache npm directory - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - uses: actions/cache@v4 - with: - path: ${{ steps.npmCacheDirPath.outputs.dir }} - key: ${{ runner.os }}-npmCacheDir-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-npmCacheDir- - - name: Execute npm - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - run: npm ci - - - name: Compile and Download - run: npm exec -- npm-run-all -lp compile "electron x64" - - - name: Run Unit Tests - id: electron-unit-tests - run: DISPLAY=:10 ./scripts/test.sh - - - name: Run Integration Tests (Electron) - id: electron-integration-tests - run: DISPLAY=:10 ./scripts/test-integration.sh - - hygiene: - if: github.ref != 'refs/heads/main' - name: Hygiene and Layering - runs-on: ubuntu-latest - timeout-minutes: 40 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - - name: Compute node modules cache key - id: nodeModulesCacheKey - run: echo "value=$(node build/azure-pipelines/common/computeNodeModulesCacheKey.js)" >> $GITHUB_OUTPUT - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v4 - with: - path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModulesLinux-${{ steps.nodeModulesCacheKey.outputs.value }} - - name: Get npm cache directory path - id: npmCacheDirPath - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - - name: Cache npm directory - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - uses: actions/cache@v4 - with: - path: ${{ steps.npmCacheDirPath.outputs.dir }} - key: ${{ runner.os }}-npmCacheDir-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-npmCacheDir- - - name: Execute npm - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - run: npm ci - - - name: Run Hygiene Checks - run: npm run gulp hygiene - - - name: Run Valid Layers Checks - run: npm run valid-layers-check - - - name: Compile /build/ - run: npm run compile - working-directory: build - - - name: Check clean git state - run: ./.github/workflows/check-clean-git-state.sh - - - name: Run eslint - run: npm run eslint - - - name: Run vscode-dts Compile Checks - run: npm run vscode-dts-compile-check - - - name: Run Trusted Types Checks - run: npm run tsec-compile-check - - warm-cache: - name: Warm up node modules cache - if: github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - timeout-minutes: 40 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - - name: Compute node modules cache key - id: nodeModulesCacheKey - run: echo "value=$(node build/azure-pipelines/common/computeNodeModulesCacheKey.js)" >> $GITHUB_OUTPUT - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v4 - with: - path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModulesLinux-${{ steps.nodeModulesCacheKey.outputs.value }} - - name: Get npm cache directory path - id: npmCacheDirPath - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - - name: Cache npm directory - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - uses: actions/cache@v4 - with: - path: ${{ steps.npmCacheDirPath.outputs.dir }} - key: ${{ runner.os }}-npmCacheDir-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-npmCacheDir- - - name: Execute npm - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - run: npm ci diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 344213e0ca88..000000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,316 +0,0 @@ -name: CI - -on: workflow_dispatch - -# on: -# push: -# branches: -# - main -# - release/* -# pull_request: -# branches: -# - main -# - release/* - -jobs: - windows: - name: Windows - runs-on: windows-2022 - timeout-minutes: 60 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - - uses: actions/setup-python@v5 - with: - python-version: "3.x" - - - name: Compute node modules cache key - id: nodeModulesCacheKey - run: echo "value=$(node build/azure-pipelines/common/computeNodeModulesCacheKey.js)" >> $GITHUB_OUTPUT - - name: Cache node_modules archive - id: cacheNodeModules - uses: actions/cache@v4 - with: - path: ".build/node_modules_cache" - key: "${{ runner.os }}-cacheNodeModulesArchive-${{ steps.nodeModulesCacheKey.outputs.value }}" - - name: Extract node_modules archive - if: ${{ steps.cacheNodeModules.outputs.cache-hit == 'true' }} - run: 7z.exe x .build/node_modules_cache/cache.7z -aos - - name: Get npm cache directory path - id: npmCacheDirPath - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - - name: Cache npm directory - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - uses: actions/cache@v4 - with: - path: ${{ steps.npmCacheDirPath.outputs.dir }} - key: ${{ runner.os }}-npmCacheDir-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-npmCacheDir- - - name: Execute npm - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - env: - npm_config_foreground_scripts: "true" - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - run: npm ci - - name: Create node_modules archive - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - run: | - mkdir -Force .build - node build/azure-pipelines/common/listNodeModules.js .build/node_modules_list.txt - mkdir -Force .build/node_modules_cache - 7z.exe a .build/node_modules_cache/cache.7z -mx3 `@.build/node_modules_list.txt - - - name: Compile and Download - run: npm exec -- npm-run-all -lp compile "electron x64" playwright-install download-builtin-extensions - - - name: Compile Integration Tests - run: npm run compile - working-directory: test/integration/browser - - - name: Run Unit Tests (Electron) - run: .\scripts\test.bat - - - name: Run Unit Tests (node.js) - run: npm run test-node - - - name: Run Unit Tests (Browser, Chromium) - run: npm run test-browser-no-install -- --browser chromium - - - name: Run Integration Tests (Electron) - run: .\scripts\test-integration.bat - - - name: Run Integration Tests (Browser, Firefox) - timeout-minutes: 20 - run: .\scripts\test-web-integration.bat --browser firefox - - - name: Run Integration Tests (Remote) - timeout-minutes: 20 - run: .\scripts\test-remote-integration.bat - - linux: - name: Linux - runs-on: ubuntu-latest - timeout-minutes: 40 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - # TODO: rename azure-pipelines/linux/xvfb.init to github-actions - - name: Setup Build Environment - run: | - sudo apt-get update - sudo apt-get install -y libxkbfile-dev pkg-config libkrb5-dev libxss1 dbus xvfb libgtk-3-0 libgbm1 - sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start - - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - - name: Compute node modules cache key - id: nodeModulesCacheKey - run: echo "value=$(node build/azure-pipelines/common/computeNodeModulesCacheKey.js)" >> $GITHUB_OUTPUT - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v4 - with: - path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModulesLinux-${{ steps.nodeModulesCacheKey.outputs.value }} - - name: Get npm cache directory path - id: npmCacheDirPath - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - - name: Cache npm directory - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - uses: actions/cache@v4 - with: - path: ${{ steps.npmCacheDirPath.outputs.dir }} - key: ${{ runner.os }}-npmCacheDir-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-npmCacheDir- - - name: Execute npm - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - run: npm ci - - - name: Compile and Download - run: npm exec -- npm-run-all -lp compile "electron x64" playwright-install download-builtin-extensions - - - name: Compile Integration Tests - run: npm run compile - working-directory: test/integration/browser - - - name: Run Unit Tests (Electron) - id: electron-unit-tests - run: DISPLAY=:10 ./scripts/test.sh - - - name: Run Unit Tests (node.js) - id: nodejs-unit-tests - run: npm run test-node - - - name: Run Unit Tests (Browser, Chromium) - id: browser-unit-tests - run: DISPLAY=:10 npm run test-browser-no-install -- --browser chromium - - - name: Run Integration Tests (Electron) - id: electron-integration-tests - run: DISPLAY=:10 ./scripts/test-integration.sh - - - name: Run Integration Tests (Browser, Chromium) - id: browser-integration-tests - run: DISPLAY=:10 ./scripts/test-web-integration.sh --browser chromium - - - name: Run Integration Tests (Remote) - id: electron-remote-integration-tests - timeout-minutes: 15 - run: DISPLAY=:10 ./scripts/test-remote-integration.sh - - darwin: - name: macOS - runs-on: macos-latest - timeout-minutes: 40 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - - name: Compute node modules cache key - id: nodeModulesCacheKey - run: echo "value=$(node build/azure-pipelines/common/computeNodeModulesCacheKey.js)" >> $GITHUB_OUTPUT - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v4 - with: - path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModulesMacOS-${{ steps.nodeModulesCacheKey.outputs.value }} - - name: Get npm cache directory path - id: npmCacheDirPath - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - - name: Cache npm directory - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - uses: actions/cache@v4 - with: - path: ${{ steps.npmCacheDirPath.outputs.dir }} - key: ${{ runner.os }}-npmCacheDir-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-npmCacheDir- - - name: Execute npm - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - run: npm ci - - - name: Compile and Download - run: npm exec -- npm-run-all -lp compile "electron x64" playwright-install download-builtin-extensions - - - name: Compile Integration Tests - run: npm run compile - working-directory: test/integration/browser - - # This is required for SecretStorage unittests - - name: Create temporary keychain - run: | - security create-keychain -p pwd $RUNNER_TEMP/buildagent.keychain - security default-keychain -s $RUNNER_TEMP/buildagent.keychain - security unlock-keychain -p pwd $RUNNER_TEMP/buildagent.keychain - - - name: Run Unit Tests (Electron) - run: DISPLAY=:10 ./scripts/test.sh - - - name: Run Unit Tests (node.js) - run: npm run test-node - - - name: Run Unit Tests (Browser, Chromium) - run: DISPLAY=:10 npm run test-browser-no-install -- --browser chromium - - - name: Run Integration Tests (Electron) - run: DISPLAY=:10 ./scripts/test-integration.sh - - - name: Run Integration Tests (Browser, Webkit) - run: DISPLAY=:10 ./scripts/test-web-integration.sh --browser webkit - - - name: Run Integration Tests (Remote) - timeout-minutes: 15 - run: DISPLAY=:10 ./scripts/test-remote-integration.sh - - hygiene: - name: Hygiene and Layering - runs-on: ubuntu-latest - timeout-minutes: 40 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - - name: Compute node modules cache key - id: nodeModulesCacheKey - run: echo "value=$(node build/azure-pipelines/common/computeNodeModulesCacheKey.js)" >> $GITHUB_OUTPUT - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v4 - with: - path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModulesLinux-${{ steps.nodeModulesCacheKey.outputs.value }} - - name: Get npm cache directory path - id: npmCacheDirPath - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - - name: Cache npm directory - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - uses: actions/cache@v4 - with: - path: ${{ steps.npmCacheDirPath.outputs.dir }} - key: ${{ runner.os }}-npmCacheDir-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-npmCacheDir- - - name: Execute npm - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - run: npm ci - - - name: Download Playwright - run: npm run playwright-install - - - name: Run Hygiene Checks - run: npm run gulp hygiene - - - name: Run Valid Layers Checks - run: npm run valid-layers-check - - - name: Compile /build/ - run: npm run compile - working-directory: build - - - name: Check clean git state - run: ./.github/workflows/check-clean-git-state.sh - - - name: Run eslint - run: npm run eslint - - - name: Run vscode-dts Compile Checks - run: npm run vscode-dts-compile-check - - - name: Run Trusted Types Checks - run: npm run tsec-compile-check diff --git a/.github/workflows/monaco-editor.yml b/.github/workflows/monaco-editor.yml deleted file mode 100644 index 1f5694faec2b..000000000000 --- a/.github/workflows/monaco-editor.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: Monaco Editor checks - -on: - push: - branches: - - main - - release/* - pull_request: - branches: - - main - - release/* - -jobs: - main: - name: Monaco Editor checks - runs-on: ubuntu-latest - timeout-minutes: 40 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - - name: Compute node modules cache key - id: nodeModulesCacheKey - run: echo "value=$(node build/azure-pipelines/common/computeNodeModulesCacheKey.js)" >> $GITHUB_OUTPUT - - name: Cache node modules - id: cacheNodeModules - uses: actions/cache@v4 - with: - path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules20-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-cacheNodeModules20- - - name: Get npm cache directory path - id: npmCacheDirPath - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - - name: Cache npm directory - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - uses: actions/cache@v4 - with: - path: ${{ steps.npmCacheDirPath.outputs.dir }} - key: ${{ runner.os }}-npmCacheDir-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-npmCacheDir- - - name: Install system dependencies - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - run: | - sudo apt update - sudo apt install -y libxkbfile-dev pkg-config libkrb5-dev libxss1 - - name: Execute npm - if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - run: | - npm ci - - - name: Download Playwright - run: npm run playwright-install - - - name: Run Monaco Editor Checks - run: npm run monaco-compile-check - - - name: Editor Distro & ESM - run: npm run gulp editor-esm - - - name: Editor ESM sources check - working-directory: ./test/monaco - run: npm run esm-check - - - name: Typings validation prep - run: | - mkdir typings-test - - - name: Typings validation - working-directory: ./typings-test - run: | - npm init -yp - ../node_modules/.bin/tsc --init - echo "import '../out-monaco-editor-core';" > a.ts - ../node_modules/.bin/tsc --noEmit - - - name: Package Editor with Webpack - working-directory: ./test/monaco - run: npm run bundle-webpack - - - name: Compile Editor Tests - working-directory: ./test/monaco - run: npm run compile - - - name: Run Editor Tests - timeout-minutes: 5 - working-directory: ./test/monaco - run: npm run test diff --git a/.github/workflows/no-package-lock-changes.yml b/.github/workflows/no-package-lock-changes.yml deleted file mode 100644 index 45d5d17407bf..000000000000 --- a/.github/workflows/no-package-lock-changes.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Prevent package-lock.json changes in PRs -on: [pull_request] - -jobs: - main: - name: Prevent package-lock.json changes in PRs - runs-on: ubuntu-latest - steps: - - uses: octokit/request-action@v2.x - id: get_permissions - with: - route: GET /repos/microsoft/vscode/collaborators/{username}/permission - username: ${{ github.event.pull_request.user.login }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Set control output variable - id: control - run: | - echo "user: ${{ github.event.pull_request.user.login }}" - echo "role: ${{ fromJson(steps.get_permissions.outputs.data).permission }}" - echo "is dependabot: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }}" - echo "should_run: ${{ !contains(fromJson('["admin", "maintain", "write"]'), fromJson(steps.get_permissions.outputs.data).permission) }}" - echo "should_run=${{ !contains(fromJson('["admin", "maintain", "write"]'), fromJson(steps.get_permissions.outputs.data).permission) && github.event.pull_request.user.login != 'dependabot[bot]' }}" >> $GITHUB_OUTPUT - - name: Get file changes - uses: trilom/file-changes-action@ce38c8ce2459ca3c303415eec8cb0409857b4272 - if: ${{ steps.control.outputs.should_run == 'true' }} - - name: Check for lockfile changes - if: ${{ steps.control.outputs.should_run == 'true' }} - run: | - cat $HOME/files.json | jq -e 'any(test("package-lock\\.json$|Cargo\\.lock$")) | not' \ - || (echo "Changes to package-lock.json/Cargo.lock files aren't allowed in PRs." && exit 1) diff --git a/.github/workflows/no-yarn-lock-changes.yml b/.github/workflows/no-yarn-lock-changes.yml deleted file mode 100644 index 57082a28b1cc..000000000000 --- a/.github/workflows/no-yarn-lock-changes.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Prevent yarn.lock changes in PRs -on: [pull_request] - -jobs: - main: - name: Prevent yarn.lock changes in PRs - runs-on: ubuntu-latest - steps: - - uses: octokit/request-action@v2.x - id: get_permissions - with: - route: GET /repos/microsoft/vscode/collaborators/{username}/permission - username: ${{ github.event.pull_request.user.login }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Set control output variable - id: control - run: | - echo "user: ${{ github.event.pull_request.user.login }}" - echo "role: ${{ fromJson(steps.get_permissions.outputs.data).permission }}" - echo "is dependabot: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }}" - echo "should_run: ${{ !contains(fromJson('["admin", "maintain", "write"]'), fromJson(steps.get_permissions.outputs.data).permission) }}" - echo "should_run=${{ !contains(fromJson('["admin", "maintain", "write"]'), fromJson(steps.get_permissions.outputs.data).permission) && github.event.pull_request.user.login != 'dependabot[bot]' }}" >> $GITHUB_OUTPUT - - name: Get file changes - uses: trilom/file-changes-action@ce38c8ce2459ca3c303415eec8cb0409857b4272 - if: ${{ steps.control.outputs.should_run == 'true' }} - - name: Check for lockfile changes - if: ${{ steps.control.outputs.should_run == 'true' }} - run: | - cat $HOME/files.json | jq -e 'any(test("yarn\\.lock$|Cargo\\.lock$")) | not' \ - || (echo "Changes to yarn.lock/Cargo.lock files aren't allowed in PRs." && exit 1) diff --git a/.github/workflows/telemetry.yml b/.github/workflows/telemetry.yml index d29ea6c58dac..c28342952976 100644 --- a/.github/workflows/telemetry.yml +++ b/.github/workflows/telemetry.yml @@ -4,16 +4,18 @@ on: jobs: check-metdata: name: 'Check metadata' + permissions: + contents: read runs-on: 'ubuntu-latest' steps: - uses: 'actions/checkout@v4' - - uses: 'actions/setup-node@v4' + - uses: 'actions/setup-node@v6' with: node-version: 'lts/*' - name: 'Run vscode-telemetry-extractor' - run: 'npx --package=@vscode/telemetry-extractor --yes vscode-telemetry-extractor -s .' + run: 'npx --package=@vscode/telemetry-extractor@1.14.0 --yes vscode-telemetry-extractor -s .' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.npmrc b/.npmrc index 27692c2409ee..71d98e6c5834 100644 --- a/.npmrc +++ b/.npmrc @@ -1,6 +1,6 @@ disturl="https://electronjs.org/headers" -target="32.2.7" -ms_build_id="10660205" +target="34.3.2" +ms_build_id="11161073" runtime="electron" build_from_source="true" legacy-peer-deps="true" diff --git a/.nvmrc b/.nvmrc index d4b7699d36ca..0254b1e633c7 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20.18.1 +20.18.2 diff --git a/.vscode-test.js b/.vscode-test.js index 917413ede2ac..823ef615f4f7 100644 --- a/.vscode-test.js +++ b/.vscode-test.js @@ -19,7 +19,7 @@ const { defineConfig } = require('@vscode/test-cli'); * A list of extension folders who have opted into tests, or configuration objects. * Edit me to add more! * - * @type {Array & { label: string })>} + * @type {Array & { label: string }>} */ const extensions = [ { @@ -65,6 +65,20 @@ const extensions = [ { label: 'microsoft-authentication', mocha: { timeout: 60_000 } + }, + { + label: 'vscode-api-tests-folder', + extensionDevelopmentPath: `extensions/vscode-api-tests`, + workspaceFolder: `extensions/vscode-api-tests/testWorkspace`, + mocha: { timeout: 60_000 }, + files: 'extensions/vscode-api-tests/out/singlefolder-tests/**/*.test.js', + }, + { + label: 'vscode-api-tests-workspace', + extensionDevelopmentPath: `extensions/vscode-api-tests`, + workspaceFolder: `extensions/vscode-api-tests/testworkspace.code-workspace`, + mocha: { timeout: 60_000 }, + files: 'extensions/vscode-api-tests/out/workspace-tests/**/*.test.js', } ]; @@ -75,9 +89,12 @@ const defaultLaunchArgs = process.env.API_TESTS_EXTRA_ARGS?.split(' ') || [ const config = defineConfig(extensions.map(extension => { /** @type {import('@vscode/test-cli').TestConfiguration} */ - const config = typeof extension === 'object' - ? { files: `extensions/${extension.label}/out/**/*.test.js`, ...extension } - : { files: `extensions/${extension}/out/**/*.test.js`, label: extension }; + const config = { + platform: 'desktop', + files: `extensions/${extension.label}/out/**/*.test.js`, + extensionDevelopmentPath: `extensions/${extension.label}`, + ...extension, + }; config.mocha ??= {}; if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) { diff --git a/.vscode/extensions/vscode-selfhost-test-provider/package.json b/.vscode/extensions/vscode-selfhost-test-provider/package.json index 3548b00ba81f..71b5ee73c60d 100644 --- a/.vscode/extensions/vscode-selfhost-test-provider/package.json +++ b/.vscode/extensions/vscode-selfhost-test-provider/package.json @@ -4,8 +4,7 @@ "description": "Test provider for the VS Code project", "enabledApiProposals": [ "testObserver", - "testRelatedCode", - "attributableCoverage" + "testRelatedCode" ], "engines": { "vscode": "^1.88.0" diff --git a/.vscode/launch.json b/.vscode/launch.json index afd57934304f..f922b5d9c803 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -251,7 +251,51 @@ "timeout": 0, "env": { "VSCODE_EXTHOST_WILL_SEND_SOCKET": null, - "VSCODE_SKIP_PRELAUNCH": "1" + "VSCODE_SKIP_PRELAUNCH": "1", + }, + "cleanUp": "wholeBrowser", + "runtimeArgs": [ + "--inspect-brk=5875", + "--no-cached-data", + "--crash-reporter-directory=${workspaceFolder}/.profile-oss/crashes", + // for general runtime freezes: https://github.com/microsoft/vscode/issues/127861#issuecomment-904144910 + "--disable-features=CalculateNativeWinOcclusion", + "--disable-extension=vscode.vscode-api-tests" + ], + "userDataDir": "${userHome}/.vscode-oss-dev", + "webRoot": "${workspaceFolder}", + "cascadeTerminateToConfigurations": [ + "Attach to Extension Host" + ], + "pauseForSourceMap": false, + "outFiles": [ + "${workspaceFolder}/out/**/*.js" + ], + "browserLaunchLocation": "workspace", + "presentation": { + "hidden": true, + }, + }, + { + // To debug observables you also need the extension "ms-vscode.debug-value-editor" + "type": "chrome", + "request": "launch", + "name": "Launch VS Code Internal (Dev Debug)", + "windows": { + "runtimeExecutable": "${workspaceFolder}/scripts/code.bat" + }, + "osx": { + "runtimeExecutable": "${workspaceFolder}/scripts/code.sh" + }, + "linux": { + "runtimeExecutable": "${workspaceFolder}/scripts/code.sh" + }, + "port": 9222, + "timeout": 0, + "env": { + "VSCODE_EXTHOST_WILL_SEND_SOCKET": null, + "VSCODE_SKIP_PRELAUNCH": "1", + "VSCODE_DEV_DEBUG": "1", }, "cleanUp": "wholeBrowser", "runtimeArgs": [ @@ -568,6 +612,21 @@ "order": 1 } }, + { + "name": "VS Code (Debug Observables)", + "stopAll": true, + "configurations": [ + "Launch VS Code Internal (Dev Debug)", + "Attach to Main Process", + "Attach to Extension Host", + "Attach to Shared Process", + ], + "preLaunchTask": "Ensure Prelaunch Dependencies", + "presentation": { + "group": "0_vscode", + "order": 1 + } + }, { "name": "Search, Renderer, and Main processes", "configurations": [ diff --git a/.vscode/notebooks/api.github-issues b/.vscode/notebooks/api.github-issues index d29f2bc441d4..3a0eaec922fa 100644 --- a/.vscode/notebooks/api.github-issues +++ b/.vscode/notebooks/api.github-issues @@ -7,7 +7,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPO=repo:microsoft/vscode\n$MILESTONE=milestone:\"January 2025\"" + "value": "$REPO=repo:microsoft/vscode\n$MILESTONE=milestone:\"March 2025\"" }, { "kind": 1, diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index d1c128a6d0a7..ca93d5033384 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -7,7 +7,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n\n$MILESTONE=milestone:\"January 2025\"" + "value": "$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\r\n\r\n$MILESTONE=milestone:\"February 2025\"" }, { "kind": 1, @@ -97,7 +97,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE is:issue is:closed reason:completed label:verification-needed -label:verified" + "value": "$REPOS $MILESTONE is:issue is:closed reason:completed label:verification-needed -label:verified -label:on-testplan" }, { "kind": 1, diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index b16f0025f564..0fd05ece4853 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -7,7 +7,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n\n$MILESTONE=milestone:\"January 2025\"\n\n$MINE=assignee:@me" + "value": "$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n\n$MILESTONE=milestone:\"February 2025\"\n\n$MINE=assignee:@me" }, { "kind": 1, @@ -62,7 +62,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:feature-request label:verification-needed -label:verified" + "value": "$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:feature-request label:verification-needed -label:verified -label:on-testplan" }, { "kind": 1, @@ -87,7 +87,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPOS $MILESTONE -$MINE is:issue is:closed reason:completed -assignee:@me -label:verified -label:z-author-verified label:feature-request label:verification-needed -label:verification-steps-needed -label:unreleased" + "value": "$REPOS $MILESTONE -$MINE is:issue is:closed reason:completed -assignee:@me -label:verified -label:z-author-verified label:feature-request label:verification-needed -label:verification-steps-needed -label:unreleased -label:on-testplan" }, { "kind": 1, diff --git a/.vscode/notebooks/my-work.github-issues b/.vscode/notebooks/my-work.github-issues index e8b184f8e573..c7674cef414a 100644 --- a/.vscode/notebooks/my-work.github-issues +++ b/.vscode/notebooks/my-work.github-issues @@ -7,7 +7,7 @@ { "kind": 2, "language": "github-issues", - "value": "// list of repos we work in\n$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n\n// current milestone name\n$MILESTONE=milestone:\"January 2025\"\n" + "value": "// list of repos we work in\n$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n\n// current milestone name\n$MILESTONE=milestone:\"February 2025\"\n" }, { "kind": 1, diff --git a/.vscode/settings.json b/.vscode/settings.json index 29f501a1de83..eb5327bb1814 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -49,6 +49,7 @@ "out-vscode-reh/**": true, "extensions/**/dist/**": true, "extensions/**/out/**": true, + "extensions/terminal-suggest/src/completions/upstream/**": true, "test/smoke/out/**": true, "test/automation/out/**": true, "test/integration/browser/out/**": true @@ -76,6 +77,7 @@ "npm.exclude": "**/extensions/**", "emmet.excludeLanguages": [], "typescript.preferences.importModuleSpecifier": "relative", + "typescript.preferences.importModuleSpecifierEnding": "js", "typescript.preferences.quoteStyle": "single", "json.schemas": [ { @@ -171,4 +173,11 @@ "eslint.useFlatConfig": true, "editor.occurrencesHighlightDelay": 0, "typescript.experimental.expandableHover": true, + "git.diagnosticsCommitHook.Enabled": true, + "git.diagnosticsCommitHook.Sources": { + "*": "error", + "ts": "warning", + "eslint": "warning" + }, + "editor.experimental.preferTreeSitter.typescript": true } diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index a0026469915f..0f17c5ed11bd 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -4,6 +4,34 @@ This repository incorporates material as listed below or described in the code. +--------------------------------------------------------- + +@fig/autocomplete-shared 1.1.2 +https://github.com/withfig/autocomplete-tools + +MIT License + +Copyright (c) 2021 Hercules Labs Inc. (Fig) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +--------------------------------------------------------- + --------------------------------------------------------- @iktakahiro/markdown-it-katex 4.0.2 - MIT @@ -58,6 +86,34 @@ SOFTWARE. --------------------------------------------------------- +amazon-q-developer-cli f66e0b0e917ab185eef528dc36eca56b78ca8b5d +https://github.com/aws/amazon-q-developer-cli + +MIT License + +Copyright (c) 2024 Amazon.com, Inc. or its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +--------------------------------------------------------- + +--------------------------------------------------------- + atom/language-clojure 0.22.8 - MIT https://github.com/atom/language-clojure @@ -468,6 +524,580 @@ Title to copyright in this work will at all times remain with copyright holders. --------------------------------------------------------- +dompurify 3.1.7 - Apache 2.0 +https://github.com/cure53/DOMPurify + +DOMPurify +Copyright 2025 Dr.-Ing. Mario Heiderich, Cure53 + +DOMPurify is free software; you can redistribute it and/or modify it under the +terms of either: + +a) the Apache License Version 2.0, or +b) the Mozilla Public License Version 2.0 + +----------------------------------------------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +----------------------------------------------------------------------------- +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. +--------------------------------------------------------- + +--------------------------------------------------------- + dotnet/csharp-tmLanguage 0.1.0 - MIT https://github.com/dotnet/csharp-tmLanguage @@ -889,7 +1519,7 @@ SOFTWARE. --------------------------------------------------------- -jlelong/vscode-latex-basics 1.9.0 - MIT +jlelong/vscode-latex-basics 1.10.0 - MIT https://github.com/jlelong/vscode-latex-basics Copyright (c) vscode-latex-basics authors @@ -2539,7 +3169,7 @@ Creative Commons may be contacted at creativecommons.org. --------------------------------------------------------- -vscode-logfile-highlighter 2.17.0 - MIT +vscode-logfile-highlighter 3.3.4 - MIT https://github.com/emilast/vscode-logfile-highlighter The MIT License (MIT) diff --git a/build/.moduleignore b/build/.moduleignore index 01541e8c40a0..6b7f365730fe 100644 --- a/build/.moduleignore +++ b/build/.moduleignore @@ -55,6 +55,11 @@ fsevents/test/** @vscode/windows-registry/build/** !@vscode/windows-registry/build/Release/*.node +@vscode/tree-sitter-wasm/wasm/tree-sitter-*.wasm +!@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm +!@vscode/tree-sitter-wasm/wasm/tree-sitter-regex.wasm +!@vscode/tree-sitter-wasm/wasm/tree-sitter-ini.wasm + native-keymap/binding.gyp native-keymap/build/** native-keymap/src/** @@ -130,6 +135,7 @@ vsda/** !@vscode/windows-ca-certs/package.json !@vscode/windows-ca-certs/**/*.node +@vscode/node-addon-api/**/* node-addon-api/**/* prebuild-install/**/* diff --git a/build/.npmrc b/build/.npmrc index 1b073e71a832..551822f79cd6 100644 --- a/build/.npmrc +++ b/build/.npmrc @@ -2,4 +2,5 @@ disturl="https://nodejs.org/dist" runtime="node" build_from_source="true" legacy-peer-deps="true" +force_process_config="true" timeout=180000 diff --git a/build/azure-pipelines/cli/cli-compile.yml b/build/azure-pipelines/cli/cli-compile.yml index 71cd3f71e78b..a5d8bdc1a2c3 100644 --- a/build/azure-pipelines/cli/cli-compile.yml +++ b/build/azure-pipelines/cli/cli-compile.yml @@ -42,7 +42,6 @@ steps: - script: | set -e if [ -n "$SYSROOT_ARCH" ]; then - export VSCODE_SYSROOT_PREFIX='-glibc-2.17' export VSCODE_SYSROOT_DIR=$(Build.SourcesDirectory)/.build/sysroots node -e '(async () => { const { getVSCodeSysroot } = require("../build/linux/debian/install-sysroot.js"); await getVSCodeSysroot(process.env["SYSROOT_ARCH"]); })()' if [ "$SYSROOT_ARCH" == "arm64" ]; then @@ -73,7 +72,7 @@ steps: # verify glibc requirement if [ -n "$SYSROOT_ARCH" ]; then - glibc_version="2.17" + glibc_version="2.28" while IFS= read -r line; do if [[ $line == *"GLIBC_"* ]]; then version=$(echo "$line" | awk '{print $5}' | tr -d '()') @@ -83,8 +82,8 @@ steps: fi fi done < <("$OBJDUMP" -T "$PWD/target/${{ parameters.VSCODE_CLI_TARGET }}/release/code") - if [[ "$glibc_version" != "2.17" ]]; then - echo "Error: binary has dependency on GLIBC > 2.17, found $glibc_version" + if [[ "$glibc_version" != "2.28" ]]; then + echo "Error: binary has dependency on GLIBC > 2.28, found $glibc_version" exit 1 fi fi @@ -120,22 +119,6 @@ steps: ArtifactServices.Symbol.UseAAD: false displayName: Publish Symbols - - task: CopyFiles@2 - inputs: - SourceFolder: $(Build.SourcesDirectory)/cli/target/${{ parameters.VSCODE_CLI_TARGET }}/release - Contents: 'code.*' - TargetFolder: $(Agent.TempDirectory)/binskim-cli - displayName: Copy files for BinSkim - - - task: BinSkim@4 - inputs: - InputType: Basic - Function: analyze - TargetPattern: guardianGlob - AnalyzeTargetGlob: $(Agent.TempDirectory)/binskim-cli/*.* - AnalyzeSymPath: $(Agent.TempDirectory)/binskim-cli - displayName: Run BinSkim - - powershell: | . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" diff --git a/build/azure-pipelines/cli/install-rust-posix.yml b/build/azure-pipelines/cli/install-rust-posix.yml index fee56e028f72..0607cde33e56 100644 --- a/build/azure-pipelines/cli/install-rust-posix.yml +++ b/build/azure-pipelines/cli/install-rust-posix.yml @@ -1,7 +1,7 @@ parameters: - name: channel type: string - default: 1.81 + default: 1.85 - name: targets default: [] type: object diff --git a/build/azure-pipelines/cli/install-rust-win32.yml b/build/azure-pipelines/cli/install-rust-win32.yml index 45a1cfd188e1..bff114fccd07 100644 --- a/build/azure-pipelines/cli/install-rust-win32.yml +++ b/build/azure-pipelines/cli/install-rust-win32.yml @@ -1,7 +1,7 @@ parameters: - name: channel type: string - default: 1.81 + default: 1.85 - name: targets default: [] type: object diff --git a/build/azure-pipelines/common/publish.js b/build/azure-pipelines/common/publish.js index 599f12f47af1..8e052881b2ca 100644 --- a/build/azure-pipelines/common/publish.js +++ b/build/azure-pipelines/common/publish.js @@ -94,7 +94,8 @@ class ESRPReleaseService { requestSigningCertificates; requestSigningKey; containerClient; - static async create(log, tenantId, clientId, authCertificatePfx, requestSigningCertificatePfx, containerClient) { + stagingSasToken; + static async create(log, tenantId, clientId, authCertificatePfx, requestSigningCertificatePfx, containerClient, stagingSasToken) { const authKey = getKeyFromPFX(authCertificatePfx); const authCertificate = getCertificatesFromPFX(authCertificatePfx)[0]; const requestSigningKey = getKeyFromPFX(requestSigningCertificatePfx); @@ -113,16 +114,17 @@ class ESRPReleaseService { const response = await app.acquireTokenByClientCredential({ scopes: ['https://api.esrp.microsoft.com/.default'] }); - return new ESRPReleaseService(log, clientId, response.accessToken, requestSigningCertificates, requestSigningKey, containerClient); + return new ESRPReleaseService(log, clientId, response.accessToken, requestSigningCertificates, requestSigningKey, containerClient, stagingSasToken); } static API_URL = 'https://api.esrp.microsoft.com/api/v3/releaseservices/clients/'; - constructor(log, clientId, accessToken, requestSigningCertificates, requestSigningKey, containerClient) { + constructor(log, clientId, accessToken, requestSigningCertificates, requestSigningKey, containerClient, stagingSasToken) { this.log = log; this.clientId = clientId; this.accessToken = accessToken; this.requestSigningCertificates = requestSigningCertificates; this.requestSigningKey = requestSigningKey; this.containerClient = containerClient; + this.stagingSasToken = stagingSasToken; } async createRelease(version, filePath, friendlyFileName) { const correlationId = crypto_1.default.randomUUID(); @@ -166,6 +168,7 @@ class ESRPReleaseService { async submitRelease(version, filePath, friendlyFileName, correlationId, blobClient) { const size = fs_1.default.statSync(filePath).size; const hash = await hashStream('sha256', fs_1.default.createReadStream(filePath)); + const blobUrl = `${blobClient.url}?${this.stagingSasToken}`; const message = { customerCorrelationId: correlationId, esrpCorrelationId: correlationId, @@ -197,11 +200,11 @@ class ESRPReleaseService { files: [{ name: path_1.default.basename(filePath), friendlyFileName, - tenantFileLocation: blobClient.url, + tenantFileLocation: blobUrl, tenantFileLocationType: 'AzureBlob', sourceLocation: { type: 'azureBlob', - blobUrl: blobClient.url + blobUrl }, hashType: 'sha256', hash: Array.from(hash), @@ -379,7 +382,7 @@ async function unzip(packagePath, outputPath) { }); } // Contains all of the logic for mapping details to our actual product names in CosmosDB -function getPlatform(product, os, arch, type, isLegacy) { +function getPlatform(product, os, arch, type) { switch (os) { case 'win32': switch (product) { @@ -424,12 +427,12 @@ function getPlatform(product, os, arch, type, isLegacy) { case 'client': return `linux-${arch}`; case 'server': - return isLegacy ? `server-linux-legacy-${arch}` : `server-linux-${arch}`; + return `server-linux-${arch}`; case 'web': if (arch === 'standalone') { return 'web-standalone'; } - return isLegacy ? `server-linux-legacy-${arch}-web` : `server-linux-${arch}-web`; + return `server-linux-${arch}-web`; default: throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`); } @@ -542,12 +545,18 @@ async function processArtifact(artifact, filePath) { else { const stagingContainerClient = blobServiceClient.getContainerClient('staging'); await stagingContainerClient.createIfNotExists(); - const releaseService = await ESRPReleaseService.create(log, e('RELEASE_TENANT_ID'), e('RELEASE_CLIENT_ID'), e('RELEASE_AUTH_CERT'), e('RELEASE_REQUEST_SIGNING_CERT'), stagingContainerClient); + const now = new Date().valueOf(); + const oneHour = 60 * 60 * 1000; + const oneHourAgo = new Date(now - oneHour); + const oneHourFromNow = new Date(now + oneHour); + const userDelegationKey = await blobServiceClient.getUserDelegationKey(oneHourAgo, oneHourFromNow); + const sasOptions = { containerName: 'staging', permissions: storage_blob_1.ContainerSASPermissions.from({ read: true }), startsOn: oneHourAgo, expiresOn: oneHourFromNow }; + const stagingSasToken = (0, storage_blob_1.generateBlobSASQueryParameters)(sasOptions, userDelegationKey, e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')).toString(); + const releaseService = await ESRPReleaseService.create(log, e('RELEASE_TENANT_ID'), e('RELEASE_CLIENT_ID'), e('RELEASE_AUTH_CERT'), e('RELEASE_REQUEST_SIGNING_CERT'), stagingContainerClient, stagingSasToken); await releaseService.createRelease(version, filePath, friendlyFileName); } const { product, os, arch, unprocessedType } = match.groups; - const isLegacy = artifact.name.includes('_legacy'); - const platform = getPlatform(product, os, arch, unprocessedType, isLegacy); + const platform = getPlatform(product, os, arch, unprocessedType); const type = getRealType(unprocessedType); const size = fs_1.default.statSync(filePath).size; const stream = fs_1.default.createReadStream(filePath); @@ -587,16 +596,19 @@ async function main() { for (const name of done) { console.log(`\u2705 ${name}`); } - const stages = new Set(['Compile', 'CompileCLI']); + const stages = new Set(['Compile']); + if (e('VSCODE_BUILD_STAGE_LINUX') === 'True' || + e('VSCODE_BUILD_STAGE_ALPINE') === 'True' || + e('VSCODE_BUILD_STAGE_MACOS') === 'True' || + e('VSCODE_BUILD_STAGE_WINDOWS') === 'True') { + stages.add('CompileCLI'); + } if (e('VSCODE_BUILD_STAGE_WINDOWS') === 'True') { stages.add('Windows'); } if (e('VSCODE_BUILD_STAGE_LINUX') === 'True') { stages.add('Linux'); } - if (e('VSCODE_BUILD_STAGE_LINUX_LEGACY_SERVER') === 'True') { - stages.add('LinuxLegacyServer'); - } if (e('VSCODE_BUILD_STAGE_ALPINE') === 'True') { stages.add('Alpine'); } diff --git a/build/azure-pipelines/common/publish.ts b/build/azure-pipelines/common/publish.ts index 39d189c05faa..37bf5ccc6cd3 100644 --- a/build/azure-pipelines/common/publish.ts +++ b/build/azure-pipelines/common/publish.ts @@ -16,7 +16,7 @@ import cp from 'child_process'; import os from 'os'; import { Worker, isMainThread, workerData } from 'node:worker_threads'; import { ConfidentialClientApplication } from '@azure/msal-node'; -import { BlobClient, BlobServiceClient, BlockBlobClient, ContainerClient } from '@azure/storage-blob'; +import { BlobClient, BlobServiceClient, BlockBlobClient, ContainerClient, ContainerSASPermissions, generateBlobSASQueryParameters } from '@azure/storage-blob'; import jws from 'jws'; import { clearInterval, setInterval } from 'node:timers'; @@ -320,7 +320,8 @@ class ESRPReleaseService { clientId: string, authCertificatePfx: string, requestSigningCertificatePfx: string, - containerClient: ContainerClient + containerClient: ContainerClient, + stagingSasToken: string ) { const authKey = getKeyFromPFX(authCertificatePfx); const authCertificate = getCertificatesFromPFX(authCertificatePfx)[0]; @@ -343,7 +344,7 @@ class ESRPReleaseService { scopes: ['https://api.esrp.microsoft.com/.default'] }); - return new ESRPReleaseService(log, clientId, response!.accessToken, requestSigningCertificates, requestSigningKey, containerClient); + return new ESRPReleaseService(log, clientId, response!.accessToken, requestSigningCertificates, requestSigningKey, containerClient, stagingSasToken); } private static API_URL = 'https://api.esrp.microsoft.com/api/v3/releaseservices/clients/'; @@ -354,7 +355,8 @@ class ESRPReleaseService { private readonly accessToken: string, private readonly requestSigningCertificates: string[], private readonly requestSigningKey: string, - private readonly containerClient: ContainerClient + private readonly containerClient: ContainerClient, + private readonly stagingSasToken: string ) { } async createRelease(version: string, filePath: string, friendlyFileName: string) { @@ -411,6 +413,7 @@ class ESRPReleaseService { ): Promise { const size = fs.statSync(filePath).size; const hash = await hashStream('sha256', fs.createReadStream(filePath)); + const blobUrl = `${blobClient.url}?${this.stagingSasToken}`; const message: ReleaseRequestMessage = { customerCorrelationId: correlationId, @@ -443,11 +446,11 @@ class ESRPReleaseService { files: [{ name: path.basename(filePath), friendlyFileName, - tenantFileLocation: blobClient.url, + tenantFileLocation: blobUrl, tenantFileLocationType: 'AzureBlob', sourceLocation: { type: 'azureBlob', - blobUrl: blobClient.url + blobUrl }, hashType: 'sha256', hash: Array.from(hash), @@ -691,7 +694,7 @@ interface Asset { } // Contains all of the logic for mapping details to our actual product names in CosmosDB -function getPlatform(product: string, os: string, arch: string, type: string, isLegacy: boolean): string { +function getPlatform(product: string, os: string, arch: string, type: string): string { switch (os) { case 'win32': switch (product) { @@ -736,12 +739,12 @@ function getPlatform(product: string, os: string, arch: string, type: string, is case 'client': return `linux-${arch}`; case 'server': - return isLegacy ? `server-linux-legacy-${arch}` : `server-linux-${arch}`; + return `server-linux-${arch}`; case 'web': if (arch === 'standalone') { return 'web-standalone'; } - return isLegacy ? `server-linux-legacy-${arch}-web` : `server-linux-${arch}-web`; + return `server-linux-${arch}-web`; default: throw new Error(`Unrecognized: ${product} ${os} ${arch} ${type}`); } @@ -871,21 +874,29 @@ async function processArtifact( const stagingContainerClient = blobServiceClient.getContainerClient('staging'); await stagingContainerClient.createIfNotExists(); + const now = new Date().valueOf(); + const oneHour = 60 * 60 * 1000; + const oneHourAgo = new Date(now - oneHour); + const oneHourFromNow = new Date(now + oneHour); + const userDelegationKey = await blobServiceClient.getUserDelegationKey(oneHourAgo, oneHourFromNow); + const sasOptions = { containerName: 'staging', permissions: ContainerSASPermissions.from({ read: true }), startsOn: oneHourAgo, expiresOn: oneHourFromNow }; + const stagingSasToken = generateBlobSASQueryParameters(sasOptions, userDelegationKey, e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')).toString(); + const releaseService = await ESRPReleaseService.create( log, e('RELEASE_TENANT_ID'), e('RELEASE_CLIENT_ID'), e('RELEASE_AUTH_CERT'), e('RELEASE_REQUEST_SIGNING_CERT'), - stagingContainerClient + stagingContainerClient, + stagingSasToken ); await releaseService.createRelease(version, filePath, friendlyFileName); } const { product, os, arch, unprocessedType } = match.groups!; - const isLegacy = artifact.name.includes('_legacy'); - const platform = getPlatform(product, os, arch, unprocessedType, isLegacy); + const platform = getPlatform(product, os, arch, unprocessedType); const type = getRealType(unprocessedType); const size = fs.statSync(filePath).size; const stream = fs.createReadStream(filePath); @@ -931,10 +942,19 @@ async function main() { console.log(`\u2705 ${name}`); } - const stages = new Set(['Compile', 'CompileCLI']); + const stages = new Set(['Compile']); + + if ( + e('VSCODE_BUILD_STAGE_LINUX') === 'True' || + e('VSCODE_BUILD_STAGE_ALPINE') === 'True' || + e('VSCODE_BUILD_STAGE_MACOS') === 'True' || + e('VSCODE_BUILD_STAGE_WINDOWS') === 'True' + ) { + stages.add('CompileCLI'); + } + if (e('VSCODE_BUILD_STAGE_WINDOWS') === 'True') { stages.add('Windows'); } if (e('VSCODE_BUILD_STAGE_LINUX') === 'True') { stages.add('Linux'); } - if (e('VSCODE_BUILD_STAGE_LINUX_LEGACY_SERVER') === 'True') { stages.add('LinuxLegacyServer'); } if (e('VSCODE_BUILD_STAGE_ALPINE') === 'True') { stages.add('Alpine'); } if (e('VSCODE_BUILD_STAGE_MACOS') === 'True') { stages.add('macOS'); } if (e('VSCODE_BUILD_STAGE_WEB') === 'True') { stages.add('Web'); } diff --git a/build/azure-pipelines/darwin/product-build-darwin-sign.yml b/build/azure-pipelines/darwin/product-build-darwin-sign.yml index 8ae5c217db8e..dffb6665d999 100644 --- a/build/azure-pipelines/darwin/product-build-darwin-sign.yml +++ b/build/azure-pipelines/darwin/product-build-darwin-sign.yml @@ -21,6 +21,25 @@ steps: Pattern: noop displayName: 'Install ESRP Tooling' + - script: | + # For legacy purposes, arch for x64 is just 'darwin' + case $VSCODE_ARCH in + x64) ASSET_ID="darwin" ;; + arm64) ASSET_ID="darwin-arm64" ;; + universal) ASSET_ID="darwin-universal" ;; + esac + echo "##vso[task.setvariable variable=ASSET_ID]$ASSET_ID" + displayName: Set asset id variable + + - script: | + if [ -z "$(ASSET_ID)" ]; then + echo "ASSET_ID is empty" + exit 1 + else + echo "ASSET_ID is set to $(ASSET_ID)" + fi + displayName: Check ASSET_ID variable + - download: current artifact: unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive displayName: Download $(VSCODE_ARCH) artifact @@ -48,16 +67,6 @@ steps: displayName: Verify signature condition: and(succeeded(), ne(variables['VSCODE_ARCH'], 'arm64')) - - script: | - # For legacy purposes, arch for x64 is just 'darwin' - case $VSCODE_ARCH in - x64) ASSET_ID="darwin" ;; - arm64) ASSET_ID="darwin-arm64" ;; - universal) ASSET_ID="darwin-universal" ;; - esac - echo "##vso[task.setvariable variable=ASSET_ID]$ASSET_ID" - displayName: Set asset id variable - - script: mv $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin-x64.zip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin.zip displayName: Rename x64 build to its legacy name condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) diff --git a/build/azure-pipelines/linux/product-build-linux-legacy-server.yml b/build/azure-pipelines/linux/product-build-linux-legacy-server.yml deleted file mode 100644 index 4c26baf2f999..000000000000 --- a/build/azure-pipelines/linux/product-build-linux-legacy-server.yml +++ /dev/null @@ -1,233 +0,0 @@ -parameters: - - name: VSCODE_QUALITY - type: string - - name: VSCODE_RUN_INTEGRATION_TESTS - type: boolean - - name: VSCODE_ARCH - type: string - -steps: - - task: NodeTool@0 - inputs: - versionSource: fromFile - versionFilePath: .nvmrc - nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download - - - template: ../distro/download-distro.yml - - - task: AzureKeyVault@2 - displayName: "Azure Key Vault: Get Secrets" - inputs: - azureSubscription: vscode - KeyVaultName: vscode-build-secrets - SecretsFilter: "github-distro-mixin-password" - - - task: DownloadPipelineArtifact@2 - inputs: - artifact: Compilation - path: $(Build.ArtifactStagingDirectory) - displayName: Download compilation output - - - script: tar -xzf $(Build.ArtifactStagingDirectory)/compilation.tar.gz - displayName: Extract compilation output - - - script: | - set -e - # Start X server - ./build/azure-pipelines/linux/apt-retry.sh sudo apt-get update - ./build/azure-pipelines/linux/apt-retry.sh sudo apt-get install -y pkg-config \ - dbus \ - xvfb \ - libgtk-3-0 \ - libxkbfile-dev \ - libkrb5-dev \ - libgbm1 \ - rpm \ - gcc-10 \ - g++-10 - sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start - # Start dbus session - sudo mkdir -p /var/run/dbus - DBUS_LAUNCH_RESULT=$(sudo dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address) - echo "##vso[task.setvariable variable=DBUS_SESSION_BUS_ADDRESS]$DBUS_LAUNCH_RESULT" - displayName: Setup system services - - - script: node build/setup-npm-registry.js $NPM_REGISTRY - condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none')) - displayName: Setup NPM Registry - - - script: | - set -e - # Set the private NPM registry to the global npmrc file - # so that authentication works for subfolders like build/, remote/, extensions/ etc - # which does not have their own .npmrc file - npm config set registry "$NPM_REGISTRY" - echo "##vso[task.setvariable variable=NPMRC_PATH]$(npm config get userconfig)" - condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none')) - displayName: Setup NPM - - - task: npmAuthenticate@0 - inputs: - workingFile: $(NPMRC_PATH) - condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none')) - displayName: Setup NPM Authentication - - - ${{ if or(eq(parameters.VSCODE_ARCH, 'x64'), eq(parameters.VSCODE_ARCH, 'arm64')) }}: - - task: Docker@1 - displayName: "Pull Docker image" - inputs: - azureSubscriptionEndpoint: vscode - azureContainerRegistry: vscodehub.azurecr.io - command: "Run an image" - imageName: vscode-linux-build-agent:centos7-devtoolset8-$(VSCODE_ARCH) - containerCommand: uname - - - script: | - set -e - - for i in {1..5}; do # try 5 times - npm ci && break - if [ $i -eq 5 ]; then - echo "Npm install failed too many times" >&2 - exit 1 - fi - echo "Npm install failed $i, trying again..." - done - workingDirectory: build - env: - GITHUB_TOKEN: "$(github-distro-mixin-password)" - displayName: Install build dependencies - - - script: | - set -e - - export VSCODE_SYSROOT_PREFIX='-glibc-2.17' - export CC=$(which gcc-10) - export CXX=$(which g++-10) - source ./build/azure-pipelines/linux/setup-env.sh --skip-sysroot - - for i in {1..5}; do # try 5 times - npm ci && break - if [ $i -eq 5 ]; then - echo "Npm install failed too many times" >&2 - exit 1 - fi - echo "Npm install failed $i, trying again..." - done - env: - npm_config_arch: $(NPM_ARCH) - VSCODE_ARCH: $(VSCODE_ARCH) - NPM_REGISTRY: "$(NPM_REGISTRY)" - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - GITHUB_TOKEN: "$(github-distro-mixin-password)" - VSCODE_HOST_MOUNT: "/mnt/vss/_work/1/s" - ${{ if or(eq(parameters.VSCODE_ARCH, 'x64'), eq(parameters.VSCODE_ARCH, 'arm64')) }}: - VSCODE_REMOTE_DEPENDENCIES_CONTAINER_NAME: vscodehub.azurecr.io/vscode-linux-build-agent:centos7-devtoolset8-$(VSCODE_ARCH) - displayName: Install dependencies - - - script: node build/azure-pipelines/distro/mixin-npm - displayName: Mixin distro node modules - - - script: node build/azure-pipelines/distro/mixin-quality - displayName: Mixin distro quality - - - template: ../common/install-builtin-extensions.yml - - - script: | - set -e - npm run gulp vscode-linux-$(VSCODE_ARCH)-min-ci - ARCHIVE_PATH=".build/linux/client/code-${{ parameters.VSCODE_QUALITY }}-$(VSCODE_ARCH)-$(date +%s).tar.gz" - mkdir -p $(dirname $ARCHIVE_PATH) - echo "##vso[task.setvariable variable=CLIENT_PATH]$ARCHIVE_PATH" - env: - GITHUB_TOKEN: "$(github-distro-mixin-password)" - displayName: Build client - - - script: | - set -e - tar -czf $CLIENT_PATH -C .. VSCode-linux-$(VSCODE_ARCH) - env: - GITHUB_TOKEN: "$(github-distro-mixin-password)" - displayName: Archive client - - - script: | - set -e - export VSCODE_NODE_GLIBC="-glibc-2.17" - npm run gulp vscode-reh-linux-$(VSCODE_ARCH)-min-ci - mv ../vscode-reh-linux-$(VSCODE_ARCH) ../vscode-server-linux-$(VSCODE_ARCH) # TODO@joaomoreno - ARCHIVE_PATH=".build/linux/server/vscode-server-linux-legacy-$(VSCODE_ARCH).tar.gz" - UNARCHIVE_PATH="`pwd`/../vscode-server-linux-$(VSCODE_ARCH)" - mkdir -p $(dirname $ARCHIVE_PATH) - tar --owner=0 --group=0 -czf $ARCHIVE_PATH -C .. vscode-server-linux-$(VSCODE_ARCH) - echo "##vso[task.setvariable variable=SERVER_PATH]$ARCHIVE_PATH" - echo "##vso[task.setvariable variable=SERVER_UNARCHIVE_PATH]$UNARCHIVE_PATH" - env: - GITHUB_TOKEN: "$(github-distro-mixin-password)" - displayName: Build server - - - script: | - set -e - export VSCODE_NODE_GLIBC="-glibc-2.17" - npm run gulp vscode-reh-web-linux-$(VSCODE_ARCH)-min-ci - mv ../vscode-reh-web-linux-$(VSCODE_ARCH) ../vscode-server-linux-$(VSCODE_ARCH)-web # TODO@joaomoreno - ARCHIVE_PATH=".build/linux/web/vscode-server-linux-legacy-$(VSCODE_ARCH)-web.tar.gz" - mkdir -p $(dirname $ARCHIVE_PATH) - tar --owner=0 --group=0 -czf $ARCHIVE_PATH -C .. vscode-server-linux-$(VSCODE_ARCH)-web - echo "##vso[task.setvariable variable=WEB_PATH]$ARCHIVE_PATH" - env: - GITHUB_TOKEN: "$(github-distro-mixin-password)" - displayName: Build server (web) - - - ${{ if or(eq(parameters.VSCODE_ARCH, 'x64'), eq(parameters.VSCODE_ARCH, 'arm64')) }}: - - script: | - set -e - EXPECTED_GLIBC_VERSION="2.17" \ - EXPECTED_GLIBCXX_VERSION="3.4.19" \ - ./build/azure-pipelines/linux/verify-glibc-requirements.sh - env: - SEARCH_PATH: $(SERVER_UNARCHIVE_PATH) - displayName: Check GLIBC and GLIBCXX dependencies in server archive - - - ${{ else }}: - - script: | - set -e - EXPECTED_GLIBC_VERSION="2.17" \ - EXPECTED_GLIBCXX_VERSION="3.4.22" \ - ./build/azure-pipelines/linux/verify-glibc-requirements.sh - env: - SEARCH_PATH: $(SERVER_UNARCHIVE_PATH) - displayName: Check GLIBC and GLIBCXX dependencies in server archive - - - ${{ if eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true) }}: - - template: product-build-linux-test.yml - parameters: - VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }} - VSCODE_RUN_UNIT_TESTS: false - VSCODE_RUN_INTEGRATION_TESTS: ${{ parameters.VSCODE_RUN_INTEGRATION_TESTS }} - VSCODE_RUN_SMOKE_TESTS: false - ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}: - PUBLISH_TASK_NAME: 1ES.PublishPipelineArtifact@1 - - - task: 1ES.PublishPipelineArtifact@1 - inputs: - targetPath: $(SERVER_PATH) - artifactName: $(ARTIFACT_PREFIX)vscode_server_linux_legacy_$(VSCODE_ARCH)_archive-unsigned - sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-server-linux-$(VSCODE_ARCH) - sbomPackageName: "VS Code Linux $(VSCODE_ARCH) Legacy Server" - sbomPackageVersion: $(Build.SourceVersion) - condition: and(succeededOrFailed(), ne(variables['SERVER_PATH'], '')) - displayName: Publish server archive - - - task: 1ES.PublishPipelineArtifact@1 - inputs: - targetPath: $(WEB_PATH) - artifactName: $(ARTIFACT_PREFIX)vscode_web_linux_legacy_$(VSCODE_ARCH)_archive-unsigned - sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-server-linux-$(VSCODE_ARCH)-web - sbomPackageName: "VS Code Linux $(VSCODE_ARCH) Legacy Web" - sbomPackageVersion: $(Build.SourceVersion) - condition: and(succeededOrFailed(), ne(variables['WEB_PATH'], '')) - displayName: Publish web server archive diff --git a/build/azure-pipelines/linux/setup-env.sh b/build/azure-pipelines/linux/setup-env.sh index d836fb70fb0a..94105642b190 100755 --- a/build/azure-pipelines/linux/setup-env.sh +++ b/build/azure-pipelines/linux/setup-env.sh @@ -16,56 +16,50 @@ else fi if [ "$npm_config_arch" == "x64" ]; then - # Download clang based on chromium revision used by vscode - curl -s https://raw.githubusercontent.com/chromium/chromium/128.0.6613.186/tools/clang/scripts/update.py | python - --output-dir=$PWD/.build/CR_Clang --host-os=linux + # Download clang based on chromium revision used by vscode + curl -s https://raw.githubusercontent.com/chromium/chromium/132.0.6834.210/tools/clang/scripts/update.py | python - --output-dir=$PWD/.build/CR_Clang --host-os=linux - # Download libcxx headers and objects from upstream electron releases - DEBUG=libcxx-fetcher \ - VSCODE_LIBCXX_OBJECTS_DIR=$PWD/.build/libcxx-objects \ - VSCODE_LIBCXX_HEADERS_DIR=$PWD/.build/libcxx_headers \ - VSCODE_LIBCXXABI_HEADERS_DIR=$PWD/.build/libcxxabi_headers \ - VSCODE_ARCH="$npm_config_arch" \ - node build/linux/libcxx-fetcher.js + # Download libcxx headers and objects from upstream electron releases + DEBUG=libcxx-fetcher \ + VSCODE_LIBCXX_OBJECTS_DIR=$PWD/.build/libcxx-objects \ + VSCODE_LIBCXX_HEADERS_DIR=$PWD/.build/libcxx_headers \ + VSCODE_LIBCXXABI_HEADERS_DIR=$PWD/.build/libcxxabi_headers \ + VSCODE_ARCH="$npm_config_arch" \ + node build/linux/libcxx-fetcher.js - # Set compiler toolchain - # Flags for the client build are based on - # https://source.chromium.org/chromium/chromium/src/+/refs/tags/128.0.6613.186:build/config/arm.gni - # https://source.chromium.org/chromium/chromium/src/+/refs/tags/128.0.6613.186:build/config/compiler/BUILD.gn - # https://source.chromium.org/chromium/chromium/src/+/refs/tags/128.0.6613.186:build/config/c++/BUILD.gn - export CC="$PWD/.build/CR_Clang/bin/clang --gcc-toolchain=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu" - export CXX="$PWD/.build/CR_Clang/bin/clang++ --gcc-toolchain=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu" - export CXXFLAGS="-nostdinc++ -D__NO_INLINE__ -I$PWD/.build/libcxx_headers -isystem$PWD/.build/libcxx_headers/include -isystem$PWD/.build/libcxxabi_headers/include -fPIC -flto=thin -fsplit-lto-unit -D_LIBCPP_ABI_NAMESPACE=Cr -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE --sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot" - export LDFLAGS="-stdlib=libc++ --sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot -fuse-ld=lld -flto=thin -L$PWD/.build/libcxx-objects -lc++abi -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/usr/lib/x86_64-linux-gnu -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib/x86_64-linux-gnu -Wl,--lto-O0" + # Set compiler toolchain + # Flags for the client build are based on + # https://source.chromium.org/chromium/chromium/src/+/refs/tags/132.0.6834.210:build/config/arm.gni + # https://source.chromium.org/chromium/chromium/src/+/refs/tags/132.0.6834.210:build/config/compiler/BUILD.gn + # https://source.chromium.org/chromium/chromium/src/+/refs/tags/132.0.6834.210:build/config/c++/BUILD.gn + export CC="$PWD/.build/CR_Clang/bin/clang --gcc-toolchain=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu" + export CXX="$PWD/.build/CR_Clang/bin/clang++ --gcc-toolchain=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu" + export CXXFLAGS="-nostdinc++ -D__NO_INLINE__ -DSPDLOG_USE_STD_FORMAT -I$PWD/.build/libcxx_headers -isystem$PWD/.build/libcxx_headers/include -isystem$PWD/.build/libcxxabi_headers/include -fPIC -flto=thin -fsplit-lto-unit -D_LIBCPP_ABI_NAMESPACE=Cr -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE --sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot" + export LDFLAGS="-stdlib=libc++ --sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot -fuse-ld=lld -flto=thin -L$PWD/.build/libcxx-objects -lc++abi -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/usr/lib/x86_64-linux-gnu -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib/x86_64-linux-gnu -Wl,--lto-O0" - if [ "$(echo "$@" | grep -c -- "--skip-sysroot")" -eq 0 ]; then - # Set compiler toolchain for remote server - export VSCODE_REMOTE_CC=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/bin/x86_64-linux-gnu-gcc - export VSCODE_REMOTE_CXX=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/bin/x86_64-linux-gnu-g++ - export VSCODE_REMOTE_CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot" - export VSCODE_REMOTE_LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/usr/lib/x86_64-linux-gnu -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib/x86_64-linux-gnu" - fi + # Set compiler toolchain for remote server + export VSCODE_REMOTE_CC=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/bin/x86_64-linux-gnu-gcc + export VSCODE_REMOTE_CXX=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/bin/x86_64-linux-gnu-g++ + export VSCODE_REMOTE_CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot" + export VSCODE_REMOTE_LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/usr/lib/x86_64-linux-gnu -L$VSCODE_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib/x86_64-linux-gnu" elif [ "$npm_config_arch" == "arm64" ]; then - if [ "$(echo "$@" | grep -c -- "--skip-sysroot")" -eq 0 ]; then - # Set compiler toolchain for client native modules - export CC=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc - export CXX=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-g++ - export CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot" - export LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/usr/lib/aarch64-linux-gnu -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/lib/aarch64-linux-gnu" + # Set compiler toolchain for client native modules + export CC=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc + export CXX=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-g++ + export CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot" + export LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/usr/lib/aarch64-linux-gnu -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/lib/aarch64-linux-gnu" - # Set compiler toolchain for remote server - export VSCODE_REMOTE_CC=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc - export VSCODE_REMOTE_CXX=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-g++ - export VSCODE_REMOTE_CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot" - export VSCODE_REMOTE_LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/usr/lib/aarch64-linux-gnu -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/lib/aarch64-linux-gnu" - fi + # Set compiler toolchain for remote server + export VSCODE_REMOTE_CC=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc + export VSCODE_REMOTE_CXX=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/bin/aarch64-linux-gnu-g++ + export VSCODE_REMOTE_CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot" + export VSCODE_REMOTE_LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/usr/lib/aarch64-linux-gnu -L$VSCODE_SYSROOT_DIR/aarch64-linux-gnu/aarch64-linux-gnu/sysroot/lib/aarch64-linux-gnu" elif [ "$npm_config_arch" == "arm" ]; then - if [ "$(echo "$@" | grep -c -- "--skip-sysroot")" -eq 0 ]; then - # Set compiler toolchain for client native modules - export CC=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-gcc - export CXX=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-g++ - export CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot" - export LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot -L$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot/usr/lib/arm-linux-gnueabihf -L$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot/lib/arm-linux-gnueabihf" - fi + # Set compiler toolchain for client native modules + export CC=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-gcc + export CXX=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-g++ + export CXXFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot" + export LDFLAGS="--sysroot=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot -L$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot/usr/lib/arm-linux-gnueabihf -L$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/arm-rpi-linux-gnueabihf/sysroot/lib/arm-linux-gnueabihf" # Set compiler toolchain for remote server export VSCODE_REMOTE_CC=$VSCODE_SYSROOT_DIR/arm-rpi-linux-gnueabihf/bin/arm-rpi-linux-gnueabihf-gcc diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index ee7dcb99eeab..c3e1342359ab 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -8,6 +8,7 @@ schedules: - main trigger: + batch: true branches: include: ["main", "release/*"] @@ -40,26 +41,14 @@ parameters: displayName: "🎯 Linux x64" type: boolean default: true - - name: VSCODE_BUILD_LINUX_X64_LEGACY_SERVER - displayName: "🎯 Linux x64 Legacy Server" - type: boolean - default: true - name: VSCODE_BUILD_LINUX_ARM64 displayName: "🎯 Linux arm64" type: boolean default: true - - name: VSCODE_BUILD_LINUX_ARM64_LEGACY_SERVER - displayName: "🎯 Linux arm64 Legacy Server" - type: boolean - default: true - name: VSCODE_BUILD_LINUX_ARMHF displayName: "🎯 Linux armhf" type: boolean default: true - - name: VSCODE_BUILD_LINUX_ARMHF_LEGACY_SERVER - displayName: "🎯 Linux armhf Legacy Server" - type: boolean - default: true - name: VSCODE_BUILD_ALPINE displayName: "🎯 Alpine x64" type: boolean @@ -105,7 +94,10 @@ variables: - name: VSCODE_PRIVATE_BUILD value: ${{ ne(variables['Build.Repository.Uri'], 'https://github.com/microsoft/vscode.git') }} - name: NPM_REGISTRY - value: ${{ parameters.NPM_REGISTRY }} + ${{ if in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI') }}: # disable terrapin when in VSCODE_CIBUILD + value: none + ${{ else }}: + value: ${{ parameters.NPM_REGISTRY }} - name: CARGO_REGISTRY value: ${{ parameters.CARGO_REGISTRY }} - name: VSCODE_QUALITY @@ -114,8 +106,6 @@ variables: value: ${{ or(eq(parameters.VSCODE_BUILD_WIN32, true), eq(parameters.VSCODE_BUILD_WIN32_ARM64, true)) }} - name: VSCODE_BUILD_STAGE_LINUX value: ${{ or(eq(parameters.VSCODE_BUILD_LINUX, true), eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true), eq(parameters.VSCODE_BUILD_LINUX_ARM64, true)) }} - - name: VSCODE_BUILD_STAGE_LINUX_LEGACY_SERVER - value: ${{ or(eq(parameters.VSCODE_BUILD_LINUX_X64_LEGACY_SERVER, true), eq(parameters.VSCODE_BUILD_LINUX_ARMHF_LEGACY_SERVER, true), eq(parameters.VSCODE_BUILD_LINUX_ARM64_LEGACY_SERVER, true)) }} - name: VSCODE_BUILD_STAGE_ALPINE value: ${{ or(eq(parameters.VSCODE_BUILD_ALPINE, true), eq(parameters.VSCODE_BUILD_ALPINE_ARM64, true)) }} - name: VSCODE_BUILD_STAGE_MACOS @@ -128,8 +118,6 @@ variables: value: ${{ and(eq(parameters.VSCODE_PUBLISH, true), eq(variables.VSCODE_CIBUILD, false), eq(parameters.VSCODE_COMPILE_ONLY, false)) }} - name: VSCODE_SCHEDULEDBUILD value: ${{ eq(variables['Build.Reason'], 'Schedule') }} - - name: VSCODE_7PM_BUILD - value: ${{ in(variables['Build.Reason'], 'BuildCompletion', 'ResourceTrigger') }} - name: VSCODE_STEP_ON_IT value: ${{ eq(parameters.VSCODE_STEP_ON_IT, true) }} - name: VSCODE_BUILD_MACOS_UNIVERSAL @@ -181,6 +169,8 @@ extends: tsa: enabled: true configFile: $(Build.SourcesDirectory)/build/azure-pipelines/config/tsaoptions.json + binskim: + analyzeTargetGlob: '+:file|$(Agent.BuildDirectory)/VSCode-*/**/*.exe;+:file|$(Agent.BuildDirectory)/VSCode-*/**/*.node;+:file|$(Agent.BuildDirectory)/VSCode-*/**/*.dll;-:file|**/VSCodeSetup*.exe' codeql: runSourceLanguagesInSourceAnalysis: true compiled: @@ -199,20 +189,16 @@ extends: image: vscodehub.azurecr.io/vscode-linux-build-agent:snapcraft-x64 ubuntu-2004-arm64: image: onebranch.azurecr.io/linux/ubuntu-2004-arm64:latest - authenticatedContainerRegistries: - - registry: onebranch.azurecr.io - tenant: AME - identity: 1ESPipelineIdentity stages: - stage: Compile jobs: - job: Compile timeoutInMinutes: 90 pool: - name: 1es-ubuntu-22.04-x64 - os: linux + name: AcesShared + os: macOS variables: - VSCODE_ARCH: x64 + VSCODE_ARCH: arm64 steps: - template: build/azure-pipelines/product-compile.yml@self parameters: @@ -264,6 +250,11 @@ extends: os: linux hostArchitecture: arm64 container: ubuntu-2004-arm64 + templateContext: + authenticatedContainerRegistries: + - registry: onebranch.azurecr.io + tenant: AME + identity: 1ESPipelineIdentity steps: - template: build/azure-pipelines/alpine/cli-build-alpine.yml@self parameters: @@ -276,6 +267,10 @@ extends: name: Azure Pipelines image: macOS-13 os: macOS + variables: + # todo@connor4312 to diagnose build flakes + - name: MSRUSTUP_LOG + value: debug steps: - template: build/azure-pipelines/darwin/cli-build-darwin.yml@self parameters: @@ -289,6 +284,10 @@ extends: name: Azure Pipelines image: macOS-13 os: macOS + variables: + # todo@connor4312 to diagnose build flakes + - name: MSRUSTUP_LOG + value: debug steps: - template: build/azure-pipelines/darwin/cli-build-darwin.yml@self parameters: @@ -319,13 +318,13 @@ extends: VSCODE_BUILD_WIN32_ARM64: ${{ parameters.VSCODE_BUILD_WIN32_ARM64 }} - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_COMPILE_ONLY, false)) }}: - - stage: CustomSDL + - stage: APIScan dependsOn: [] pool: name: 1es-windows-2019-x64 os: windows jobs: - - job: WindowsSDL + - job: WindowsAPIScan steps: - template: build/azure-pipelines/win32/sdl-scan-win32.yml@self parameters: @@ -506,6 +505,11 @@ extends: container: snapcraft variables: VSCODE_ARCH: x64 + templateContext: + authenticatedContainerRegistries: + - registry: onebranch.azurecr.io + tenant: AME + identity: 1ESPipelineIdentity steps: - template: build/azure-pipelines/linux/snap-build-linux.yml@self @@ -539,51 +543,6 @@ extends: VSCODE_RUN_INTEGRATION_TESTS: false VSCODE_RUN_SMOKE_TESTS: false - - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_LINUX_LEGACY_SERVER'], true)) }}: - - stage: LinuxLegacyServer - dependsOn: - - Compile - pool: - name: 1es-ubuntu-20.04-x64 - os: linux - jobs: - - ${{ if eq(parameters.VSCODE_BUILD_LINUX_X64_LEGACY_SERVER, true) }}: - - job: Linuxx64LegacyServer - variables: - VSCODE_ARCH: x64 - NPM_ARCH: x64 - DISPLAY: ":10" - steps: - - template: build/azure-pipelines/linux/product-build-linux-legacy-server.yml@self - parameters: - VSCODE_ARCH: x64 - VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} - VSCODE_RUN_INTEGRATION_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }} - - - ${{ if eq(parameters.VSCODE_BUILD_LINUX_ARMHF_LEGACY_SERVER, true) }}: - - job: LinuxArmhfLegacyServer - variables: - VSCODE_ARCH: armhf - NPM_ARCH: arm - steps: - - template: build/azure-pipelines/linux/product-build-linux-legacy-server.yml@self - parameters: - VSCODE_ARCH: armhf - VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} - VSCODE_RUN_INTEGRATION_TESTS: false - - - ${{ if eq(parameters.VSCODE_BUILD_LINUX_ARM64_LEGACY_SERVER, true) }}: - - job: LinuxArm64LegacyServer - variables: - VSCODE_ARCH: arm64 - NPM_ARCH: arm64 - steps: - - template: build/azure-pipelines/linux/product-build-linux-legacy-server.yml@self - parameters: - VSCODE_ARCH: arm64 - VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} - VSCODE_RUN_INTEGRATION_TESTS: false - - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_ALPINE'], true)) }}: - stage: Alpine dependsOn: diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index ea71c18ff7d9..6096157ad8d5 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -23,7 +23,7 @@ steps: condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none')) displayName: Setup NPM Registry - - script: mkdir -p .build && node build/azure-pipelines/common/computeNodeModulesCacheKey.js compile > .build/packagelockhash + - script: mkdir -p .build && node build/azure-pipelines/common/computeNodeModulesCacheKey.js compile $VSCODE_ARCH > .build/packagelockhash displayName: Prepare node_modules cache key - task: Cache@2 @@ -53,9 +53,10 @@ steps: condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none')) displayName: Setup NPM Authentication - - script: sudo apt update -y && sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libnotify-bin libkrb5-dev - displayName: Install build tools - condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) + - ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}: + - script: sudo apt update -y && sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libnotify-bin libkrb5-dev + displayName: Install build tools + condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) - script: | set -e @@ -103,12 +104,12 @@ steps: - template: common/install-builtin-extensions.yml@self - ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}: - - script: npm exec -- npm-run-all -lp core-ci-pr extensions-ci-pr hygiene eslint valid-layers-check vscode-dts-compile-check tsec-compile-check + - script: npm exec -- npm-run-all -lp core-ci-pr extensions-ci-pr hygiene eslint valid-layers-check property-init-order-check vscode-dts-compile-check tsec-compile-check env: GITHUB_TOKEN: "$(github-distro-mixin-password)" displayName: Compile & Hygiene (OSS) - ${{ else }}: - - script: npm exec -- npm-run-all -lp core-ci extensions-ci hygiene eslint valid-layers-check vscode-dts-compile-check tsec-compile-check + - script: npm exec -- npm-run-all -lp core-ci extensions-ci hygiene eslint valid-layers-check property-init-order-check vscode-dts-compile-check tsec-compile-check env: GITHUB_TOKEN: "$(github-distro-mixin-password)" displayName: Compile & Hygiene (non-OSS) @@ -152,7 +153,7 @@ steps: - script: ./build/azure-pipelines/common/extract-telemetry.sh displayName: Generate lists of telemetry events - - script: tar -cz --ignore-failed-read --exclude='.build/node_modules_cache' --exclude='.build/node_modules_list.txt' --exclude='.build/distro' -f $(Build.ArtifactStagingDirectory)/compilation.tar.gz .build out-* test/integration/browser/out test/smoke/out test/automation/out + - script: tar -cz --exclude='.build/node_modules_cache' --exclude='.build/node_modules_list.txt' --exclude='.build/distro' -f $(Build.ArtifactStagingDirectory)/compilation.tar.gz $(ls -d .build out-* test/integration/browser/out test/smoke/out test/automation/out 2>/dev/null) displayName: Compress compilation artifact - task: 1ES.PublishPipelineArtifact@1 diff --git a/build/azure-pipelines/product-publish.yml b/build/azure-pipelines/product-publish.yml index 8ecf5e6238ef..1127e5212e9b 100644 --- a/build/azure-pipelines/product-publish.yml +++ b/build/azure-pipelines/product-publish.yml @@ -102,7 +102,6 @@ steps: $stages = @( if ($env:VSCODE_BUILD_STAGE_WINDOWS -eq 'True') { 'Windows' } if ($env:VSCODE_BUILD_STAGE_LINUX -eq 'True') { 'Linux' } - if ($env:VSCODE_BUILD_STAGE_LINUX_LEGACY_SERVER -eq 'True') { 'LinuxLegacyServer' } if ($env:VSCODE_BUILD_STAGE_ALPINE -eq 'True') { 'Alpine' } if ($env:VSCODE_BUILD_STAGE_MACOS -eq 'True') { 'macOS' } if ($env:VSCODE_BUILD_STAGE_WEB -eq 'True') { 'Web' } diff --git a/build/azure-pipelines/publish-types/update-types.ts b/build/azure-pipelines/publish-types/update-types.ts index 0f99b07cf9a3..3bb02b7adabd 100644 --- a/build/azure-pipelines/publish-types/update-types.ts +++ b/build/azure-pipelines/publish-types/update-types.ts @@ -16,7 +16,7 @@ try { const dtsUri = `https://raw.githubusercontent.com/microsoft/vscode/${tag}/src/vscode-dts/vscode.d.ts`; const outPath = path.resolve(process.cwd(), 'DefinitelyTyped/types/vscode/index.d.ts'); - cp.execSync(`curl ${dtsUri} --output ${outPath}`); + cp.execFileSync('curl', [dtsUri, '--output', outPath]); updateDTSFile(outPath, tag); diff --git a/build/azure-pipelines/upload-cdn.js b/build/azure-pipelines/upload-cdn.js index 3174c8dfbaf0..f8247450f258 100644 --- a/build/azure-pipelines/upload-cdn.js +++ b/build/azure-pipelines/upload-cdn.js @@ -78,8 +78,8 @@ async function main() { const options = (compressed) => ({ account: process.env.AZURE_STORAGE_ACCOUNT, credential, - container: process.env.VSCODE_QUALITY, - prefix: commit + '/', + container: '$web', + prefix: `${process.env.VSCODE_QUALITY}/${commit}/`, contentSettings: { contentEncoding: compressed ? 'gzip' : undefined, cacheControl: 'max-age=31536000, public' diff --git a/build/azure-pipelines/upload-cdn.ts b/build/azure-pipelines/upload-cdn.ts index 8ca5e03f1f84..61d7cea523ca 100644 --- a/build/azure-pipelines/upload-cdn.ts +++ b/build/azure-pipelines/upload-cdn.ts @@ -79,8 +79,8 @@ async function main(): Promise { const options = (compressed: boolean) => ({ account: process.env.AZURE_STORAGE_ACCOUNT, credential, - container: process.env.VSCODE_QUALITY, - prefix: commit + '/', + container: '$web', + prefix: `${process.env.VSCODE_QUALITY}/${commit}/`, contentSettings: { contentEncoding: compressed ? 'gzip' : undefined, cacheControl: 'max-age=31536000, public' diff --git a/build/azure-pipelines/upload-nlsmetadata.js b/build/azure-pipelines/upload-nlsmetadata.js index 146f804ce699..e89a6497d704 100644 --- a/build/azure-pipelines/upload-nlsmetadata.js +++ b/build/azure-pipelines/upload-nlsmetadata.js @@ -109,8 +109,8 @@ function main() { .pipe(azure.upload({ account: process.env.AZURE_STORAGE_ACCOUNT, credential, - container: 'nlsmetadata', - prefix: commit + '/', + container: '$web', + prefix: `nlsmetadata/${commit}/`, contentSettings: { contentEncoding: 'gzip', cacheControl: 'max-age=31536000, public' diff --git a/build/azure-pipelines/upload-nlsmetadata.ts b/build/azure-pipelines/upload-nlsmetadata.ts index 7337156f5775..1a4f2665617d 100644 --- a/build/azure-pipelines/upload-nlsmetadata.ts +++ b/build/azure-pipelines/upload-nlsmetadata.ts @@ -126,8 +126,8 @@ function main(): Promise { .pipe(azure.upload({ account: process.env.AZURE_STORAGE_ACCOUNT, credential, - container: 'nlsmetadata', - prefix: commit + '/', + container: '$web', + prefix: `nlsmetadata/${commit}/`, contentSettings: { contentEncoding: 'gzip', cacheControl: 'max-age=31536000, public' diff --git a/build/azure-pipelines/upload-sourcemaps.js b/build/azure-pipelines/upload-sourcemaps.js index fe267275b5bc..cac1ae3caf20 100644 --- a/build/azure-pipelines/upload-sourcemaps.js +++ b/build/azure-pipelines/upload-sourcemaps.js @@ -87,8 +87,8 @@ function main() { .pipe(azure.upload({ account: process.env.AZURE_STORAGE_ACCOUNT, credential, - container: 'sourcemaps', - prefix: commit + '/' + container: '$web', + prefix: `sourcemaps/${commit}/` })) .on('end', () => c()) .on('error', (err) => e(err)); diff --git a/build/azure-pipelines/upload-sourcemaps.ts b/build/azure-pipelines/upload-sourcemaps.ts index d2950368ee07..0c51827fef41 100644 --- a/build/azure-pipelines/upload-sourcemaps.ts +++ b/build/azure-pipelines/upload-sourcemaps.ts @@ -60,8 +60,8 @@ function main(): Promise { .pipe(azure.upload({ account: process.env.AZURE_STORAGE_ACCOUNT, credential, - container: 'sourcemaps', - prefix: commit + '/' + container: '$web', + prefix: `sourcemaps/${commit}/` })) .on('end', () => c()) .on('error', (err: any) => e(err)); diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index de8b5b072b21..f7389943dc7a 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -145,7 +145,7 @@ steps: exec { npm run gulp "vscode-win32-$(VSCODE_ARCH)-min-ci" } exec { npm run gulp "vscode-win32-$(VSCODE_ARCH)-inno-updater" } echo "##vso[task.setvariable variable=BUILT_CLIENT]true" - echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)" + echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(Agent.BuildDirectory)/VSCode-win32-$(VSCODE_ARCH)" env: GITHUB_TOKEN: "$(github-distro-mixin-password)" displayName: Build client @@ -156,7 +156,7 @@ steps: exec { npm run gulp "vscode-reh-win32-$(VSCODE_ARCH)-min-ci" } mv ..\vscode-reh-win32-$(VSCODE_ARCH) ..\vscode-server-win32-$(VSCODE_ARCH) # TODO@joaomoreno echo "##vso[task.setvariable variable=BUILT_SERVER]true" - echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(CodeSigningFolderPath),$(agent.builddirectory)/vscode-server-win32-$(VSCODE_ARCH)" + echo "##vso[task.setvariable variable=CodeSigningFolderPath]$(CodeSigningFolderPath),$(Agent.BuildDirectory)/vscode-server-win32-$(VSCODE_ARCH)" env: GITHUB_TOKEN: "$(github-distro-mixin-password)" displayName: Build server @@ -196,10 +196,10 @@ steps: $ErrorActionPreference = "Stop" $ArtifactName = (gci -Path "$(Build.ArtifactStagingDirectory)/cli" | Select-Object -last 1).FullName Expand-Archive -Path $ArtifactName -DestinationPath "$(Build.ArtifactStagingDirectory)/cli" - $AppProductJson = Get-Content -Raw -Path "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)\resources\app\product.json" | ConvertFrom-Json + $AppProductJson = Get-Content -Raw -Path "$(Agent.BuildDirectory)\VSCode-win32-$(VSCODE_ARCH)\resources\app\product.json" | ConvertFrom-Json $CliAppName = $AppProductJson.tunnelApplicationName $AppName = $AppProductJson.applicationName - Move-Item -Path "$(Build.ArtifactStagingDirectory)/cli/$AppName.exe" -Destination "$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)/bin/$CliAppName.exe" + Move-Item -Path "$(Build.ArtifactStagingDirectory)/cli/$AppName.exe" -Destination "$(Agent.BuildDirectory)/VSCode-win32-$(VSCODE_ARCH)/bin/$CliAppName.exe" displayName: Move VS Code CLI - task: UseDotNet@2 @@ -239,6 +239,8 @@ steps: - ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}: - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" $PackageJson = Get-Content -Raw -Path ..\VSCode-win32-$(VSCODE_ARCH)\resources\app\package.json | ConvertFrom-Json $Version = $PackageJson.version echo "##vso[task.setvariable variable=VSCODE_VERSION]$Version" diff --git a/build/azure-pipelines/win32/sdl-scan-win32.yml b/build/azure-pipelines/win32/sdl-scan-win32.yml index def3cb53dfcc..bf6819a4b479 100644 --- a/build/azure-pipelines/win32/sdl-scan-win32.yml +++ b/build/azure-pipelines/win32/sdl-scan-win32.yml @@ -102,13 +102,6 @@ steps: - powershell: npm run compile displayName: Compile - - powershell: | - Get-ChildItem '$(Build.SourcesDirectory)' -Recurse -Filter "*.exe" - Get-ChildItem '$(Build.SourcesDirectory)' -Recurse -Filter "*.dll" - Get-ChildItem '$(Build.SourcesDirectory)' -Recurse -Filter "*.node" - Get-ChildItem '$(Build.SourcesDirectory)' -Recurse -Filter "*.pdb" - displayName: List files - - powershell: npm run gulp "vscode-symbols-win32-${{ parameters.VSCODE_ARCH }}" env: GITHUB_TOKEN: "$(github-distro-mixin-password)" @@ -119,16 +112,7 @@ steps: Get-ChildItem '$(Agent.BuildDirectory)\scanbin' -Recurse -Filter "*.dll" Get-ChildItem '$(Agent.BuildDirectory)\scanbin' -Recurse -Filter "*.node" Get-ChildItem '$(Agent.BuildDirectory)\scanbin' -Recurse -Filter "*.pdb" - displayName: List files again - - - task: BinSkim@4 - inputs: - InputType: "Basic" - Function: "analyze" - TargetPattern: "guardianGlob" - AnalyzeIgnorePdbLoadError: true - AnalyzeTargetGlob: '$(Agent.BuildDirectory)\scanbin\**.dll;$(Agent.BuildDirectory)\scanbin\**.exe;$(Agent.BuildDirectory)\scanbin\**.node' - AnalyzeLocalSymbolDirectories: '$(Agent.BuildDirectory)\scanbin\VSCode-win32-${{ parameters.VSCODE_ARCH }}\pdb' + displayName: List files - task: CopyFiles@2 displayName: 'Collect Symbols for API Scan' @@ -139,19 +123,6 @@ steps: flattenFolders: true condition: succeeded() - - task: PublishSymbols@2 - inputs: - IndexSources: false - SymbolsFolder: '$(Agent.BuildDirectory)\symbols' - SearchPattern: '**\*.pdb' - SymbolServerType: TeamServices - SymbolsProduct: 'code' - ArtifactServices.Symbol.AccountName: microsoft - ArtifactServices.Symbol.PAT: $(System.AccessToken) - ArtifactServices.Symbol.UseAAD: false - displayName: Publish Symbols - condition: succeeded() - - task: APIScan@2 inputs: softwareFolder: $(Agent.BuildDirectory)\scanbin diff --git a/build/checksums/electron.txt b/build/checksums/electron.txt index 293250496af8..d390d7a233ca 100644 --- a/build/checksums/electron.txt +++ b/build/checksums/electron.txt @@ -1,75 +1,75 @@ -0729d2cb830425c4591b40d7189c2f7da020f5adb887a49a4faa022d551b1e6f *chromedriver-v32.2.7-darwin-arm64.zip -a7d61c68d3b3522c0ec383915b6ab3d9f269d9ada0e09aa87a4e7d9fc24fe928 *chromedriver-v32.2.7-darwin-x64.zip -45314c8c7127f6083469c2c067aa78beb20055ba4d7a63eb2108b27e594a647a *chromedriver-v32.2.7-linux-arm64.zip -7e976a7131dcfd55f781c073ae59c8a24a1393119d831fbac13c6a335eb71467 *chromedriver-v32.2.7-linux-armv7l.zip -3437feb5d8e7157476d2e7a6558346061cd7e46506874bc7870eed8a3a43642a *chromedriver-v32.2.7-linux-x64.zip -3737301add80a936374acb17b84bb3a715fab9fbce049816ea7a51fa53d3b35e *chromedriver-v32.2.7-mas-arm64.zip -8b8b62f48a5e8b8a340b47348a2cc5dd4ba38789f76bc5567c039587538081a9 *chromedriver-v32.2.7-mas-x64.zip -24b666e3ab41eb1c66ab0f2361af0529b2b8e1e5ef153cfcef36adc700f9ed6d *chromedriver-v32.2.7-win32-arm64.zip -6d40251661afb1835adbef85e317fd520c0f1378156614c82befb348c3122c2d *chromedriver-v32.2.7-win32-ia32.zip -483012da9903d8d75e5e251a3262667c9a0a012a492b93dbe1237c7827eba778 *chromedriver-v32.2.7-win32-x64.zip -1e9b2b9011f56fa26f4d9fa57254ef1d0bdb34405a9bdf83a652f6258347e46d *electron-api.json -c0ea4a21f2e7e946300bf587a4e31f72ef996c497eaa94e6b8f788b917b896e5 *electron-v32.2.7-darwin-arm64-dsym-snapshot.zip -1e6e84e56cfb3a2473cab41577c160d3afcbda8337dda17c5295da90266433c9 *electron-v32.2.7-darwin-arm64-dsym.zip -9f460100fb71ef098bec26e9a09978ec1b1663165d6a358bfc398f5548a844c3 *electron-v32.2.7-darwin-arm64-symbols.zip -71e76a0a81a0c1c10e9e4862caf96437ba85a18c8fa7d8e15d59e3c057b893bd *electron-v32.2.7-darwin-arm64.zip -e406d690365f332826843c86c6a1b5c0320a84b0527ad8700a0e995b12a35f8c *electron-v32.2.7-darwin-x64-dsym-snapshot.zip -53d6fb64d717af80f024284161a432aaffb47631ef7548f18f33016c3376871a *electron-v32.2.7-darwin-x64-dsym.zip -3c9187db2cc0570d7b01651fa78294df7d451c87c361335cee80a61c1c561b67 *electron-v32.2.7-darwin-x64-symbols.zip -34310ed51d32b6c02ba3e3f447b0807ea85804d1f2b239e02a9de58b9080fbf8 *electron-v32.2.7-darwin-x64.zip -e884f2f9f3d001488888929b8affe053a60a7a780af7d0ec8d7023023f40ca52 *electron-v32.2.7-linux-arm64-debug.zip -fd88e47e7b564b006f68641b5c328721bbc8d87cfc9e569d9733354d263cddee *electron-v32.2.7-linux-arm64-symbols.zip -fb6e1f24385c3058844bd768320d5b332b4cbd011ab930e7252dc330c8ee17b3 *electron-v32.2.7-linux-arm64.zip -e884f2f9f3d001488888929b8affe053a60a7a780af7d0ec8d7023023f40ca52 *electron-v32.2.7-linux-armv7l-debug.zip -f338ea7ea592c3ccdad1bb788e9b936610f825ac69290e48d394790d5266dce3 *electron-v32.2.7-linux-armv7l-symbols.zip -4a95643e88cadfb011354d25cafe242cdb8c5327d65f86b4fbabe64717367ed2 *electron-v32.2.7-linux-armv7l.zip -e6e0fce9f6d95a84653b537b741967cae48c4c70c8026c02293c979074225b46 *electron-v32.2.7-linux-x64-debug.zip -122cc565d0ccd2774e298645473869752d27d2632aa97583d93b499e9b02f22b *electron-v32.2.7-linux-x64-symbols.zip -98007545e1d3700b32de5cb5eebcc10b9d105fb0dad6396155fdab1b40abb638 *electron-v32.2.7-linux-x64.zip -556d9ca239ee1206c9d67affa836ebb651db88eea6bee48cb7b43fa75851c72d *electron-v32.2.7-mas-arm64-dsym-snapshot.zip -662a3742b94fcbf7ab91a7c20e1430825ae7852e915fcb558d6357a310d631c6 *electron-v32.2.7-mas-arm64-dsym.zip -edd0763ead7ffd5bf5072539e5ca0be9252b9590e674e6e44e69b2057c329d79 *electron-v32.2.7-mas-arm64-symbols.zip -a4483f5246ecadfa48b1fc671d92b5dfbc09fbd88fe386f2ce48f10de79f2127 *electron-v32.2.7-mas-arm64.zip -a9aad4c413d4851fa3463eeef7015e3a3e77a501192965db1c5b870fa31a9660 *electron-v32.2.7-mas-x64-dsym-snapshot.zip -96c20e5c4b73febd3458679e9cc939f5f8255a327b06f49188ab2e3fe8311ea3 *electron-v32.2.7-mas-x64-dsym.zip -6ac844957373114e04411d3af1cb6507e35174d1dc279cce41cb92bbf2ea5d26 *electron-v32.2.7-mas-x64-symbols.zip -888b830b991dab6cf2c4351e112a48f24a4748efefcd763d693a79161199e65a *electron-v32.2.7-mas-x64.zip -27759db6bcdd16d4ff5548684361ba4372d885d3142bf02db59837c3634b1934 *electron-v32.2.7-win32-arm64-pdb.zip -6019e6ec58e9b6da335f20874efebc42d034a179163180b3b6faedf2963ae577 *electron-v32.2.7-win32-arm64-symbols.zip -48b81d28fdceb4ab3ca27650d79bab910a1a19dbda72271882bfdc877c71975f *electron-v32.2.7-win32-arm64-toolchain-profile.zip -2c755fdd4f9fda618b2db6b8c7210c5f3106a88b1e87b83e8433b4ab4a628cc2 *electron-v32.2.7-win32-arm64.zip -4dce0b21d1c2093cc4f7c0eaf9453a38377e0076d811da3c7391f105fc1d6afb *electron-v32.2.7-win32-ia32-pdb.zip -9a0a9c3746cd40ddc9c926755633b16676714e2138d7a2d888f658a26f617039 *electron-v32.2.7-win32-ia32-symbols.zip -48b81d28fdceb4ab3ca27650d79bab910a1a19dbda72271882bfdc877c71975f *electron-v32.2.7-win32-ia32-toolchain-profile.zip -6c338c5cd0b0587349ab0f119ca8f7d2728b1c3a43fe241741087f5fdf139c9c *electron-v32.2.7-win32-ia32.zip -fa240d324c5376aa12ed2aef26597764d9bfc2fdd0d16d7f76afc2c3e3c65a29 *electron-v32.2.7-win32-x64-pdb.zip -f645b53771cbcdfaa041d9cf9581348821d82c1b185ddb913759e2d62ee2410a *electron-v32.2.7-win32-x64-symbols.zip -48b81d28fdceb4ab3ca27650d79bab910a1a19dbda72271882bfdc877c71975f *electron-v32.2.7-win32-x64-toolchain-profile.zip -819ab19b7111dfd39dff506b3cb5cd2e1d8f4bb17f96ba74b987b2eac14b6c63 *electron-v32.2.7-win32-x64.zip -ce41b10c28bd43249cd3b409e081b1c83a2b691381bdd2e3bf208ec40ca176b8 *electron.d.ts -d2491071a641ce2e0f63c1f52e3a412856dd83ca17d021af1166d6e5b4de5638 *ffmpeg-v32.2.7-darwin-arm64.zip -5c5589b2c93f834e595eb692aa768b934245d2631df69bc4cad3a6602bba0e67 *ffmpeg-v32.2.7-darwin-x64.zip -3f1eafaf4cd90ab43ba0267429189be182435849a166a2cbe1faefc0d07217c4 *ffmpeg-v32.2.7-linux-arm64.zip -3db919bc57e1a5bf7c1bae1d7aeacf4a331990ea82750391c0b24a046d9a2812 *ffmpeg-v32.2.7-linux-armv7l.zip -fe7d779dddbfb5da5999a7607fc5e3c7a6ab7c65e8da9fee1384918865231612 *ffmpeg-v32.2.7-linux-x64.zip -feeef1ab10543c813f730cc7a482b43eda35d40f1285b950e1a6d7805db2332a *ffmpeg-v32.2.7-mas-arm64.zip -96ef45180589c854fedf2d0601a20e70a65220c0820c45d0dfd4ec64724c58e0 *ffmpeg-v32.2.7-mas-x64.zip -ab4ab9cd62e40c4d3064004caa9de680cb72d8180d4facc1be06bdc886c23410 *ffmpeg-v32.2.7-win32-arm64.zip -90b5e2ebd4ff683eda97cc43ebbdee9b133b27edd2a34ae7ef37e7969d1d68be *ffmpeg-v32.2.7-win32-ia32.zip -8452085c0a650035f30a4b76e2ce1791f9b392ea7262109d29f7fe383fc41ddb *ffmpeg-v32.2.7-win32-x64.zip -78b415ebb9040dacabb6eb776a8d4837dda9a9b1ec9d64ee15db28dbb8598862 *hunspell_dictionaries.zip -a30057c37e6be5732944084575a2278616297242ae51bd474c683263cbc0c3e4 *libcxx-objects-v32.2.7-linux-arm64.zip -f9e9d1ff1a03a3e609ab8e727b1f89e77934509a4afdb849698b70e701c2176f *libcxx-objects-v32.2.7-linux-armv7l.zip -bb66e3b48f8e0706126b2b8b08827a4adda6f56c509eae4d136fcffd5414c353 *libcxx-objects-v32.2.7-linux-x64.zip -5181518d7da83fea5d8b033ab4fb7ed300f73bd8d20b8c26b624128233bd6ab2 *libcxx_headers.zip -6030ad099859b62cbdd9021b2cdb453a744a2751cb1dab30519e3e8708ad72d6 *libcxxabi_headers.zip -d3dcc4925a6bd55bc305fd41805ffee77dc8821730ac75cf4ee9ed2ca4ebdccb *mksnapshot-v32.2.7-darwin-arm64.zip -e6dfad3c30f4f38509b2fc972dd05cef06142c4832d931edba19742e06161279 *mksnapshot-v32.2.7-darwin-x64.zip -25ba5be47a721700f16af10945e71408ed86ffd6800b5d5ef04d38c0d77aa446 *mksnapshot-v32.2.7-linux-arm64-x64.zip -f7e8b50691712206587d81844bd63271f2dd49253c946a5b66bd6f169ccf94d6 *mksnapshot-v32.2.7-linux-armv7l-x64.zip -a0b119abe93c0231601b6c699cce4b78e89def766c24f9a8a06cfab3feca8f6c *mksnapshot-v32.2.7-linux-x64.zip -e3e8a496a1eaf6c8ce623fa4b139e5458cf3ce3702ea3560cded839087b60792 *mksnapshot-v32.2.7-mas-arm64.zip -c03219273c82022c29e277d07ce1d0980d25c22d39269fa3eef9547f57ec410b *mksnapshot-v32.2.7-mas-x64.zip -7684cb9c6f621db05b6e68080fade81f46d0ff8eeac94080bd635f035069d13e *mksnapshot-v32.2.7-win32-arm64-x64.zip -f7ca1d557e3d0f878b13f57dc0e00932f7a97f3dd0f0cc3bbbd565a06718bd17 *mksnapshot-v32.2.7-win32-ia32.zip -d9d8dd33561eb648e5ebd00f99418122d9a915ec63fe967e7cb0ff64ef8ee199 *mksnapshot-v32.2.7-win32-x64.zip +c9b82c9f381742e839fea00aeb14f24519bcaf38a0f4eed25532191701f9535b *chromedriver-v34.3.2-darwin-arm64.zip +d556c1e2b06f1bf131e83c2fb981de755c28e1083a884d257eb964815be16b0c *chromedriver-v34.3.2-darwin-x64.zip +1cabad4f3303ac2ff172a9f22185f64944dbaa6fc68271609077158eaefdee35 *chromedriver-v34.3.2-linux-arm64.zip +4213ce52c72ef414179b5c5c22ae8423847ff030d438296bd6c2aac763930a7b *chromedriver-v34.3.2-linux-armv7l.zip +3c64c08221fdfc0f4be60ea8b1b126f2ecca45f60001b63778522f711022c6ea *chromedriver-v34.3.2-linux-x64.zip +e8388734d88e011cb6cd79795431de9206820749219d80565ee49d90501d2bf3 *chromedriver-v34.3.2-mas-arm64.zip +3ad1dd37bd6e0bb37e8503898db7aedd56bd5213e6d6760b05c3d11f4625062b *chromedriver-v34.3.2-mas-x64.zip +d567b481a0f5d88e84bba7718f89fb08f56363bfc4cb5914e1c2086358a5c252 *chromedriver-v34.3.2-win32-arm64.zip +df6732e9dc61cb20a3c0b2a2de453aac7e2bd54e7cbff43512afa614852c15fa *chromedriver-v34.3.2-win32-ia32.zip +dda0765c8d064924632e18cd152014ecd767f3808fc51c8249a053bfb7ca70a2 *chromedriver-v34.3.2-win32-x64.zip +1945f15caff98f2e0f1ee539c483d352fb8d4d0c13f342caa7abe247676d828c *electron-api.json +c078bbf727b3c3026f60e07a0f4643b85c06c581b54be017d0a6c284ba6772d3 *electron-v34.3.2-darwin-arm64-dsym-snapshot.zip +35f587754d6a3272606258386bf73688d63dd53c7e572d3a7cbaae6f3f60bdae *electron-v34.3.2-darwin-arm64-dsym.zip +08b14ee02c98353de3c738120dfd017322666e82b914a7f6de9b9888dcc5c0f0 *electron-v34.3.2-darwin-arm64-symbols.zip +2a4aa7e8fa30f229e465ebd18d3e4722e2b41529dc51a68a954d333a7e556ffe *electron-v34.3.2-darwin-arm64.zip +1509ccdeb80024f5e3edd5ecf804b4cef4e47ea2bd74e33ef0b39044b0ccf892 *electron-v34.3.2-darwin-x64-dsym-snapshot.zip +3bbe5d587c3f582ed8c126b0fb635cc02ad9a14d077b04892fe6f862092445b0 *electron-v34.3.2-darwin-x64-dsym.zip +fa7ece82e6ecaf1c94ed341e8ebff98e64687c68fe113f52cd9a21400302e22f *electron-v34.3.2-darwin-x64-symbols.zip +23938c62257a65a863ed7aa7c7966ba5f257a7d3dc16c78293e826962cc39c5c *electron-v34.3.2-darwin-x64.zip +0547eecf8ab538d74fa854f591ce8b888a3dbb339256d2db3038e7bb2c6dd929 *electron-v34.3.2-linux-arm64-debug.zip +676d0dc2b1c1c85c8b2abbb8cd5376ee22ecdb910493b910d9ae5a998532136a *electron-v34.3.2-linux-arm64-symbols.zip +774e4ccb39d553e5487994a9f8c60774a90f08cdb049ff65f3963fc27c969ff2 *electron-v34.3.2-linux-arm64.zip +0547eecf8ab538d74fa854f591ce8b888a3dbb339256d2db3038e7bb2c6dd929 *electron-v34.3.2-linux-armv7l-debug.zip +ba33bf53fcb35dea568a2795f5b23ecf46c218abe8258946611c72a1f42f716c *electron-v34.3.2-linux-armv7l-symbols.zip +73ae92c8fffb351d3a455569cf57ce9a3f676f42bf61939c613c607fe0fc3bfb *electron-v34.3.2-linux-armv7l.zip +e61a9a69dd7ea6f2687708a8e83516670cdea53c728226e598e2f6f1fad5b77b *electron-v34.3.2-linux-x64-debug.zip +f1a04df7fe67dd1cd29e7b87871525458d2eb24c0cf3b5835a1c56974707562a *electron-v34.3.2-linux-x64-symbols.zip +7b74c0c4fae82e27c7e9cbca13e9763e046113dba8737d3e27de9a0b300ac87e *electron-v34.3.2-linux-x64.zip +8571a6aa83e00925ceb39fdc5a45a9f6b9aa3d92fd84951c6f252ed723aea4ae *electron-v34.3.2-mas-arm64-dsym-snapshot.zip +477410c6f9a6c5eeaedf376058a02c2996fc0a334aa40eeec7d3734c09347f4d *electron-v34.3.2-mas-arm64-dsym.zip +c2e62dcd6630cb51b2d8e2869e74e47d29bda785521cea6e82e546d0fc58aabb *electron-v34.3.2-mas-arm64-symbols.zip +a1698e8546a062fd59b7f8e5507a7f3220fb00b347f2377de83fc9a07f7f3507 *electron-v34.3.2-mas-arm64.zip +741a24ac230a3651dca81d211f9f00b835c428a5ed0c5f67d370d4e88b62f8d6 *electron-v34.3.2-mas-x64-dsym-snapshot.zip +aeff97ec9e5c9e173ac89e38acd94476025c5640d5f27be1e8c2abd54398bab3 *electron-v34.3.2-mas-x64-dsym.zip +9f14b66b1d612ac66697288e8763171c388f7f200854871a5f0ab464a6a921c2 *electron-v34.3.2-mas-x64-symbols.zip +c979d7e7175f1e8e03ca187997d4c156b878189fc3611b347fadebcb16f3e027 *electron-v34.3.2-mas-x64.zip +f43c700641e8220205dd356952e32718d113cf530520c4ed7209b59851eac266 *electron-v34.3.2-win32-arm64-pdb.zip +3ba6e01c99bffac6b5dd3fd6f122ecdb571cf6f675dc5498c65050bd7a382ef8 *electron-v34.3.2-win32-arm64-symbols.zip +c23f84aabb09c24cd2ae759a547fdba4206af19a3bb0f4554a91cd9528648ad0 *electron-v34.3.2-win32-arm64-toolchain-profile.zip +9b9cb65d75a16782088b492f9ef3bb4d27525012b819c12bf29bd27e159d749b *electron-v34.3.2-win32-arm64.zip +1006e7af4c149114b5ebc3497617aaa6cd1bb0b131e0a225fd73709ff308f9c5 *electron-v34.3.2-win32-ia32-pdb.zip +1ecb6430cd04454f08f557c9579163f3552144bfcc0b67b768dad8868b5b891d *electron-v34.3.2-win32-ia32-symbols.zip +c23f84aabb09c24cd2ae759a547fdba4206af19a3bb0f4554a91cd9528648ad0 *electron-v34.3.2-win32-ia32-toolchain-profile.zip +d004fd5f853754001fafaec33e383d1950b30c935ee71b297ec1c9e084355e9b *electron-v34.3.2-win32-ia32.zip +4e0721552fd2f09e9466e88089af8b965f1bfbc4ae00a59aaf6245b1d1efabfd *electron-v34.3.2-win32-x64-pdb.zip +9dea812a7e7cd0fb18e5fed9a99db5531959a068c24d3c0ecedceb644cd3ffa0 *electron-v34.3.2-win32-x64-symbols.zip +c23f84aabb09c24cd2ae759a547fdba4206af19a3bb0f4554a91cd9528648ad0 *electron-v34.3.2-win32-x64-toolchain-profile.zip +1785e161420fb90d2331c26e50bba3413cae9625b7db3c8524ea02ade631efba *electron-v34.3.2-win32-x64.zip +722b304c31ddac58b0083d94a241c5276464f04bd8ea4fcbfd33051d197be103 *electron.d.ts +31ce159b2e47d1de5bc907d8e1c89726b0f2ba530ec2e9d7a8e5c723b1ccf6e0 *ffmpeg-v34.3.2-darwin-arm64.zip +565539bac64a6ee9cf6f188070f520210a1507341718f5dc388ac7c454b1e1d5 *ffmpeg-v34.3.2-darwin-x64.zip +6006ea0f46ab229feb2685be086b0fafd65981e2939dd2218a078459c75ab527 *ffmpeg-v34.3.2-linux-arm64.zip +9404ce2e85df7c40f809f2cf62c7af607de299839fe6b7ae978c3015500abcc8 *ffmpeg-v34.3.2-linux-armv7l.zip +79aec96898b7e2462826780ee0b52b9ab299dc662af333e128a34fd5ddae87f1 *ffmpeg-v34.3.2-linux-x64.zip +9190743c78210574faf5d5ecb82a00f8fa15e5f2253378cb925a99ca9d39961b *ffmpeg-v34.3.2-mas-arm64.zip +48915adcb1a6342efeda896035101300f0432c0304cfb38f2378e98c6309ebae *ffmpeg-v34.3.2-mas-x64.zip +745d5ef786de6d4a720475079836e2fda7b501cfcd255819485a47de5b24b74e *ffmpeg-v34.3.2-win32-arm64.zip +d0d86d60978439dc8ae4a723d4e4c1f853891d596bfd84033440a232fa762e2f *ffmpeg-v34.3.2-win32-ia32.zip +4441539fd8c9cbe79880ff1bade9bdc0c3744c33d7409130af6404e57ee401ff *ffmpeg-v34.3.2-win32-x64.zip +39edd1eeefe881aa75af0e438204e0b1c6e6724e34fa5819109276331c0c2c9a *hunspell_dictionaries.zip +20dd417536e5f4ebc01f480221284c0673729c27b082bc04e2922f16cd571719 *libcxx-objects-v34.3.2-linux-arm64.zip +7e53c5779c04f895f8282c0450ec4a63074d15a0e910e41006cfea133d0288af *libcxx-objects-v34.3.2-linux-armv7l.zip +92e2283c924ab523ffec3ea22513beaab6417f7fc3d570f57d51a1e1ceb7f510 *libcxx-objects-v34.3.2-linux-x64.zip +9bf3c6e8ad68f523fe086fada4148dd04e5bb0b9290d104873e66f2584a5cf50 *libcxx_headers.zip +34e4b44f9c5e08b557a2caed55456ce7690abab910196a783a2a47b58d2b9ac9 *libcxxabi_headers.zip +11f67635e6659f9188198e4086c51b89890b61a22f6c17c99eff35595ee8f51d *mksnapshot-v34.3.2-darwin-arm64.zip +c0add9ef4ac27c73fa043d04b4c9635fd3fd9f5c16d7a03e961864ba05252813 *mksnapshot-v34.3.2-darwin-x64.zip +6262adf86a340d8d28059937b01ef1117b93212e945fddbceea5c18d7e7c64f0 *mksnapshot-v34.3.2-linux-arm64-x64.zip +f7db8ebe91a1cc8d24ef6aad12949a18d8e4975ac296e3e5e9ecd88c9bccb143 *mksnapshot-v34.3.2-linux-armv7l-x64.zip +6642038e86bda362980ff1c8973a404e2b02efdd87de9e35b650fc1e743833da *mksnapshot-v34.3.2-linux-x64.zip +15883bf8e8cd737c3682d1e719d7cbac92f50b525681aac324dca876861dfc7d *mksnapshot-v34.3.2-mas-arm64.zip +4da23a950bfcc377ef21c37d496017ab4c36da03f3b41049ac114042c42608ce *mksnapshot-v34.3.2-mas-x64.zip +fab59573d3c2f9bdf31146a1896d24ac0c51f736aad86d2f3c7ecef13c05a7fd *mksnapshot-v34.3.2-win32-arm64-x64.zip +66f25e07c6f8d5d2009577a129440255a3baf63c929a5b60b2e77cd52e46105b *mksnapshot-v34.3.2-win32-ia32.zip +8168bfbf61882cfac80aed1e71e364e1c7f2fccd11eac298e6abade8b46894ea *mksnapshot-v34.3.2-win32-x64.zip diff --git a/build/checksums/nodejs.txt b/build/checksums/nodejs.txt index 9e53ad908323..d394605dda3a 100644 --- a/build/checksums/nodejs.txt +++ b/build/checksums/nodejs.txt @@ -1,7 +1,7 @@ -9e92ce1032455a9cc419fe71e908b27ae477799371b45a0844eedb02279922a4 node-v20.18.1-darwin-arm64.tar.gz -c5497dd17c8875b53712edaf99052f961013cedc203964583fc0cfc0aaf93581 node-v20.18.1-darwin-x64.tar.gz -73cd297378572e0bc9dfc187c5ec8cca8d43aee6a596c10ebea1ed5f9ec682b6 node-v20.18.1-linux-arm64.tar.gz -7b7c3315818e9fe57512737c2380fada14d8717ce88945fb6f7b8baadd3cfb92 node-v20.18.1-linux-armv7l.tar.gz -259e5a8bf2e15ecece65bd2a47153262eda71c0b2c9700d5e703ce4951572784 node-v20.18.1-linux-x64.tar.gz -9a52905b5d22b08b5b34e86b8d5358cd22c03fbd0fcb9dbb37c9bd82a8f18c17 win-arm64/node.exe -06c1dec1b428927d6ff01c8f5882f119ec13b61ac77483760aa7fba215c72cf5 win-x64/node.exe +1f15b7ed18a580af31cf32bc126572292d820f547bf55bf9cdce08041a24e1d9 node-v20.18.3-darwin-arm64.tar.gz +ba668f64df9239843fefcef095ee539f5ac5aa1b0fc15a71f1ecca16abedec7a node-v20.18.3-darwin-x64.tar.gz +93a9df19238adfaa289f4784041d03edaf2fdd89fbb247faffca2fe4a1000703 node-v20.18.3-linux-arm64.tar.gz +8a84eb34287db6a273066934d7195e429f57b91686b62fc19497210204a2b3de node-v20.18.3-linux-armv7l.tar.gz +9fc3952da39b20d1fcfdb777b198cc035485afbbb1004b4df93f35245d61151e node-v20.18.3-linux-x64.tar.gz +4258e333f4b95060681d61bffa762542a8068547d3dffebe57c575b38d380dda win-arm64/node.exe +528a9aa64888a2a3ba71c6aea89434dd5ab5cb3caa9f0f31345cf5facf685ab0 win-x64/node.exe diff --git a/build/checksums/vscode-sysroot.txt b/build/checksums/vscode-sysroot.txt index 0b5f38c60ce7..67182b078ed5 100644 --- a/build/checksums/vscode-sysroot.txt +++ b/build/checksums/vscode-sysroot.txt @@ -1,6 +1,3 @@ -68a17006021975ff271a1dd615f9db9eda7c25f2cc65e750c87980dc57a06c94 aarch64-linux-gnu-glibc-2.17.tar.gz 0de422a81683cf9e8cf875dbd1e0c27545ac3c775b2d53015daf3ca2b31d3f15 aarch64-linux-gnu-glibc-2.28.tar.gz -3ced48cb479f2cdba95aa649710fcb7778685551c745bbd76ac706c3c0ead9fb arm-rpi-linux-gnueabihf-glibc-2.17.tar.gz 7aea163f7fad8cc50000c86b5108be880121d35e2f55d016ef8c96bbe54129eb arm-rpi-linux-gnueabihf-glibc-2.28.tar.gz -5aae21115f1d284c3cdf32c83db15771b59bc80793f1423032abf5a823c0d658 x86_64-linux-gnu-glibc-2.17.tar.gz dbb927408393041664a020661f2641c9785741be3d29b050b9dac58980967784 x86_64-linux-gnu-glibc-2.28.tar.gz diff --git a/build/filters.js b/build/filters.js index 17e74c3871a5..716d7be104c9 100644 --- a/build/filters.js +++ b/build/filters.js @@ -89,6 +89,7 @@ module.exports.indentationFilter = [ '!test/automation/out/**', '!test/monaco/out/**', '!test/smoke/out/**', + '!extensions/terminal-suggest/src/shell/zshBuiltinsCache.ts', '!extensions/terminal-suggest/src/completions/upstream/**', '!extensions/typescript-language-features/test-workspace/**', '!extensions/typescript-language-features/resources/walkthroughs/**', @@ -193,6 +194,7 @@ module.exports.tsFormattingFilter = [ '!extensions/vscode-api-tests/testWorkspace2/**', '!extensions/**/*.test.ts', '!extensions/html-language-features/server/lib/jquery.d.ts', + '!extensions/terminal-suggest/src/shell/zshBuiltinsCache.ts', ]; module.exports.eslintFilter = [ diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js index 739c37fc677b..9f7ea57465ba 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.js @@ -80,7 +80,7 @@ const extractEditorSrcTask = task.define('extract-editor-src', () => { importIgnorePattern: /\.css$/, destRoot: path.join(root, 'out-editor-src'), redirects: { - '@vscode/tree-sitter-wasm': '../node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-web', + '@vscode/tree-sitter-wasm': '../node_modules/@vscode/tree-sitter-wasm/wasm/web-tree-sitter', } }); }); diff --git a/build/gulpfile.reh.js b/build/gulpfile.reh.js index e0df76f1c8f2..44add792d14c 100644 --- a/build/gulpfile.reh.js +++ b/build/gulpfile.reh.js @@ -402,13 +402,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa ); } - if (platform === 'linux' && process.env['VSCODE_NODE_GLIBC'] === '-glibc-2.17') { - result = es.merge(result, - gulp.src(`resources/server/bin/helpers/check-requirements-linux-legacy.sh`, { base: '.' }) - .pipe(rename(`bin/helpers/check-requirements.sh`)) - .pipe(util.setExecutableBit()) - ); - } else if (platform === 'linux' || platform === 'alpine') { + if (platform === 'linux' || platform === 'alpine') { result = es.merge(result, gulp.src(`resources/server/bin/helpers/check-requirements-linux.sh`, { base: '.' }) .pipe(rename(`bin/helpers/check-requirements.sh`)) diff --git a/build/lib/builtInExtensions.js b/build/lib/builtInExtensions.js index 400ca6885a85..249777c44588 100644 --- a/build/lib/builtInExtensions.js +++ b/build/lib/builtInExtensions.js @@ -81,9 +81,17 @@ function isUpToDate(extension) { } } function getExtensionDownloadStream(extension) { - const galleryServiceUrl = productjson.extensionsGallery?.serviceUrl; - return (galleryServiceUrl ? ext.fromMarketplace(galleryServiceUrl, extension) : ext.fromGithub(extension)) - .pipe((0, gulp_rename_1.default)(p => p.dirname = `${extension.name}/${p.dirname}`)); + let input; + if (extension.vsix) { + input = ext.fromVsix(path_1.default.join(root, extension.vsix), extension); + } + else if (productjson.extensionsGallery?.serviceUrl) { + input = ext.fromMarketplace(productjson.extensionsGallery.serviceUrl, extension); + } + else { + input = ext.fromGithub(extension); + } + return input.pipe((0, gulp_rename_1.default)(p => p.dirname = `${extension.name}/${p.dirname}`)); } function getExtensionStream(extension) { // if the extension exists on disk, use those files instead of downloading anew diff --git a/build/lib/builtInExtensions.ts b/build/lib/builtInExtensions.ts index 9b1ec7356ef3..e9a1180ce35e 100644 --- a/build/lib/builtInExtensions.ts +++ b/build/lib/builtInExtensions.ts @@ -21,6 +21,7 @@ export interface IExtensionDefinition { sha256: string; repo: string; platforms?: string[]; + vsix?: string; metadata: { id: string; publisherId: { @@ -68,9 +69,17 @@ function isUpToDate(extension: IExtensionDefinition): boolean { } function getExtensionDownloadStream(extension: IExtensionDefinition) { - const galleryServiceUrl = productjson.extensionsGallery?.serviceUrl; - return (galleryServiceUrl ? ext.fromMarketplace(galleryServiceUrl, extension) : ext.fromGithub(extension)) - .pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`)); + let input: Stream; + + if (extension.vsix) { + input = ext.fromVsix(path.join(root, extension.vsix), extension); + } else if (productjson.extensionsGallery?.serviceUrl) { + input = ext.fromMarketplace(productjson.extensionsGallery.serviceUrl, extension); + } else { + input = ext.fromGithub(extension); + } + + return input.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`)); } export function getExtensionStream(extension: IExtensionDefinition) { diff --git a/build/lib/extensions.js b/build/lib/extensions.js index 6afa72e5bfa9..79a9507f66c0 100644 --- a/build/lib/extensions.js +++ b/build/lib/extensions.js @@ -41,6 +41,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.fromMarketplace = fromMarketplace; +exports.fromVsix = fromVsix; exports.fromGithub = fromGithub; exports.packageNonNativeLocalExtensionsStream = packageNonNativeLocalExtensionsStream; exports.packageNativeLocalExtensionsStream = packageNativeLocalExtensionsStream; @@ -56,6 +57,7 @@ const child_process_1 = __importDefault(require("child_process")); const glob_1 = __importDefault(require("glob")); const gulp_1 = __importDefault(require("gulp")); const path_1 = __importDefault(require("path")); +const crypto_1 = __importDefault(require("crypto")); const vinyl_1 = __importDefault(require("vinyl")); const stats_1 = require("./stats"); const util2 = __importStar(require("./util")); @@ -265,6 +267,29 @@ function fromMarketplace(serviceUrl, { name: extensionName, version, sha256, met .pipe(json({ __metadata: metadata })) .pipe(packageJsonFilter.restore); } +function fromVsix(vsixPath, { name: extensionName, version, sha256, metadata }) { + const json = require('gulp-json-editor'); + (0, fancy_log_1.default)('Using local VSIX for extension:', ansi_colors_1.default.yellow(`${extensionName}@${version}`), '...'); + const packageJsonFilter = (0, gulp_filter_1.default)('package.json', { restore: true }); + return gulp_1.default.src(vsixPath) + .pipe((0, gulp_buffer_1.default)()) + .pipe(event_stream_1.default.mapSync((f) => { + const hash = crypto_1.default.createHash('sha256'); + hash.update(f.contents); + const checksum = hash.digest('hex'); + if (checksum !== sha256) { + throw new Error(`Checksum mismatch for ${vsixPath} (expected ${sha256}, actual ${checksum}))`); + } + return f; + })) + .pipe(vzip.src()) + .pipe((0, gulp_filter_1.default)('extension/**')) + .pipe((0, gulp_rename_1.default)(p => p.dirname = p.dirname.replace(/^extension\/?/, ''))) + .pipe(packageJsonFilter) + .pipe((0, gulp_buffer_1.default)()) + .pipe(json({ __metadata: metadata })) + .pipe(packageJsonFilter.restore); +} function fromGithub({ name, version, repo, sha256, metadata }) { const json = require('gulp-json-editor'); (0, fancy_log_1.default)('Downloading extension from GH:', ansi_colors_1.default.yellow(`${name}@${version}`), '...'); diff --git a/build/lib/extensions.ts b/build/lib/extensions.ts index 7ddfbb035877..908480b60776 100644 --- a/build/lib/extensions.ts +++ b/build/lib/extensions.ts @@ -9,6 +9,7 @@ import cp from 'child_process'; import glob from 'glob'; import gulp from 'gulp'; import path from 'path'; +import crypto from 'crypto'; import { Stream } from 'stream'; import File from 'vinyl'; import { createStatsStream } from './stats'; @@ -254,6 +255,33 @@ export function fromMarketplace(serviceUrl: string, { name: extensionName, versi .pipe(packageJsonFilter.restore); } +export function fromVsix(vsixPath: string, { name: extensionName, version, sha256, metadata }: IExtensionDefinition): Stream { + const json = require('gulp-json-editor') as typeof import('gulp-json-editor'); + + fancyLog('Using local VSIX for extension:', ansiColors.yellow(`${extensionName}@${version}`), '...'); + + const packageJsonFilter = filter('package.json', { restore: true }); + + return gulp.src(vsixPath) + .pipe(buffer()) + .pipe(es.mapSync((f: File) => { + const hash = crypto.createHash('sha256'); + hash.update(f.contents as Buffer); + const checksum = hash.digest('hex'); + if (checksum !== sha256) { + throw new Error(`Checksum mismatch for ${vsixPath} (expected ${sha256}, actual ${checksum}))`); + } + return f; + })) + .pipe(vzip.src()) + .pipe(filter('extension/**')) + .pipe(rename(p => p.dirname = p.dirname!.replace(/^extension\/?/, ''))) + .pipe(packageJsonFilter) + .pipe(buffer()) + .pipe(json({ __metadata: metadata })) + .pipe(packageJsonFilter.restore); +} + export function fromGithub({ name, version, repo, sha256, metadata }: IExtensionDefinition): Stream { const json = require('gulp-json-editor') as typeof import('gulp-json-editor'); diff --git a/build/lib/layersChecker.js b/build/lib/layersChecker.js index 5cf5c58402c7..8e46cb715417 100644 --- a/build/lib/layersChecker.js +++ b/build/lib/layersChecker.js @@ -81,7 +81,8 @@ const CORE_TYPES = [ 'ImportMeta', // webcrypto has been available since Node.js 19, but still live in dom.d.ts 'Crypto', - 'SubtleCrypto' + 'SubtleCrypto', + 'JsonWebKey', ]; // Types that are defined in a common layer but are known to be only // available in native environments should not be allowed in browser diff --git a/build/lib/layersChecker.ts b/build/lib/layersChecker.ts index 633773289282..235d2d68dbed 100644 --- a/build/lib/layersChecker.ts +++ b/build/lib/layersChecker.ts @@ -80,7 +80,8 @@ const CORE_TYPES = [ // webcrypto has been available since Node.js 19, but still live in dom.d.ts 'Crypto', - 'SubtleCrypto' + 'SubtleCrypto', + 'JsonWebKey', ]; // Types that are defined in a common layer but are known to be only diff --git a/build/lib/mangle/index.js b/build/lib/mangle/index.js index b93003221a4f..ce7446425512 100644 --- a/build/lib/mangle/index.js +++ b/build/lib/mangle/index.js @@ -354,7 +354,7 @@ class Mangler { this.log = log; this.config = config; this.renameWorkerPool = workerpool_1.default.pool(path_1.default.join(__dirname, 'renameWorker.js'), { - maxWorkers: 1, + maxWorkers: 4, minWorkers: 'max' }); } diff --git a/build/lib/mangle/index.ts b/build/lib/mangle/index.ts index a6f066e2d2a7..4cbbd3cdaddc 100644 --- a/build/lib/mangle/index.ts +++ b/build/lib/mangle/index.ts @@ -407,7 +407,7 @@ export class Mangler { ) { this.renameWorkerPool = workerpool.pool(path.join(__dirname, 'renameWorker.js'), { - maxWorkers: 1, + maxWorkers: 4, minWorkers: 'max' }); } diff --git a/build/lib/policies.js b/build/lib/policies.js index d52015c550bc..b76d9ffe00ae 100644 --- a/build/lib/policies.js +++ b/build/lib/policies.js @@ -160,10 +160,10 @@ class ObjectPolicy extends BasePolicy { super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName); } renderADMXElements() { - return [``]; + return [``]; } renderADMLPresentationContents() { - return ``; + return ``; } } class StringEnumPolicy extends BasePolicy { diff --git a/build/lib/policies.ts b/build/lib/policies.ts index 57941d8e9676..2488920ce268 100644 --- a/build/lib/policies.ts +++ b/build/lib/policies.ts @@ -262,11 +262,11 @@ class ObjectPolicy extends BasePolicy { } protected renderADMXElements(): string[] { - return [``]; + return [``]; } renderADMLPresentationContents() { - return ``; + return ``; } } diff --git a/build/lib/propertyInitOrderChecker.js b/build/lib/propertyInitOrderChecker.js new file mode 100644 index 000000000000..4c5b735d8a73 --- /dev/null +++ b/build/lib/propertyInitOrderChecker.js @@ -0,0 +1,368 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.EntryKind = void 0; +const ts = __importStar(require("typescript")); +const path = __importStar(require("path")); +const fs = __importStar(require("fs")); +const TS_CONFIG_PATH = path.join(__dirname, '../../', 'src', 'tsconfig.json'); +// +// ############################################################################################# +// +// A custom typescript checker that ensure constructor properties are NOT used to initialize +// defined properties. This is needed for the times when `useDefineForClassFields` is gone. +// +// see https://github.com/microsoft/vscode/issues/243049, https://github.com/microsoft/vscode/issues/186726, +// https://github.com/microsoft/vscode/pull/241544 +// +// ############################################################################################# +// +const ignored = new Set([ + 'vs/base/common/arrays.ts', + 'vs/platform/extensionManagement/common/extensionsScannerService.ts', + 'vs/platform/configuration/common/configurations.ts', + 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/tokenizer.ts', + 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/bracketPairsTree.ts', + 'vs/editor/common/model/textModelTokens.ts', + 'vs/editor/common/model/tokenizationTextModelPart.ts', + 'vs/editor/common/core/textEdit.ts', + 'vs/workbench/contrib/debug/common/debugStorage.ts', + 'vs/workbench/contrib/debug/common/debugModel.ts', + 'vs/workbench/api/common/extHostCommands.ts', + 'vs/editor/browser/view/viewLayer.ts', + 'vs/editor/browser/controller/editContext/textArea/textAreaEditContextInput.ts', + 'vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts', + 'vs/editor/browser/widget/diffEditor/utils.ts', + 'vs/editor/browser/observableCodeEditor.ts', + 'vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/diffEditorViewZones.ts', + 'vs/editor/browser/widget/diffEditor/diffEditorOptions.ts', + 'vs/editor/browser/widget/diffEditor/components/diffEditorEditors.ts', + 'vs/editor/browser/widget/diffEditor/features/movedBlocksLinesFeature.ts', + 'vs/editor/browser/widget/diffEditor/components/diffEditorSash.ts', + 'vs/editor/browser/widget/diffEditor/utils/editorGutter.ts', + 'vs/editor/browser/widget/diffEditor/features/gutterFeature.ts', + 'vs/editor/browser/widget/diffEditor/features/revertButtonsFeature.ts', + 'vs/editor/browser/widget/diffEditor/diffEditorWidget.ts', + 'vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsSource.ts', + 'vs/editor/contrib/inlineCompletions/browser/model/suggestWidgetAdapter.ts', + 'vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts', + 'vs/editor/contrib/inlineCompletions/browser/hintsWidget/inlineCompletionsHintsWidget.ts', + 'vs/editor/contrib/inlayHints/browser/inlayHintsController.ts', + 'vs/editor/contrib/inlineCompletions/browser/model/changeRecorder.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/ghostText/ghostTextView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditWithChanges.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/components/gutterIndicatorView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsWordReplacementView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsLineReplacementView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsSideBySideView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/originalEditorInlineDiffView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineCompletionsView.ts', + 'vs/editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController.ts', + 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionsAccessibleView.ts', + 'vs/editor/contrib/placeholderText/browser/placeholderTextContribution.ts', + 'vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.ts', + 'vs/workbench/contrib/chat/common/promptSyntax/parsers/basePromptParser.ts', + 'vs/workbench/contrib/files/browser/views/openEditorsView.ts', + 'vs/workbench/contrib/chat/browser/chatContentParts/chatAttachmentsContentPart.ts', + 'vs/workbench/contrib/chat/browser/contrib/chatImplicitContext.ts', + 'vs/workbench/contrib/chat/browser/chatInputPart.ts', + 'vs/workbench/contrib/mergeEditor/browser/model/modifiedBaseRange.ts', + 'vs/workbench/contrib/mergeEditor/browser/model/diffComputer.ts', + 'vs/workbench/contrib/mergeEditor/browser/model/mergeEditorModel.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/editorGutter.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/editors/codeEditorView.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/editors/inputCodeEditorView.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/viewModel.ts', + 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInputModel.ts', + 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInput.ts', + 'vs/editor/browser/widget/multiDiffEditor/multiDiffEditorViewModel.ts', + 'vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditorInput.ts', + 'vs/platform/terminal/common/capabilities/commandDetectionCapability.ts', + 'vs/workbench/contrib/testing/common/testExclusions.ts', + 'vs/workbench/contrib/testing/common/testResultStorage.ts', + 'vs/workbench/services/userDataProfile/browser/snippetsResource.ts', + 'vs/platform/quickinput/browser/quickInputController.ts', + 'vs/platform/userDataSync/common/abstractSynchronizer.ts', + 'vs/workbench/services/authentication/browser/authenticationExtensionsService.ts', + 'vs/workbench/services/textMate/browser/backgroundTokenization/textMateWorkerTokenizerController.ts', + 'vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts', + 'vs/workbench/contrib/notebook/browser/services/notebookServiceImpl.ts', + 'vs/workbench/contrib/notebook/browser/contrib/multicursor/notebookMulticursor.ts', + 'vs/editor/browser/widget/multiDiffEditor/diffEditorItemTemplate.ts', + 'vs/editor/browser/widget/multiDiffEditor/multiDiffEditorWidgetImpl.ts', + 'vs/workbench/contrib/notebook/browser/diff/notebookMultiDiffEditor.ts', + 'vs/workbench/contrib/chat/common/promptSyntax/contentProviders/textModelContentsProvider.ts', + 'vs/workbench/contrib/chat/common/promptSyntax/service/promptsService.ts', + 'vs/workbench/contrib/search/common/cacheState.ts', + 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts', + 'vs/workbench/contrib/search/browser/anythingQuickAccess.ts', + 'vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts', + 'vs/workbench/contrib/testing/browser/testResultsView/testResultsOutput.ts', + 'vs/workbench/contrib/testing/common/testExplorerFilterState.ts', + 'vs/workbench/contrib/testing/browser/testResultsView/testResultsTree.ts', + 'vs/workbench/contrib/testing/browser/testingOutputPeek.ts', + 'vs/workbench/contrib/testing/browser/explorerProjections/index.ts', + 'vs/workbench/contrib/testing/browser/testingExplorerFilter.ts', + 'vs/workbench/contrib/testing/browser/testingExplorerView.ts', + 'vs/workbench/contrib/testing/common/testServiceImpl.ts', + 'vs/platform/quickinput/browser/commandsQuickAccess.ts', + 'vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts', + 'vs/workbench/contrib/multiDiffEditor/browser/scmMultiDiffSourceResolver.ts', + 'vs/workbench/contrib/debug/browser/debugMemory.ts', + 'vs/workbench/contrib/markers/browser/markersViewActions.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/viewZones.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.ts', + 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts', + 'vs/workbench/contrib/output/browser/outputServices.ts', + 'vs/workbench/contrib/terminalContrib/typeAhead/browser/terminalTypeAheadAddon.ts', + 'vs/workbench/contrib/remote/browser/remoteIndicator.ts', + 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts', + 'vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts', + 'vs/workbench/contrib/accessibilitySignals/browser/editorTextPropertySignalsContribution.ts', + 'vs/workbench/contrib/inlineCompletions/browser/inlineCompletionLanguageStatusBarContribution.ts', + 'vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts', + 'vs/workbench/contrib/welcomeDialog/browser/welcomeWidget.ts', + 'vs/editor/standalone/browser/quickInput/standaloneQuickInputService.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsWordInsertView.ts', + 'vs/platform/terminal/node/ptyService.ts', + 'vs/workbench/api/common/extHostLanguageFeatures.ts', + 'vs/workbench/api/common/extHostSearch.ts', + 'vs/workbench/contrib/testing/test/common/testStubs.ts' +]); +const cancellationToken = { + isCancellationRequested: () => false, + throwIfCancellationRequested: () => { }, +}; +const seenFiles = new Set(); +let errorCount = 0; +function createProgram(tsconfigPath) { + const tsConfig = ts.readConfigFile(tsconfigPath, ts.sys.readFile); + const configHostParser = { fileExists: fs.existsSync, readDirectory: ts.sys.readDirectory, readFile: file => fs.readFileSync(file, 'utf8'), useCaseSensitiveFileNames: process.platform === 'linux' }; + const tsConfigParsed = ts.parseJsonConfigFileContent(tsConfig.config, configHostParser, path.resolve(path.dirname(tsconfigPath)), { noEmit: true }); + const compilerHost = ts.createCompilerHost(tsConfigParsed.options, true); + return ts.createProgram(tsConfigParsed.fileNames, tsConfigParsed.options, compilerHost); +} +const program = createProgram(TS_CONFIG_PATH); +program.getTypeChecker(); +for (const file of program.getSourceFiles()) { + if (!file || file.isDeclarationFile) { + continue; + } + const relativePath = path.relative(path.dirname(TS_CONFIG_PATH), file.fileName).replace(/\\/g, '/'); + if (ignored.has(relativePath)) { + continue; + } + visit(file); +} +if (seenFiles.size) { + console.log(); + console.log(`Found ${errorCount} error${errorCount === 1 ? '' : 's'} in ${seenFiles.size} file${seenFiles.size === 1 ? '' : 's'}.`); + process.exit(errorCount); +} +function visit(node) { + if (ts.isParameter(node) && ts.isParameterPropertyDeclaration(node, node.parent)) { + checkParameterPropertyDeclaration(node); + } + ts.forEachChild(node, visit); +} +function checkParameterPropertyDeclaration(param) { + const uses = [...collectReferences(param.name, [])]; + if (!uses.length) { + return; + } + const sourceFile = param.getSourceFile(); + if (!seenFiles.has(sourceFile)) { + if (seenFiles.size) { + console.log(``); + } + console.log(`${formatFileName(param)}:`); + seenFiles.add(sourceFile); + } + else { + console.log(``); + } + console.log(` Parameter property '${param.name.getText()}' is used before its declaration.`); + for (const { stack, container } of uses) { + const use = stack[stack.length - 1]; + console.log(` at ${formatLocation(use)}: ${formatMember(container)} -> ${formatStack(stack)}`); + errorCount++; + } +} +function* collectReferences(node, stack, requiresInvocationDepth = 0, seen = new Set()) { + for (const use of findAllReferencesInClass(node)) { + const container = findContainer(use); + if (!container || seen.has(container) || ts.isConstructorDeclaration(container)) { + continue; + } + seen.add(container); + const nextStack = [...stack, use]; + let nextRequiresInvocationDepth = requiresInvocationDepth; + if (isInvocation(use) && nextRequiresInvocationDepth > 0) { + nextRequiresInvocationDepth--; + } + if (ts.isPropertyDeclaration(container) && nextRequiresInvocationDepth === 0) { + yield { stack: nextStack, container }; + } + else if (requiresInvocation(container)) { + nextRequiresInvocationDepth++; + } + yield* collectReferences(container.name ?? container, nextStack, nextRequiresInvocationDepth, seen); + } +} +function requiresInvocation(definition) { + return ts.isMethodDeclaration(definition) || ts.isFunctionDeclaration(definition) || ts.isFunctionExpression(definition) || ts.isArrowFunction(definition); +} +function isInvocation(use) { + let location = use; + if (ts.isPropertyAccessExpression(location.parent) && location.parent.name === location) { + location = location.parent; + } + else if (ts.isElementAccessExpression(location.parent) && location.parent.argumentExpression === location) { + location = location.parent; + } + return ts.isCallExpression(location.parent) && location.parent.expression === location + || ts.isTaggedTemplateExpression(location.parent) && location.parent.tag === location; +} +function formatFileName(node) { + const sourceFile = node.getSourceFile(); + return path.resolve(sourceFile.fileName); +} +function formatLocation(node) { + const sourceFile = node.getSourceFile(); + const { line, character } = ts.getLineAndCharacterOfPosition(sourceFile, node.pos); + return `${formatFileName(sourceFile)}(${line + 1},${character + 1})`; +} +function formatStack(stack) { + return stack.slice().reverse().map((use) => formatUse(use)).join(' -> '); +} +function formatMember(container) { + const name = container.name?.getText(); + if (name) { + const className = findClass(container)?.name?.getText(); + if (className) { + return `${className}.${name}`; + } + return name; + } + return ''; +} +function formatUse(use) { + let text = use.getText(); + if (use.parent && ts.isPropertyAccessExpression(use.parent) && use.parent.name === use) { + if (use.parent.expression.kind === ts.SyntaxKind.ThisKeyword) { + text = `this.${text}`; + } + use = use.parent; + } + else if (use.parent && ts.isElementAccessExpression(use.parent) && use.parent.argumentExpression === use) { + if (use.parent.expression.kind === ts.SyntaxKind.ThisKeyword) { + text = `this['${text}']`; + } + use = use.parent; + } + if (ts.isCallExpression(use.parent)) { + text = `${text}(...)`; + } + return text; +} +function findContainer(node) { + return ts.findAncestor(node, ancestor => { + switch (ancestor.kind) { + case ts.SyntaxKind.PropertyDeclaration: + case ts.SyntaxKind.MethodDeclaration: + case ts.SyntaxKind.GetAccessor: + case ts.SyntaxKind.SetAccessor: + case ts.SyntaxKind.Constructor: + case ts.SyntaxKind.ClassStaticBlockDeclaration: + case ts.SyntaxKind.ArrowFunction: + case ts.SyntaxKind.FunctionExpression: + case ts.SyntaxKind.FunctionDeclaration: + case ts.SyntaxKind.Parameter: + return true; + } + return false; + }); +} +function findClass(node) { + return ts.findAncestor(node, ts.isClassLike); +} +function* findAllReferencesInClass(node) { + const classDecl = findClass(node); + if (!classDecl) { + return []; + } + for (const ref of findAllReferences(node)) { + for (const entry of ref.references) { + if (entry.kind !== 1 /* EntryKind.Node */ || entry.node === node) { + continue; + } + if (findClass(entry.node) === classDecl) { + yield entry.node; + } + } + } +} +// NOTE: The following uses TypeScript internals and are subject to change from version to version. +function findAllReferences(node) { + const sourceFile = node.getSourceFile(); + const position = node.getStart(); + const name = ts.getTouchingPropertyName(sourceFile, position); + const options = { use: ts.FindAllReferences.FindReferencesUse.References }; + return ts.FindAllReferences.Core.getReferencedSymbolsForNode(position, name, program, [sourceFile], cancellationToken, options) ?? []; +} +var DefinitionKind; +(function (DefinitionKind) { + DefinitionKind[DefinitionKind["Symbol"] = 0] = "Symbol"; + DefinitionKind[DefinitionKind["Label"] = 1] = "Label"; + DefinitionKind[DefinitionKind["Keyword"] = 2] = "Keyword"; + DefinitionKind[DefinitionKind["This"] = 3] = "This"; + DefinitionKind[DefinitionKind["String"] = 4] = "String"; + DefinitionKind[DefinitionKind["TripleSlashReference"] = 5] = "TripleSlashReference"; +})(DefinitionKind || (DefinitionKind = {})); +/** @internal */ +var EntryKind; +(function (EntryKind) { + EntryKind[EntryKind["Span"] = 0] = "Span"; + EntryKind[EntryKind["Node"] = 1] = "Node"; + EntryKind[EntryKind["StringLiteral"] = 2] = "StringLiteral"; + EntryKind[EntryKind["SearchedLocalFoundProperty"] = 3] = "SearchedLocalFoundProperty"; + EntryKind[EntryKind["SearchedPropertyFoundLocal"] = 4] = "SearchedPropertyFoundLocal"; +})(EntryKind || (exports.EntryKind = EntryKind = {})); +//# sourceMappingURL=propertyInitOrderChecker.js.map \ No newline at end of file diff --git a/build/lib/propertyInitOrderChecker.ts b/build/lib/propertyInitOrderChecker.ts new file mode 100644 index 000000000000..5b1582552125 --- /dev/null +++ b/build/lib/propertyInitOrderChecker.ts @@ -0,0 +1,418 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +import * as ts from 'typescript'; +import * as path from 'path'; +import * as fs from 'fs'; + +const TS_CONFIG_PATH = path.join(__dirname, '../../', 'src', 'tsconfig.json'); + +// +// ############################################################################################# +// +// A custom typescript checker that ensure constructor properties are NOT used to initialize +// defined properties. This is needed for the times when `useDefineForClassFields` is gone. +// +// see https://github.com/microsoft/vscode/issues/243049, https://github.com/microsoft/vscode/issues/186726, +// https://github.com/microsoft/vscode/pull/241544 +// +// ############################################################################################# +// + +const ignored = new Set([ + 'vs/base/common/arrays.ts', + 'vs/platform/extensionManagement/common/extensionsScannerService.ts', + 'vs/platform/configuration/common/configurations.ts', + 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/tokenizer.ts', + 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/bracketPairsTree.ts', + 'vs/editor/common/model/textModelTokens.ts', + 'vs/editor/common/model/tokenizationTextModelPart.ts', + 'vs/editor/common/core/textEdit.ts', + 'vs/workbench/contrib/debug/common/debugStorage.ts', + 'vs/workbench/contrib/debug/common/debugModel.ts', + 'vs/workbench/api/common/extHostCommands.ts', + 'vs/editor/browser/view/viewLayer.ts', + 'vs/editor/browser/controller/editContext/textArea/textAreaEditContextInput.ts', + 'vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts', + 'vs/editor/browser/widget/diffEditor/utils.ts', + 'vs/editor/browser/observableCodeEditor.ts', + 'vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/diffEditorViewZones.ts', + 'vs/editor/browser/widget/diffEditor/diffEditorOptions.ts', + 'vs/editor/browser/widget/diffEditor/components/diffEditorEditors.ts', + 'vs/editor/browser/widget/diffEditor/features/movedBlocksLinesFeature.ts', + 'vs/editor/browser/widget/diffEditor/components/diffEditorSash.ts', + 'vs/editor/browser/widget/diffEditor/utils/editorGutter.ts', + 'vs/editor/browser/widget/diffEditor/features/gutterFeature.ts', + 'vs/editor/browser/widget/diffEditor/features/revertButtonsFeature.ts', + 'vs/editor/browser/widget/diffEditor/diffEditorWidget.ts', + 'vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsSource.ts', + 'vs/editor/contrib/inlineCompletions/browser/model/suggestWidgetAdapter.ts', + 'vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts', + 'vs/editor/contrib/inlineCompletions/browser/hintsWidget/inlineCompletionsHintsWidget.ts', + 'vs/editor/contrib/inlayHints/browser/inlayHintsController.ts', + 'vs/editor/contrib/inlineCompletions/browser/model/changeRecorder.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/ghostText/ghostTextView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditWithChanges.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/components/gutterIndicatorView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsWordReplacementView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsLineReplacementView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsSideBySideView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/originalEditorInlineDiffView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsView.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineCompletionsView.ts', + 'vs/editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController.ts', + 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionsAccessibleView.ts', + 'vs/editor/contrib/placeholderText/browser/placeholderTextContribution.ts', + 'vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.ts', + 'vs/workbench/contrib/chat/common/promptSyntax/parsers/basePromptParser.ts', + 'vs/workbench/contrib/files/browser/views/openEditorsView.ts', + 'vs/workbench/contrib/chat/browser/chatContentParts/chatAttachmentsContentPart.ts', + 'vs/workbench/contrib/chat/browser/contrib/chatImplicitContext.ts', + 'vs/workbench/contrib/chat/browser/chatInputPart.ts', + 'vs/workbench/contrib/mergeEditor/browser/model/modifiedBaseRange.ts', + 'vs/workbench/contrib/mergeEditor/browser/model/diffComputer.ts', + 'vs/workbench/contrib/mergeEditor/browser/model/mergeEditorModel.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/editorGutter.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/editors/codeEditorView.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/editors/inputCodeEditorView.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/viewModel.ts', + 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInputModel.ts', + 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInput.ts', + 'vs/editor/browser/widget/multiDiffEditor/multiDiffEditorViewModel.ts', + 'vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditorInput.ts', + 'vs/platform/terminal/common/capabilities/commandDetectionCapability.ts', + 'vs/workbench/contrib/testing/common/testExclusions.ts', + 'vs/workbench/contrib/testing/common/testResultStorage.ts', + 'vs/workbench/services/userDataProfile/browser/snippetsResource.ts', + 'vs/platform/quickinput/browser/quickInputController.ts', + 'vs/platform/userDataSync/common/abstractSynchronizer.ts', + 'vs/workbench/services/authentication/browser/authenticationExtensionsService.ts', + 'vs/workbench/services/textMate/browser/backgroundTokenization/textMateWorkerTokenizerController.ts', + 'vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts', + 'vs/workbench/contrib/notebook/browser/services/notebookServiceImpl.ts', + 'vs/workbench/contrib/notebook/browser/contrib/multicursor/notebookMulticursor.ts', + 'vs/editor/browser/widget/multiDiffEditor/diffEditorItemTemplate.ts', + 'vs/editor/browser/widget/multiDiffEditor/multiDiffEditorWidgetImpl.ts', + 'vs/workbench/contrib/notebook/browser/diff/notebookMultiDiffEditor.ts', + 'vs/workbench/contrib/chat/common/promptSyntax/contentProviders/textModelContentsProvider.ts', + 'vs/workbench/contrib/chat/common/promptSyntax/service/promptsService.ts', + 'vs/workbench/contrib/search/common/cacheState.ts', + 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts', + 'vs/workbench/contrib/search/browser/anythingQuickAccess.ts', + 'vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts', + 'vs/workbench/contrib/testing/browser/testResultsView/testResultsOutput.ts', + 'vs/workbench/contrib/testing/common/testExplorerFilterState.ts', + 'vs/workbench/contrib/testing/browser/testResultsView/testResultsTree.ts', + 'vs/workbench/contrib/testing/browser/testingOutputPeek.ts', + 'vs/workbench/contrib/testing/browser/explorerProjections/index.ts', + 'vs/workbench/contrib/testing/browser/testingExplorerFilter.ts', + 'vs/workbench/contrib/testing/browser/testingExplorerView.ts', + 'vs/workbench/contrib/testing/common/testServiceImpl.ts', + 'vs/platform/quickinput/browser/commandsQuickAccess.ts', + 'vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts', + 'vs/workbench/contrib/multiDiffEditor/browser/scmMultiDiffSourceResolver.ts', + 'vs/workbench/contrib/debug/browser/debugMemory.ts', + 'vs/workbench/contrib/markers/browser/markersViewActions.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/viewZones.ts', + 'vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.ts', + 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts', + 'vs/workbench/contrib/output/browser/outputServices.ts', + 'vs/workbench/contrib/terminalContrib/typeAhead/browser/terminalTypeAheadAddon.ts', + 'vs/workbench/contrib/remote/browser/remoteIndicator.ts', + 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts', + 'vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts', + 'vs/workbench/contrib/accessibilitySignals/browser/editorTextPropertySignalsContribution.ts', + 'vs/workbench/contrib/inlineCompletions/browser/inlineCompletionLanguageStatusBarContribution.ts', + 'vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts', + 'vs/workbench/contrib/welcomeDialog/browser/welcomeWidget.ts', + 'vs/editor/standalone/browser/quickInput/standaloneQuickInputService.ts', + 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsWordInsertView.ts', + 'vs/platform/terminal/node/ptyService.ts', + 'vs/workbench/api/common/extHostLanguageFeatures.ts', + 'vs/workbench/api/common/extHostSearch.ts', + 'vs/workbench/contrib/testing/test/common/testStubs.ts' +]); + + +const cancellationToken: ts.CancellationToken = { + isCancellationRequested: () => false, + throwIfCancellationRequested: () => { }, +}; + +const seenFiles = new Set(); +let errorCount = 0; + + + +function createProgram(tsconfigPath: string): ts.Program { + const tsConfig = ts.readConfigFile(tsconfigPath, ts.sys.readFile); + + const configHostParser: ts.ParseConfigHost = { fileExists: fs.existsSync, readDirectory: ts.sys.readDirectory, readFile: file => fs.readFileSync(file, 'utf8'), useCaseSensitiveFileNames: process.platform === 'linux' }; + const tsConfigParsed = ts.parseJsonConfigFileContent(tsConfig.config, configHostParser, path.resolve(path.dirname(tsconfigPath)), { noEmit: true }); + + const compilerHost = ts.createCompilerHost(tsConfigParsed.options, true); + + return ts.createProgram(tsConfigParsed.fileNames, tsConfigParsed.options, compilerHost); +} + +const program = createProgram(TS_CONFIG_PATH); + +program.getTypeChecker(); + +for (const file of program.getSourceFiles()) { + if (!file || file.isDeclarationFile) { + continue; + } + + const relativePath = path.relative(path.dirname(TS_CONFIG_PATH), file.fileName).replace(/\\/g, '/'); + if (ignored.has(relativePath)) { + continue; + } + + visit(file); +} + +if (seenFiles.size) { + console.log(); + console.log(`Found ${errorCount} error${errorCount === 1 ? '' : 's'} in ${seenFiles.size} file${seenFiles.size === 1 ? '' : 's'}.`); + process.exit(errorCount); +} + +function visit(node: ts.Node) { + if (ts.isParameter(node) && ts.isParameterPropertyDeclaration(node, node.parent)) { + checkParameterPropertyDeclaration(node); + } + + ts.forEachChild(node, visit); +} + +function checkParameterPropertyDeclaration(param: ts.ParameterPropertyDeclaration) { + const uses = [...collectReferences(param.name, [])]; + if (!uses.length) { + return; + } + + const sourceFile = param.getSourceFile(); + if (!seenFiles.has(sourceFile)) { + if (seenFiles.size) { + console.log(``); + } + console.log(`${formatFileName(param)}:`); + seenFiles.add(sourceFile); + } else { + console.log(``); + } + console.log(` Parameter property '${param.name.getText()}' is used before its declaration.`); + for (const { stack, container } of uses) { + const use = stack[stack.length - 1]; + console.log(` at ${formatLocation(use)}: ${formatMember(container)} -> ${formatStack(stack)}`); + errorCount++; + } +} + +interface InvalidUse { + stack: ts.Node[]; + container: ReferenceContainer; +} + +function* collectReferences(node: ts.Node, stack: ts.Node[], requiresInvocationDepth: number = 0, seen = new Set()): Generator { + for (const use of findAllReferencesInClass(node)) { + const container = findContainer(use); + if (!container || seen.has(container) || ts.isConstructorDeclaration(container)) { + continue; + } + seen.add(container); + + const nextStack = [...stack, use]; + + let nextRequiresInvocationDepth = requiresInvocationDepth; + if (isInvocation(use) && nextRequiresInvocationDepth > 0) { + nextRequiresInvocationDepth--; + } + + if (ts.isPropertyDeclaration(container) && nextRequiresInvocationDepth === 0) { + yield { stack: nextStack, container }; + } + else if (requiresInvocation(container)) { + nextRequiresInvocationDepth++; + } + + yield* collectReferences(container.name ?? container, nextStack, nextRequiresInvocationDepth, seen); + } +} + +function requiresInvocation(definition: ReferenceContainer): boolean { + return ts.isMethodDeclaration(definition) || ts.isFunctionDeclaration(definition) || ts.isFunctionExpression(definition) || ts.isArrowFunction(definition); +} + +function isInvocation(use: ts.Node): boolean { + let location = use; + if (ts.isPropertyAccessExpression(location.parent) && location.parent.name === location) { + location = location.parent; + } + else if (ts.isElementAccessExpression(location.parent) && location.parent.argumentExpression === location) { + location = location.parent; + } + return ts.isCallExpression(location.parent) && location.parent.expression === location + || ts.isTaggedTemplateExpression(location.parent) && location.parent.tag === location; +} + +function formatFileName(node: ts.Node): string { + const sourceFile = node.getSourceFile(); + return path.resolve(sourceFile.fileName); +} + +function formatLocation(node: ts.Node): string { + const sourceFile = node.getSourceFile(); + const { line, character } = ts.getLineAndCharacterOfPosition(sourceFile, node.pos); + return `${formatFileName(sourceFile)}(${line + 1},${character + 1})`; +} + +function formatStack(stack: ts.Node[]): string { + return stack.slice().reverse().map((use) => formatUse(use)).join(' -> '); +} + +function formatMember(container: ReferenceContainer): string { + const name = container.name?.getText(); + if (name) { + const className = findClass(container)?.name?.getText(); + if (className) { + return `${className}.${name}`; + } + return name; + } + return ''; +} + +function formatUse(use: ts.Node): string { + let text = use.getText(); + if (use.parent && ts.isPropertyAccessExpression(use.parent) && use.parent.name === use) { + if (use.parent.expression.kind === ts.SyntaxKind.ThisKeyword) { + text = `this.${text}`; + } + use = use.parent; + } + else if (use.parent && ts.isElementAccessExpression(use.parent) && use.parent.argumentExpression === use) { + if (use.parent.expression.kind === ts.SyntaxKind.ThisKeyword) { + text = `this['${text}']`; + } + use = use.parent; + } + if (ts.isCallExpression(use.parent)) { + text = `${text}(...)`; + } + return text; +} + +type ReferenceContainer = + | ts.PropertyDeclaration + | ts.MethodDeclaration + | ts.GetAccessorDeclaration + | ts.SetAccessorDeclaration + | ts.ConstructorDeclaration + | ts.ClassStaticBlockDeclaration + | ts.ArrowFunction + | ts.FunctionExpression + | ts.FunctionDeclaration + | ts.ParameterDeclaration; + +function findContainer(node: ts.Node): ReferenceContainer | undefined { + return ts.findAncestor(node, ancestor => { + switch (ancestor.kind) { + case ts.SyntaxKind.PropertyDeclaration: + case ts.SyntaxKind.MethodDeclaration: + case ts.SyntaxKind.GetAccessor: + case ts.SyntaxKind.SetAccessor: + case ts.SyntaxKind.Constructor: + case ts.SyntaxKind.ClassStaticBlockDeclaration: + case ts.SyntaxKind.ArrowFunction: + case ts.SyntaxKind.FunctionExpression: + case ts.SyntaxKind.FunctionDeclaration: + case ts.SyntaxKind.Parameter: + return true; + } + return false; + }) as ReferenceContainer | undefined; +} + +function findClass(node: ts.Node): ts.ClassLikeDeclaration | undefined { + return ts.findAncestor(node, ts.isClassLike); +} + +function* findAllReferencesInClass(node: ts.Node): Generator { + const classDecl = findClass(node); + if (!classDecl) { + return []; + } + for (const ref of findAllReferences(node)) { + for (const entry of ref.references) { + if (entry.kind !== EntryKind.Node || entry.node === node) { + continue; + } + if (findClass(entry.node) === classDecl) { + yield entry.node; + } + } + } +} + +// NOTE: The following uses TypeScript internals and are subject to change from version to version. + +function findAllReferences(node: ts.Node): readonly SymbolAndEntries[] { + const sourceFile = node.getSourceFile(); + const position = node.getStart(); + const name: ts.Node = (ts as any).getTouchingPropertyName(sourceFile, position); + const options = { use: (ts as any).FindAllReferences.FindReferencesUse.References }; + return (ts as any).FindAllReferences.Core.getReferencedSymbolsForNode(position, name, program, [sourceFile], cancellationToken, options) ?? []; +} + +interface SymbolAndEntries { + readonly definition: Definition | undefined; + readonly references: readonly Entry[]; +} + +const enum DefinitionKind { + Symbol, + Label, + Keyword, + This, + String, + TripleSlashReference, +} + +type Definition = + | { readonly type: DefinitionKind.Symbol; readonly symbol: ts.Symbol } + | { readonly type: DefinitionKind.Label; readonly node: ts.Identifier } + | { readonly type: DefinitionKind.Keyword; readonly node: ts.Node } + | { readonly type: DefinitionKind.This; readonly node: ts.Node } + | { readonly type: DefinitionKind.String; readonly node: ts.StringLiteralLike } + | { readonly type: DefinitionKind.TripleSlashReference; readonly reference: ts.FileReference; readonly file: ts.SourceFile }; + +/** @internal */ +export const enum EntryKind { + Span, + Node, + StringLiteral, + SearchedLocalFoundProperty, + SearchedPropertyFoundLocal, +} +type NodeEntryKind = EntryKind.Node | EntryKind.StringLiteral | EntryKind.SearchedLocalFoundProperty | EntryKind.SearchedPropertyFoundLocal; +type Entry = NodeEntry | SpanEntry; +interface ContextWithStartAndEndNode { + start: ts.Node; + end: ts.Node; +} +type ContextNode = ts.Node | ContextWithStartAndEndNode; +interface NodeEntry { + readonly kind: NodeEntryKind; + readonly node: ts.Node; + readonly context?: ContextNode; +} +interface SpanEntry { + readonly kind: EntryKind.Span; + readonly fileName: string; + readonly textSpan: ts.TextSpan; +} diff --git a/build/lib/stylelint/vscode-known-variables.json b/build/lib/stylelint/vscode-known-variables.json index 9cadf39caa39..6b8419291cb6 100644 --- a/build/lib/stylelint/vscode-known-variables.json +++ b/build/lib/stylelint/vscode-known-variables.json @@ -232,6 +232,8 @@ "--vscode-editorGutter-commentGlyphForeground", "--vscode-editorGutter-commentRangeForeground", "--vscode-editorGutter-commentUnresolvedGlyphForeground", + "--vscode-editorGutter-itemGlyphForeground", + "--vscode-editorGutter-itemBackground", "--vscode-editorGutter-deletedBackground", "--vscode-editorGutter-foldingControlForeground", "--vscode-editorGutter-modifiedBackground", @@ -279,6 +281,7 @@ "--vscode-editorMarkerNavigationInfo-headerBackground", "--vscode-editorMarkerNavigationWarning-background", "--vscode-editorMarkerNavigationWarning-headerBackground", + "--vscode-editorMinimap-inlineChatInserted", "--vscode-editorMultiCursor-primary-background", "--vscode-editorMultiCursor-primary-foreground", "--vscode-editorMultiCursor-secondary-background", @@ -349,6 +352,13 @@ "--vscode-extensionIcon-verifiedForeground", "--vscode-focusBorder", "--vscode-foreground", + "--vscode-gauge-background", + "--vscode-gauge-border", + "--vscode-gauge-errorBackground", + "--vscode-gauge-errorForeground", + "--vscode-gauge-foreground", + "--vscode-gauge-warningBackground", + "--vscode-gauge-warningForeground", "--vscode-icon-foreground", "--vscode-inlineChat-background", "--vscode-inlineChat-border", @@ -360,17 +370,26 @@ "--vscode-inlineChatInput-border", "--vscode-inlineChatInput-focusBorder", "--vscode-inlineChatInput-placeholderForeground", - "--vscode-inlineEdit-border", + "--vscode-inlineEdit-gutterIndicator-background", + "--vscode-inlineEdit-gutterIndicator-primaryBackground", + "--vscode-inlineEdit-gutterIndicator-primaryForeground", + "--vscode-inlineEdit-gutterIndicator-secondaryBackground", + "--vscode-inlineEdit-gutterIndicator-secondaryForeground", + "--vscode-inlineEdit-gutterIndicator-successfulBackground", + "--vscode-inlineEdit-gutterIndicator-successfulForeground", "--vscode-inlineEdit-indicator-background", "--vscode-inlineEdit-indicator-border", "--vscode-inlineEdit-indicator-foreground", "--vscode-inlineEdit-modifiedBackground", + "--vscode-inlineEdit-modifiedBorder", "--vscode-inlineEdit-modifiedChangedLineBackground", "--vscode-inlineEdit-modifiedChangedTextBackground", "--vscode-inlineEdit-originalBackground", + "--vscode-inlineEdit-originalBorder", "--vscode-inlineEdit-originalChangedLineBackground", "--vscode-inlineEdit-originalChangedTextBackground", - "--vscode-inlineEdit-acceptedBackground", + "--vscode-inlineEdit-tabWillAcceptBorder", + "--vscode-inlineEdit-wordReplacementView-background", "--vscode-input-background", "--vscode-input-border", "--vscode-input-foreground", @@ -455,6 +474,7 @@ "--vscode-mergeEditor-conflict-unhandledUnfocused-border", "--vscode-mergeEditor-conflictingLines-background", "--vscode-minimap-background", + "--vscode-minimap-chatEditHighlight", "--vscode-minimap-errorHighlight", "--vscode-minimap-findMatchHighlight", "--vscode-minimap-foregroundOpacity", @@ -524,6 +544,8 @@ "--vscode-panelTitle-activeForeground", "--vscode-panelTitle-border", "--vscode-panelTitle-inactiveForeground", + "--vscode-panelTitleBadge-background", + "--vscode-panelTitleBadge-foreground", "--vscode-peekView-border", "--vscode-peekViewEditor-background", "--vscode-peekViewEditor-matchHighlightBackground", @@ -762,6 +784,8 @@ "--vscode-terminalStickyScroll-background", "--vscode-terminalStickyScroll-border", "--vscode-terminalStickyScrollHover-background", + "--vscode-terminalSymbolIcon-aliasForeground", + "--vscode-terminalSymbolIcon-flagForeground", "--vscode-testing-coverCountBadgeBackground", "--vscode-testing-coverCountBadgeForeground", "--vscode-testing-coveredBackground", @@ -913,6 +937,8 @@ "--test-bar-width", "--widget-color", "--text-link-decoration", - "--vscode-action-item-auto-timeout" + "--vscode-action-item-auto-timeout", + "--monaco-editor-warning-decoration", + "--animation-opacity" ] -} +} \ No newline at end of file diff --git a/build/lib/tsb/builder.js b/build/lib/tsb/builder.js index b329dd1cc08c..84308191361a 100644 --- a/build/lib/tsb/builder.js +++ b/build/lib/tsb/builder.js @@ -618,7 +618,7 @@ class LanguageServiceHost { }); // (2) import-require statements info.importedFiles.forEach(ref => { - if (!ref.fileName.startsWith('.') || path_1.default.extname(ref.fileName) === '') { + if (!ref.fileName.startsWith('.')) { // node module? return; } diff --git a/build/lib/tsb/builder.ts b/build/lib/tsb/builder.ts index c32753ee6eae..7a1b0e0cbb44 100644 --- a/build/lib/tsb/builder.ts +++ b/build/lib/tsb/builder.ts @@ -702,7 +702,7 @@ class LanguageServiceHost implements ts.LanguageServiceHost { // (2) import-require statements info.importedFiles.forEach(ref => { - if (!ref.fileName.startsWith('.') || path.extname(ref.fileName) === '') { + if (!ref.fileName.startsWith('.')) { // node module? return; } diff --git a/build/linux/debian/dep-lists.js b/build/linux/debian/dep-lists.js index 3bb58fb1215d..8ac57b94d7fc 100644 --- a/build/linux/debian/dep-lists.js +++ b/build/linux/debian/dep-lists.js @@ -25,7 +25,7 @@ exports.referenceGeneratedDepsByArch = { 'ca-certificates', 'libasound2 (>= 1.0.17)', 'libatk-bridge2.0-0 (>= 2.5.3)', - 'libatk1.0-0 (>= 2.2.0)', + 'libatk1.0-0 (>= 2.11.90)', 'libatspi2.0-0 (>= 2.9.90)', 'libc6 (>= 2.14)', 'libc6 (>= 2.16)', @@ -36,7 +36,6 @@ exports.referenceGeneratedDepsByArch = { 'libcairo2 (>= 1.6.0)', 'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', 'libdbus-1-3 (>= 1.9.14)', - 'libdrm2 (>= 2.4.75)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', 'libglib2.0-0 (>= 2.37.3)', @@ -46,6 +45,7 @@ exports.referenceGeneratedDepsByArch = { 'libnss3 (>= 2:3.30)', 'libnss3 (>= 3.26)', 'libpango-1.0-0 (>= 1.14.0)', + 'libudev1 (>= 183)', 'libx11-6', 'libx11-6 (>= 2:1.4.99.1)', 'libxcb1 (>= 1.9.2)', @@ -62,7 +62,7 @@ exports.referenceGeneratedDepsByArch = { 'ca-certificates', 'libasound2 (>= 1.0.17)', 'libatk-bridge2.0-0 (>= 2.5.3)', - 'libatk1.0-0 (>= 2.2.0)', + 'libatk1.0-0 (>= 2.11.90)', 'libatspi2.0-0 (>= 2.9.90)', 'libc6 (>= 2.16)', 'libc6 (>= 2.17)', @@ -73,7 +73,6 @@ exports.referenceGeneratedDepsByArch = { 'libcairo2 (>= 1.6.0)', 'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', 'libdbus-1-3 (>= 1.9.14)', - 'libdrm2 (>= 2.4.75)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', 'libglib2.0-0 (>= 2.37.3)', @@ -87,6 +86,7 @@ exports.referenceGeneratedDepsByArch = { 'libstdc++6 (>= 5)', 'libstdc++6 (>= 5.2)', 'libstdc++6 (>= 6)', + 'libudev1 (>= 183)', 'libx11-6', 'libx11-6 (>= 2:1.4.99.1)', 'libxcb1 (>= 1.9.2)', @@ -103,7 +103,7 @@ exports.referenceGeneratedDepsByArch = { 'ca-certificates', 'libasound2 (>= 1.0.17)', 'libatk-bridge2.0-0 (>= 2.5.3)', - 'libatk1.0-0 (>= 2.2.0)', + 'libatk1.0-0 (>= 2.11.90)', 'libatspi2.0-0 (>= 2.9.90)', 'libc6 (>= 2.17)', 'libc6 (>= 2.25)', @@ -111,7 +111,6 @@ exports.referenceGeneratedDepsByArch = { 'libcairo2 (>= 1.6.0)', 'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', 'libdbus-1-3 (>= 1.9.14)', - 'libdrm2 (>= 2.4.75)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', 'libglib2.0-0 (>= 2.37.3)', @@ -125,6 +124,7 @@ exports.referenceGeneratedDepsByArch = { 'libstdc++6 (>= 5)', 'libstdc++6 (>= 5.2)', 'libstdc++6 (>= 6)', + 'libudev1 (>= 183)', 'libx11-6', 'libx11-6 (>= 2:1.4.99.1)', 'libxcb1 (>= 1.9.2)', diff --git a/build/linux/debian/dep-lists.ts b/build/linux/debian/dep-lists.ts index e3d78d1139ad..df119e8b485e 100644 --- a/build/linux/debian/dep-lists.ts +++ b/build/linux/debian/dep-lists.ts @@ -25,7 +25,7 @@ export const referenceGeneratedDepsByArch = { 'ca-certificates', 'libasound2 (>= 1.0.17)', 'libatk-bridge2.0-0 (>= 2.5.3)', - 'libatk1.0-0 (>= 2.2.0)', + 'libatk1.0-0 (>= 2.11.90)', 'libatspi2.0-0 (>= 2.9.90)', 'libc6 (>= 2.14)', 'libc6 (>= 2.16)', @@ -36,7 +36,6 @@ export const referenceGeneratedDepsByArch = { 'libcairo2 (>= 1.6.0)', 'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', 'libdbus-1-3 (>= 1.9.14)', - 'libdrm2 (>= 2.4.75)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', 'libglib2.0-0 (>= 2.37.3)', @@ -46,6 +45,7 @@ export const referenceGeneratedDepsByArch = { 'libnss3 (>= 2:3.30)', 'libnss3 (>= 3.26)', 'libpango-1.0-0 (>= 1.14.0)', + 'libudev1 (>= 183)', 'libx11-6', 'libx11-6 (>= 2:1.4.99.1)', 'libxcb1 (>= 1.9.2)', @@ -62,7 +62,7 @@ export const referenceGeneratedDepsByArch = { 'ca-certificates', 'libasound2 (>= 1.0.17)', 'libatk-bridge2.0-0 (>= 2.5.3)', - 'libatk1.0-0 (>= 2.2.0)', + 'libatk1.0-0 (>= 2.11.90)', 'libatspi2.0-0 (>= 2.9.90)', 'libc6 (>= 2.16)', 'libc6 (>= 2.17)', @@ -73,7 +73,6 @@ export const referenceGeneratedDepsByArch = { 'libcairo2 (>= 1.6.0)', 'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', 'libdbus-1-3 (>= 1.9.14)', - 'libdrm2 (>= 2.4.75)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', 'libglib2.0-0 (>= 2.37.3)', @@ -87,6 +86,7 @@ export const referenceGeneratedDepsByArch = { 'libstdc++6 (>= 5)', 'libstdc++6 (>= 5.2)', 'libstdc++6 (>= 6)', + 'libudev1 (>= 183)', 'libx11-6', 'libx11-6 (>= 2:1.4.99.1)', 'libxcb1 (>= 1.9.2)', @@ -103,7 +103,7 @@ export const referenceGeneratedDepsByArch = { 'ca-certificates', 'libasound2 (>= 1.0.17)', 'libatk-bridge2.0-0 (>= 2.5.3)', - 'libatk1.0-0 (>= 2.2.0)', + 'libatk1.0-0 (>= 2.11.90)', 'libatspi2.0-0 (>= 2.9.90)', 'libc6 (>= 2.17)', 'libc6 (>= 2.25)', @@ -111,7 +111,6 @@ export const referenceGeneratedDepsByArch = { 'libcairo2 (>= 1.6.0)', 'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', 'libdbus-1-3 (>= 1.9.14)', - 'libdrm2 (>= 2.4.75)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', 'libglib2.0-0 (>= 2.37.3)', @@ -125,6 +124,7 @@ export const referenceGeneratedDepsByArch = { 'libstdc++6 (>= 5)', 'libstdc++6 (>= 5.2)', 'libstdc++6 (>= 6)', + 'libudev1 (>= 183)', 'libx11-6', 'libx11-6 (>= 2:1.4.99.1)', 'libxcb1 (>= 1.9.2)', diff --git a/build/linux/dependencies-generator.js b/build/linux/dependencies-generator.js index 386495598739..448ab38c4a43 100644 --- a/build/linux/dependencies-generator.js +++ b/build/linux/dependencies-generator.js @@ -26,7 +26,7 @@ const product = require("../../product.json"); // The reference dependencies, which one has to update when the new dependencies // are valid, are in dep-lists.ts const FAIL_BUILD_FOR_NEW_DEPENDENCIES = true; -// Based on https://source.chromium.org/chromium/chromium/src/+/refs/tags/128.0.6613.186:chrome/installer/linux/BUILD.gn;l=64-80 +// Based on https://source.chromium.org/chromium/chromium/src/+/refs/tags/132.0.6834.210:chrome/installer/linux/BUILD.gn;l=64-80 // and the Linux Archive build // Shared library dependencies that we already bundle. const bundledDeps = [ diff --git a/build/linux/dependencies-generator.ts b/build/linux/dependencies-generator.ts index 46be92eb8472..6c1f7b7570b5 100644 --- a/build/linux/dependencies-generator.ts +++ b/build/linux/dependencies-generator.ts @@ -25,7 +25,7 @@ import product = require('../../product.json'); // are valid, are in dep-lists.ts const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = true; -// Based on https://source.chromium.org/chromium/chromium/src/+/refs/tags/128.0.6613.186:chrome/installer/linux/BUILD.gn;l=64-80 +// Based on https://source.chromium.org/chromium/chromium/src/+/refs/tags/132.0.6834.210:chrome/installer/linux/BUILD.gn;l=64-80 // and the Linux Archive build // Shared library dependencies that we already bundle. const bundledDeps = [ diff --git a/build/linux/rpm/dep-lists.js b/build/linux/rpm/dep-lists.js index 6857f6b7c1a1..f45b6f34b843 100644 --- a/build/linux/rpm/dep-lists.js +++ b/build/linux/rpm/dep-lists.js @@ -46,13 +46,13 @@ exports.referenceGeneratedDepsByArch = { 'libc.so.6(GLIBC_2.18)(64bit)', 'libc.so.6(GLIBC_2.2.5)(64bit)', 'libc.so.6(GLIBC_2.25)(64bit)', + 'libc.so.6(GLIBC_2.27)(64bit)', 'libc.so.6(GLIBC_2.28)(64bit)', 'libc.so.6(GLIBC_2.3)(64bit)', 'libc.so.6(GLIBC_2.3.2)(64bit)', 'libc.so.6(GLIBC_2.3.3)(64bit)', 'libc.so.6(GLIBC_2.3.4)(64bit)', 'libc.so.6(GLIBC_2.4)(64bit)', - 'libc.so.6(GLIBC_2.5)(64bit)', 'libc.so.6(GLIBC_2.6)(64bit)', 'libc.so.6(GLIBC_2.7)(64bit)', 'libc.so.6(GLIBC_2.8)(64bit)', @@ -63,7 +63,6 @@ exports.referenceGeneratedDepsByArch = { 'libdbus-1.so.3(LIBDBUS_1_3)(64bit)', 'libdl.so.2()(64bit)', 'libdl.so.2(GLIBC_2.2.5)(64bit)', - 'libdrm.so.2()(64bit)', 'libexpat.so.1()(64bit)', 'libgbm.so.1()(64bit)', 'libgcc_s.so.1()(64bit)', @@ -87,6 +86,7 @@ exports.referenceGeneratedDepsByArch = { 'libnss3.so(NSS_3.30)(64bit)', 'libnss3.so(NSS_3.4)(64bit)', 'libnss3.so(NSS_3.5)(64bit)', + 'libnss3.so(NSS_3.6)(64bit)', 'libnss3.so(NSS_3.9.2)(64bit)', 'libnssutil3.so()(64bit)', 'libnssutil3.so(NSSUTIL_3.12.3)(64bit)', @@ -103,6 +103,8 @@ exports.referenceGeneratedDepsByArch = { 'libsmime3.so(NSS_3.10)(64bit)', 'libsmime3.so(NSS_3.2)(64bit)', 'libssl3.so(NSS_3.28)(64bit)', + 'libudev.so.1()(64bit)', + 'libudev.so.1(LIBUDEV_183)(64bit)', 'libutil.so.1()(64bit)', 'libutil.so.1(GLIBC_2.2.5)(64bit)', 'libxcb.so.1()(64bit)', @@ -139,9 +141,9 @@ exports.referenceGeneratedDepsByArch = { 'libc.so.6(GLIBC_2.17)', 'libc.so.6(GLIBC_2.18)', 'libc.so.6(GLIBC_2.25)', + 'libc.so.6(GLIBC_2.27)', 'libc.so.6(GLIBC_2.28)', 'libc.so.6(GLIBC_2.4)', - 'libc.so.6(GLIBC_2.5)', 'libc.so.6(GLIBC_2.6)', 'libc.so.6(GLIBC_2.7)', 'libc.so.6(GLIBC_2.8)', @@ -152,7 +154,6 @@ exports.referenceGeneratedDepsByArch = { 'libdbus-1.so.3(LIBDBUS_1_3)', 'libdl.so.2', 'libdl.so.2(GLIBC_2.4)', - 'libdrm.so.2', 'libexpat.so.1', 'libgbm.so.1', 'libgcc_s.so.1', @@ -178,6 +179,7 @@ exports.referenceGeneratedDepsByArch = { 'libnss3.so(NSS_3.30)', 'libnss3.so(NSS_3.4)', 'libnss3.so(NSS_3.5)', + 'libnss3.so(NSS_3.6)', 'libnss3.so(NSS_3.9.2)', 'libnssutil3.so', 'libnssutil3.so(NSSUTIL_3.12.3)', @@ -208,6 +210,8 @@ exports.referenceGeneratedDepsByArch = { 'libstdc++.so.6(GLIBCXX_3.4.22)', 'libstdc++.so.6(GLIBCXX_3.4.5)', 'libstdc++.so.6(GLIBCXX_3.4.9)', + 'libudev.so.1', + 'libudev.so.1(LIBUDEV_183)', 'libutil.so.1', 'libutil.so.1(GLIBC_2.4)', 'libxcb.so.1', @@ -238,6 +242,7 @@ exports.referenceGeneratedDepsByArch = { 'libc.so.6(GLIBC_2.17)(64bit)', 'libc.so.6(GLIBC_2.18)(64bit)', 'libc.so.6(GLIBC_2.25)(64bit)', + 'libc.so.6(GLIBC_2.27)(64bit)', 'libc.so.6(GLIBC_2.28)(64bit)', 'libcairo.so.2()(64bit)', 'libcurl.so.4()(64bit)', @@ -245,7 +250,6 @@ exports.referenceGeneratedDepsByArch = { 'libdbus-1.so.3(LIBDBUS_1_3)(64bit)', 'libdl.so.2()(64bit)', 'libdl.so.2(GLIBC_2.17)(64bit)', - 'libdrm.so.2()(64bit)', 'libexpat.so.1()(64bit)', 'libgbm.so.1()(64bit)', 'libgcc_s.so.1()(64bit)', @@ -270,6 +274,7 @@ exports.referenceGeneratedDepsByArch = { 'libnss3.so(NSS_3.30)(64bit)', 'libnss3.so(NSS_3.4)(64bit)', 'libnss3.so(NSS_3.5)(64bit)', + 'libnss3.so(NSS_3.6)(64bit)', 'libnss3.so(NSS_3.9.2)(64bit)', 'libnssutil3.so()(64bit)', 'libnssutil3.so(NSSUTIL_3.12.3)(64bit)', @@ -296,6 +301,8 @@ exports.referenceGeneratedDepsByArch = { 'libstdc++.so.6(GLIBCXX_3.4.22)(64bit)', 'libstdc++.so.6(GLIBCXX_3.4.5)(64bit)', 'libstdc++.so.6(GLIBCXX_3.4.9)(64bit)', + 'libudev.so.1()(64bit)', + 'libudev.so.1(LIBUDEV_183)(64bit)', 'libutil.so.1()(64bit)', 'libutil.so.1(GLIBC_2.17)(64bit)', 'libxcb.so.1()(64bit)', diff --git a/build/linux/rpm/dep-lists.ts b/build/linux/rpm/dep-lists.ts index 8fd025e51c23..d277ca7e6647 100644 --- a/build/linux/rpm/dep-lists.ts +++ b/build/linux/rpm/dep-lists.ts @@ -45,13 +45,13 @@ export const referenceGeneratedDepsByArch = { 'libc.so.6(GLIBC_2.18)(64bit)', 'libc.so.6(GLIBC_2.2.5)(64bit)', 'libc.so.6(GLIBC_2.25)(64bit)', + 'libc.so.6(GLIBC_2.27)(64bit)', 'libc.so.6(GLIBC_2.28)(64bit)', 'libc.so.6(GLIBC_2.3)(64bit)', 'libc.so.6(GLIBC_2.3.2)(64bit)', 'libc.so.6(GLIBC_2.3.3)(64bit)', 'libc.so.6(GLIBC_2.3.4)(64bit)', 'libc.so.6(GLIBC_2.4)(64bit)', - 'libc.so.6(GLIBC_2.5)(64bit)', 'libc.so.6(GLIBC_2.6)(64bit)', 'libc.so.6(GLIBC_2.7)(64bit)', 'libc.so.6(GLIBC_2.8)(64bit)', @@ -62,7 +62,6 @@ export const referenceGeneratedDepsByArch = { 'libdbus-1.so.3(LIBDBUS_1_3)(64bit)', 'libdl.so.2()(64bit)', 'libdl.so.2(GLIBC_2.2.5)(64bit)', - 'libdrm.so.2()(64bit)', 'libexpat.so.1()(64bit)', 'libgbm.so.1()(64bit)', 'libgcc_s.so.1()(64bit)', @@ -86,6 +85,7 @@ export const referenceGeneratedDepsByArch = { 'libnss3.so(NSS_3.30)(64bit)', 'libnss3.so(NSS_3.4)(64bit)', 'libnss3.so(NSS_3.5)(64bit)', + 'libnss3.so(NSS_3.6)(64bit)', 'libnss3.so(NSS_3.9.2)(64bit)', 'libnssutil3.so()(64bit)', 'libnssutil3.so(NSSUTIL_3.12.3)(64bit)', @@ -102,6 +102,8 @@ export const referenceGeneratedDepsByArch = { 'libsmime3.so(NSS_3.10)(64bit)', 'libsmime3.so(NSS_3.2)(64bit)', 'libssl3.so(NSS_3.28)(64bit)', + 'libudev.so.1()(64bit)', + 'libudev.so.1(LIBUDEV_183)(64bit)', 'libutil.so.1()(64bit)', 'libutil.so.1(GLIBC_2.2.5)(64bit)', 'libxcb.so.1()(64bit)', @@ -138,9 +140,9 @@ export const referenceGeneratedDepsByArch = { 'libc.so.6(GLIBC_2.17)', 'libc.so.6(GLIBC_2.18)', 'libc.so.6(GLIBC_2.25)', + 'libc.so.6(GLIBC_2.27)', 'libc.so.6(GLIBC_2.28)', 'libc.so.6(GLIBC_2.4)', - 'libc.so.6(GLIBC_2.5)', 'libc.so.6(GLIBC_2.6)', 'libc.so.6(GLIBC_2.7)', 'libc.so.6(GLIBC_2.8)', @@ -151,7 +153,6 @@ export const referenceGeneratedDepsByArch = { 'libdbus-1.so.3(LIBDBUS_1_3)', 'libdl.so.2', 'libdl.so.2(GLIBC_2.4)', - 'libdrm.so.2', 'libexpat.so.1', 'libgbm.so.1', 'libgcc_s.so.1', @@ -177,6 +178,7 @@ export const referenceGeneratedDepsByArch = { 'libnss3.so(NSS_3.30)', 'libnss3.so(NSS_3.4)', 'libnss3.so(NSS_3.5)', + 'libnss3.so(NSS_3.6)', 'libnss3.so(NSS_3.9.2)', 'libnssutil3.so', 'libnssutil3.so(NSSUTIL_3.12.3)', @@ -207,6 +209,8 @@ export const referenceGeneratedDepsByArch = { 'libstdc++.so.6(GLIBCXX_3.4.22)', 'libstdc++.so.6(GLIBCXX_3.4.5)', 'libstdc++.so.6(GLIBCXX_3.4.9)', + 'libudev.so.1', + 'libudev.so.1(LIBUDEV_183)', 'libutil.so.1', 'libutil.so.1(GLIBC_2.4)', 'libxcb.so.1', @@ -237,6 +241,7 @@ export const referenceGeneratedDepsByArch = { 'libc.so.6(GLIBC_2.17)(64bit)', 'libc.so.6(GLIBC_2.18)(64bit)', 'libc.so.6(GLIBC_2.25)(64bit)', + 'libc.so.6(GLIBC_2.27)(64bit)', 'libc.so.6(GLIBC_2.28)(64bit)', 'libcairo.so.2()(64bit)', 'libcurl.so.4()(64bit)', @@ -244,7 +249,6 @@ export const referenceGeneratedDepsByArch = { 'libdbus-1.so.3(LIBDBUS_1_3)(64bit)', 'libdl.so.2()(64bit)', 'libdl.so.2(GLIBC_2.17)(64bit)', - 'libdrm.so.2()(64bit)', 'libexpat.so.1()(64bit)', 'libgbm.so.1()(64bit)', 'libgcc_s.so.1()(64bit)', @@ -269,6 +273,7 @@ export const referenceGeneratedDepsByArch = { 'libnss3.so(NSS_3.30)(64bit)', 'libnss3.so(NSS_3.4)(64bit)', 'libnss3.so(NSS_3.5)(64bit)', + 'libnss3.so(NSS_3.6)(64bit)', 'libnss3.so(NSS_3.9.2)(64bit)', 'libnssutil3.so()(64bit)', 'libnssutil3.so(NSSUTIL_3.12.3)(64bit)', @@ -295,6 +300,8 @@ export const referenceGeneratedDepsByArch = { 'libstdc++.so.6(GLIBCXX_3.4.22)(64bit)', 'libstdc++.so.6(GLIBCXX_3.4.5)(64bit)', 'libstdc++.so.6(GLIBCXX_3.4.9)(64bit)', + 'libudev.so.1()(64bit)', + 'libudev.so.1(LIBUDEV_183)(64bit)', 'libutil.so.1()(64bit)', 'libutil.so.1(GLIBC_2.17)(64bit)', 'libxcb.so.1()(64bit)', diff --git a/build/monaco/monaco.d.ts.recipe b/build/monaco/monaco.d.ts.recipe index ef5c2e39ae52..6192ad5b2ec7 100644 --- a/build/monaco/monaco.d.ts.recipe +++ b/build/monaco/monaco.d.ts.recipe @@ -109,7 +109,7 @@ export interface ICommandMetadata { #include(vs/platform/markers/common/markers): IMarker, IMarkerData, IRelatedInformation #include(vs/editor/standalone/browser/colorizer): IColorizerOptions, IColorizerElementOptions #include(vs/base/common/scrollable): ScrollbarVisibility -#include(vs/base/common/themables): ThemeColor +#include(vs/base/common/themables): ThemeColor, ThemeIcon #include(vs/editor/common/core/editOperation): ISingleEditOperation #include(vs/editor/common/core/wordHelper): IWordAtPosition #includeAll(vs/editor/common/model): IScrollEvent @@ -136,7 +136,7 @@ declare namespace monaco.languages { #include(vs/editor/common/languageSelector): LanguageSelector, LanguageFilter #includeAll(vs/editor/standalone/browser/standaloneLanguages;languages.=>;editorCommon.=>editor.;model.=>editor.;IMarkerData=>editor.IMarkerData): #includeAll(vs/editor/common/languages/languageConfiguration): -#includeAll(vs/editor/common/languages;IMarkerData=>editor.IMarkerData;ISingleEditOperation=>editor.ISingleEditOperation;model.=>editor.): Token +#includeAll(vs/editor/common/languages;IMarkerData=>editor.IMarkerData;ISingleEditOperation=>editor.ISingleEditOperation;model.=>editor.;ThemeIcon=>editor.ThemeIcon): Token #include(vs/editor/common/languages/language): ILanguageExtensionPoint #includeAll(vs/editor/standalone/common/monarch/monarchTypes): diff --git a/build/npm/gyp/package-lock.json b/build/npm/gyp/package-lock.json index a20d85c70dca..af64f402f659 100644 --- a/build/npm/gyp/package-lock.json +++ b/build/npm/gyp/package-lock.json @@ -9,7 +9,30 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "node-gyp": "^10.1.0" + "node-gyp": "^12.1.0" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" } }, "node_modules/@isaacs/cliui": { @@ -30,88 +53,73 @@ "node": ">=12" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@npmcli/agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", - "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.0.tgz", + "integrity": "sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==", "dev": true, "license": "ISC", "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", + "lru-cache": "^11.2.1", "socks-proxy-agent": "^8.0.3" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/@npmcli/fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", - "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, "license": "ISC", "dependencies": { "semver": "^7.3.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, "engines": { "node": ">= 14" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { @@ -122,9 +130,9 @@ } }, "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", "engines": { @@ -134,65 +142,37 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/cacache": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.3.tgz", - "integrity": "sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg==", + "version": "20.0.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-20.0.2.tgz", + "integrity": "sha512-rVWvqtWcgSzB22wImrVto+7PmE+lUqv5dYzRHD0QJsfpSwTkW+GIqA4ykSt/CCjQlQle8USn8CO8vcWNrIqktg==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^3.1.0", + "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", + "glob": "^11.0.3", + "lru-cache": "^11.1.0", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "p-map": "^7.0.2", + "ssri": "^13.0.0", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=6" + "node": ">=18" } }, "node_modules/color-convert": { @@ -216,9 +196,9 @@ "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -254,13 +234,13 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -320,14 +300,32 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -351,24 +349,24 @@ } }, "node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -382,9 +380,9 @@ "license": "ISC" }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "dev": true, "license": "BSD-2-Clause" }, @@ -403,13 +401,13 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { @@ -440,26 +438,12 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", "dev": true, "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, "engines": { "node": ">= 12" } @@ -474,13 +458,6 @@ "node": ">=8" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/isexe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", @@ -492,86 +469,65 @@ } }, "node_modules/jackspeak": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", - "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">=14" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, - "license": "MIT" - }, "node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", "dev": true, "license": "ISC", "engines": { - "node": "14 || >=16.14" + "node": "20 || >=22" } }, "node_modules/make-fetch-happen": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", - "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz", + "integrity": "sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", + "@npmcli/agent": "^4.0.0", + "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", + "minipass-fetch": "^5.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", + "negotiator": "^1.0.0", + "proc-log": "^6.0.0", "promise-retry": "^2.0.1", - "ssri": "^10.0.0" + "ssri": "^13.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/proc-log": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", - "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "@isaacs/brace-expansion": "^5.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -601,18 +557,18 @@ } }, "node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.0.tgz", + "integrity": "sha512-fiCdUALipqgPWrOVTz9fw0XhcazULXOSU6ie40DDbX1F49p1dBrSRBuswndTx1x3vEb/g0FT7vC4c4C2u/mh3A==", "dev": true, "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minizlib": "^3.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" }, "optionalDependencies": { "encoding": "^0.1.13" @@ -644,6 +600,13 @@ "node": ">=8" } }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", @@ -670,6 +633,13 @@ "node": ">=8" } }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", @@ -696,57 +666,37 @@ "node": ">=8" } }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } + "license": "ISC" }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", "dev": true, "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" + "dependencies": { + "minipass": "^7.1.2" }, "engines": { - "node": ">=10" + "node": ">= 18" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, "license": "MIT", "engines": { @@ -754,66 +704,63 @@ } }, "node_modules/node-gyp": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.1.0.tgz", - "integrity": "sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.1.0.tgz", + "integrity": "sha512-W+RYA8jBnhSr2vrTtlPYPc1K+CSjGpVDRZxcqJcERZ8ND3A1ThWPHRwctTx3qC3oW99jt726jhdz3Y6ky87J4g==", "dev": true, "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", + "make-fetch-happen": "^15.0.0", + "nopt": "^9.0.0", + "proc-log": "^6.0.0", "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^4.0.0" + "tar": "^7.5.2", + "tinyglobby": "^0.2.12", + "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/nopt": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", - "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", "dev": true, "license": "ISC", "dependencies": { - "abbrev": "^2.0.0" + "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, "license": "BlueOak-1.0.0" }, @@ -828,30 +775,43 @@ } }, "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.0.0.tgz", + "integrity": "sha512-KG/XsTDN901PNfPfAMmj6N/Ywg9tM+bHK8pAz+27fS4N4Pcr+4zoYBOcGSBu6ceXYNPxkLpa4ohtfxV1XcLAfA==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/promise-retry": { @@ -887,14 +847,11 @@ "optional": true }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -902,19 +859,6 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -963,13 +907,13 @@ } }, "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "dev": true, "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", + "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -978,13 +922,13 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.1", + "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" }, @@ -992,24 +936,17 @@ "node": ">= 14" } }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.0.tgz", + "integrity": "sha512-yizwGBpbCn4YomB2lzhZqrHLJoqFGXihNbib3ozhqF/cIp5ue+xSmOQrjNasEE62hFxsCcg/V/z23t4n8jMEng==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/string-width": { @@ -1077,9 +1014,9 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { @@ -1117,89 +1054,69 @@ } }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", + "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^3.0.0" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" + "node": ">=12.0.0" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^4.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", + "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", "dev": true, "license": "ISC", "dependencies": { @@ -1209,7 +1126,7 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/wrap-ansi": { @@ -1311,11 +1228,14 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", "dev": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } } } } diff --git a/build/npm/gyp/package.json b/build/npm/gyp/package.json index a1564133a1ee..1b869649d321 100644 --- a/build/npm/gyp/package.json +++ b/build/npm/gyp/package.json @@ -4,7 +4,7 @@ "private": true, "license": "MIT", "devDependencies": { - "node-gyp": "^10.1.0" + "node-gyp": "^12.1.0" }, "scripts": {} } diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index c1f22aa50024..458847afac58 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -85,7 +85,7 @@ function setNpmrcConfig(dir, env) { // the correct clang variable. So keep the version check // in preinstall sync with this logic. // Change was first introduced in https://github.com/nodejs/node/commit/6e0a2bb54c5bbeff0e9e33e1a0c683ed980a8a0f - if (dir === 'remote' && process.platform === 'darwin') { + if ((dir === 'remote' || dir === 'build') && process.platform === 'darwin') { env['npm_config_force_process_config'] = 'true'; } else { delete env['npm_config_force_process_config']; diff --git a/build/package-lock.json b/build/package-lock.json index 801e8eb1ed62..93fdaa4335e7 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -47,7 +47,7 @@ "byline": "^5.0.0", "debug": "^4.3.2", "electron-osx-sign": "^0.4.16", - "esbuild": "0.23.0", + "esbuild": "0.25.0", "extract-zip": "^2.0.1", "gulp-merge-json": "^2.1.1", "gulp-sort": "^2.0.0", @@ -488,13 +488,14 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", + "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" @@ -504,13 +505,14 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -520,13 +522,14 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -536,13 +539,14 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -552,13 +556,14 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -568,13 +573,14 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -584,13 +590,14 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -600,13 +607,14 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -616,13 +624,14 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -632,13 +641,14 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -648,13 +658,14 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -664,13 +675,14 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -680,13 +692,14 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -696,13 +709,14 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -712,13 +726,14 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -728,13 +743,14 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -744,13 +760,14 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -759,14 +776,32 @@ "node": ">=18" } }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", + "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -776,13 +811,14 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", + "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -792,13 +828,14 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -808,13 +845,14 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -824,13 +862,14 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -840,13 +879,14 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -856,13 +896,14 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -1566,10 +1607,11 @@ "optional": true }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2228,11 +2270,12 @@ "optional": true }, "node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -2240,30 +2283,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" } }, "node_modules/escape-string-regexp": { @@ -4073,10 +4117,11 @@ } }, "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "devOptional": true, + "license": "MIT", "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -4147,10 +4192,11 @@ } }, "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.14" } @@ -4374,10 +4420,11 @@ } }, "node_modules/vscode-universal-bundler/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } diff --git a/build/package.json b/build/package.json index 76caffbce891..3a435a8326bf 100644 --- a/build/package.json +++ b/build/package.json @@ -41,7 +41,7 @@ "byline": "^5.0.0", "debug": "^4.3.2", "electron-osx-sign": "^0.4.16", - "esbuild": "0.23.0", + "esbuild": "0.25.0", "extract-zip": "^2.0.1", "gulp-merge-json": "^2.1.1", "gulp-sort": "^2.0.0", diff --git a/build/win32/Cargo.lock b/build/win32/Cargo.lock index 4c169ba0f973..5437686ef940 100644 --- a/build/win32/Cargo.lock +++ b/build/win32/Cargo.lock @@ -95,7 +95,7 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "inno_updater" -version = "0.12.1" +version = "0.13.2" dependencies = [ "byteorder", "crc", diff --git a/build/win32/Cargo.toml b/build/win32/Cargo.toml index e2130dd2bfae..42958b3124a9 100644 --- a/build/win32/Cargo.toml +++ b/build/win32/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "inno_updater" -version = "0.12.1" +version = "0.13.2" authors = ["Microsoft "] build = "build.rs" diff --git a/build/win32/inno_updater.exe b/build/win32/inno_updater.exe index ef7cb934eb63..2ca110dea1fd 100644 Binary files a/build/win32/inno_updater.exe and b/build/win32/inno_updater.exe differ diff --git a/cgmanifest.json b/cgmanifest.json index 1795c44c9372..eb5b37d39a75 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "chromium", "repositoryUrl": "https://chromium.googlesource.com/chromium/src", - "commitHash": "545591e4a0b85ce8937a0ce751bacdc0fe92f1ed" + "commitHash": "5c0cb964bca15fcf41718d54f4b8d70d6b9079de" } }, "licenseDetail": [ @@ -40,7 +40,7 @@ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ], "isOnlyProductionDependency": true, - "version": "128.0.6613.186" + "version": "132.0.6834.210" }, { "component": { @@ -516,11 +516,11 @@ "git": { "name": "nodejs", "repositoryUrl": "https://github.com/nodejs/node", - "commitHash": "70178110a8e52d28dc957b6b20da94e455922025" + "commitHash": "4819c99baa28bf2c1baf411ba100c467fec3d486" } }, "isOnlyProductionDependency": true, - "version": "20.18.1" + "version": "20.18.3" }, { "component": { @@ -528,12 +528,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "3007f859dad930ae80bafffc6042a146a45e4e4d" + "commitHash": "f98501308a973e0aee2414315b426e5de2c03a60" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "32.2.7" + "version": "34.3.2" }, { "component": { diff --git a/cli/Cargo.lock b/cli/Cargo.lock index ff45765a0c1d..c5f398e34876 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -536,9 +536,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] @@ -1717,9 +1717,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.70" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ "bitflags 2.5.0", "cfg-if", @@ -1749,9 +1749,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.105" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -2676,9 +2676,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "68722da18b0fc4a05fdc1120b302b82051265792a1e1b399086e9b204b10ad3d" dependencies = [ "backtrace", "bytes", @@ -2696,9 +2696,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 2c87d662e073..95efef30d75f 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -16,7 +16,7 @@ futures = "0.3.28" clap = { version = "4.3.0", features = ["derive", "env"] } open = "4.1.0" reqwest = { version = "0.11.22", default-features = false, features = ["json", "stream", "native-tls"] } -tokio = { version = "1.28.2", features = ["full"] } +tokio = { version = "1.38.2", features = ["full"] } tokio-util = { version = "0.7.8", features = ["compat", "codec"] } flate2 = { version = "1.0.26", default-features = false, features = ["zlib"] } zip = { version = "0.6.6", default-features = false, features = ["time", "deflate-zlib"] } diff --git a/cli/ThirdPartyNotices.txt b/cli/ThirdPartyNotices.txt index 03ac5838391f..cc255c04cfdc 100644 --- a/cli/ThirdPartyNotices.txt +++ b/cli/ThirdPartyNotices.txt @@ -684,16 +684,6 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [deps-image]: https://deps.rs/repo/github/RustCrypto/utils/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/utils -[msrv-1.39]: https://img.shields.io/badge/rustc-1.39.0+-blue.svg -[msrv-1.40]: https://img.shields.io/badge/rustc-1.40.0+-blue.svg -[msrv-1.41]: https://img.shields.io/badge/rustc-1.41.0+-blue.svg -[msrv-1.45]: https://img.shields.io/badge/rustc-1.45.0+-blue.svg -[msrv-1.51]: https://img.shields.io/badge/rustc-1.51.0+-blue.svg -[msrv-1.56]: https://img.shields.io/badge/rustc-1.56.0+-blue.svg -[msrv-1.57]: https://img.shields.io/badge/rustc-1.57.0+-blue.svg -[msrv-1.59]: https://img.shields.io/badge/rustc-1.59.0+-blue.svg -[msrv-1.60]: https://img.shields.io/badge/rustc-1.60.0+-blue.svg - [//]: # (crates) [`blobby`]: ./blobby @@ -738,16 +728,6 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [deps-image]: https://deps.rs/repo/github/RustCrypto/utils/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/utils -[msrv-1.39]: https://img.shields.io/badge/rustc-1.39.0+-blue.svg -[msrv-1.40]: https://img.shields.io/badge/rustc-1.40.0+-blue.svg -[msrv-1.41]: https://img.shields.io/badge/rustc-1.41.0+-blue.svg -[msrv-1.45]: https://img.shields.io/badge/rustc-1.45.0+-blue.svg -[msrv-1.51]: https://img.shields.io/badge/rustc-1.51.0+-blue.svg -[msrv-1.56]: https://img.shields.io/badge/rustc-1.56.0+-blue.svg -[msrv-1.57]: https://img.shields.io/badge/rustc-1.57.0+-blue.svg -[msrv-1.59]: https://img.shields.io/badge/rustc-1.59.0+-blue.svg -[msrv-1.60]: https://img.shields.io/badge/rustc-1.60.0+-blue.svg - [//]: # (crates) [`blobby`]: ./blobby @@ -962,7 +942,7 @@ chrono 0.4.38 - MIT OR Apache-2.0 https://github.com/chronotope/chrono Rust-chrono is dual-licensed under The MIT License [1] and -Apache 2.0 License [2]. Copyright (c) 2014--2017, Kang Seonghoon and +Apache 2.0 License [2]. Copyright (c) 2014--2025, Kang Seonghoon and contributors. Nota Bene: This is same as the Rust Project's own license. @@ -1525,16 +1505,6 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [deps-image]: https://deps.rs/repo/github/RustCrypto/utils/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/utils -[msrv-1.39]: https://img.shields.io/badge/rustc-1.39.0+-blue.svg -[msrv-1.40]: https://img.shields.io/badge/rustc-1.40.0+-blue.svg -[msrv-1.41]: https://img.shields.io/badge/rustc-1.41.0+-blue.svg -[msrv-1.45]: https://img.shields.io/badge/rustc-1.45.0+-blue.svg -[msrv-1.51]: https://img.shields.io/badge/rustc-1.51.0+-blue.svg -[msrv-1.56]: https://img.shields.io/badge/rustc-1.56.0+-blue.svg -[msrv-1.57]: https://img.shields.io/badge/rustc-1.57.0+-blue.svg -[msrv-1.59]: https://img.shields.io/badge/rustc-1.59.0+-blue.svg -[msrv-1.60]: https://img.shields.io/badge/rustc-1.60.0+-blue.svg - [//]: # (crates) [`blobby`]: ./blobby @@ -1674,10 +1644,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg [deps-image]: https://deps.rs/repo/github/RustCrypto/traits/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/traits -[msrv-1.56]: https://img.shields.io/badge/rustc-1.56.0+-blue.svg -[msrv-1.57]: https://img.shields.io/badge/rustc-1.57.0+-blue.svg -[msrv-1.60]: https://img.shields.io/badge/rustc-1.60.0+-blue.svg -[msrv-1.65]: https://img.shields.io/badge/rustc-1.65.0+-blue.svg +[msrv-1.85]: https://img.shields.io/badge/rustc-1.85.0+-blue.svg [//]: # (crates) @@ -1839,10 +1806,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg [deps-image]: https://deps.rs/repo/github/RustCrypto/traits/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/traits -[msrv-1.56]: https://img.shields.io/badge/rustc-1.56.0+-blue.svg -[msrv-1.57]: https://img.shields.io/badge/rustc-1.57.0+-blue.svg -[msrv-1.60]: https://img.shields.io/badge/rustc-1.60.0+-blue.svg -[msrv-1.65]: https://img.shields.io/badge/rustc-1.65.0+-blue.svg +[msrv-1.85]: https://img.shields.io/badge/rustc-1.85.0+-blue.svg [//]: # (crates) @@ -2272,7 +2236,7 @@ DEALINGS IN THE SOFTWARE. flate2 1.0.30 - MIT OR Apache-2.0 https://github.com/rust-lang/flate2-rs -Copyright (c) 2014 Alex Crichton +Copyright (c) 2014-2025 Alex Crichton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -2388,7 +2352,7 @@ SOFTWARE. form_urlencoded 1.2.1 - MIT OR Apache-2.0 https://github.com/servo/rust-url -Copyright (c) 2013-2022 The rust-url developers +Copyright (c) 2013-2025 The rust-url developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -3225,16 +3189,6 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [deps-image]: https://deps.rs/repo/github/RustCrypto/utils/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/utils -[msrv-1.39]: https://img.shields.io/badge/rustc-1.39.0+-blue.svg -[msrv-1.40]: https://img.shields.io/badge/rustc-1.40.0+-blue.svg -[msrv-1.41]: https://img.shields.io/badge/rustc-1.41.0+-blue.svg -[msrv-1.45]: https://img.shields.io/badge/rustc-1.45.0+-blue.svg -[msrv-1.51]: https://img.shields.io/badge/rustc-1.51.0+-blue.svg -[msrv-1.56]: https://img.shields.io/badge/rustc-1.56.0+-blue.svg -[msrv-1.57]: https://img.shields.io/badge/rustc-1.57.0+-blue.svg -[msrv-1.59]: https://img.shields.io/badge/rustc-1.59.0+-blue.svg -[msrv-1.60]: https://img.shields.io/badge/rustc-1.60.0+-blue.svg - [//]: # (crates) [`blobby`]: ./blobby @@ -3278,9 +3232,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg [deps-image]: https://deps.rs/repo/github/RustCrypto/MACs/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/MACs -[msrv-1.41]: https://img.shields.io/badge/rustc-1.41.0+-blue.svg -[msrv-1.81]: https://img.shields.io/badge/rustc-1.56.0+-blue.svg -[msrv-1.57]: https://img.shields.io/badge/rustc-1.57.0+-blue.svg +[msrv-1.85]: https://img.shields.io/badge/rustc-1.85.0+-blue.svg [//]: # (crates) @@ -3344,7 +3296,7 @@ https://github.com/hyperium/http-body The MIT License (MIT) -Copyright (c) 2019-2024 Sean McArthur & Hyper Contributors +Copyright (c) 2019-2025 Sean McArthur & Hyper Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -3376,7 +3328,7 @@ DEALINGS IN THE SOFTWARE. httparse 1.8.0 - MIT/Apache-2.0 https://github.com/seanmonstar/httparse -Copyright (c) 2015-2024 Sean McArthur +Copyright (c) 2015-2025 Sean McArthur Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3430,7 +3382,7 @@ https://github.com/hyperium/hyper The MIT License (MIT) -Copyright (c) 2014-2021 Sean McArthur +Copyright (c) 2014-2025 Sean McArthur Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -4076,7 +4028,7 @@ ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation a idna 1.0.3 - MIT OR Apache-2.0 https://github.com/servo/rust-url/ -Copyright (c) 2013-2022 The rust-url developers +Copyright (c) 2013-2025 The rust-url developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -4220,16 +4172,6 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [deps-image]: https://deps.rs/repo/github/RustCrypto/utils/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/utils -[msrv-1.39]: https://img.shields.io/badge/rustc-1.39.0+-blue.svg -[msrv-1.40]: https://img.shields.io/badge/rustc-1.40.0+-blue.svg -[msrv-1.41]: https://img.shields.io/badge/rustc-1.41.0+-blue.svg -[msrv-1.45]: https://img.shields.io/badge/rustc-1.45.0+-blue.svg -[msrv-1.51]: https://img.shields.io/badge/rustc-1.51.0+-blue.svg -[msrv-1.56]: https://img.shields.io/badge/rustc-1.56.0+-blue.svg -[msrv-1.57]: https://img.shields.io/badge/rustc-1.57.0+-blue.svg -[msrv-1.59]: https://img.shields.io/badge/rustc-1.59.0+-blue.svg -[msrv-1.60]: https://img.shields.io/badge/rustc-1.60.0+-blue.svg - [//]: # (crates) [`blobby`]: ./blobby @@ -4509,8 +4451,6 @@ DEALINGS IN THE SOFTWARE. lazy_static 1.4.0 - MIT/Apache-2.0 https://github.com/rust-lang-nursery/lazy-static.rs -Copyright (c) 2010 The Rust Project Developers - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the @@ -5315,7 +5255,7 @@ DEALINGS IN THE SOFTWARE. num_cpus 1.16.0 - MIT OR Apache-2.0 https://github.com/seanmonstar/num_cpus -Copyright (c) 2015 +Copyright (c) 2015-2025 Sean McArthur Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -5459,7 +5399,7 @@ OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -openssl 0.10.66 - Apache-2.0 +openssl 0.10.70 - Apache-2.0 https://github.com/sfackler/rust-openssl Copyright 2011-2017 Google Inc. @@ -5538,7 +5478,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -openssl-sys 0.9.103 - MIT +openssl-sys 0.9.105 - MIT https://github.com/sfackler/rust-openssl The MIT License (MIT) @@ -6791,7 +6731,7 @@ DEALINGS IN THE SOFTWARE. percent-encoding 2.3.1 - MIT OR Apache-2.0 https://github.com/servo/rust-url/ -Copyright (c) 2013-2022 The rust-url developers +Copyright (c) 2013-2025 The rust-url developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -7505,7 +7445,7 @@ DEALINGS IN THE SOFTWARE. reqwest 0.11.27 - MIT OR Apache-2.0 https://github.com/seanmonstar/reqwest -Copyright (c) 2016 Sean McArthur +Copyright (c) 2016-2025 Sean McArthur Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -8358,7 +8298,7 @@ DEALINGS IN THE SOFTWARE. secret-service 3.0.1 - MIT OR Apache-2.0 https://github.com/hwchen/secret-service-rs -Copyright (c) 2016 secret-service Developers +Copyright (c) 2025 secret-service Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -8644,7 +8584,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg [deps-image]: https://deps.rs/repo/github/RustCrypto/hashes/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/hashes -[msrv-1.81]: https://img.shields.io/badge/rustc-1.81.0+-blue.svg +[msrv-1.85]: https://img.shields.io/badge/rustc-1.85.0+-blue.svg [//]: # (crates) @@ -8737,7 +8677,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg [deps-image]: https://deps.rs/repo/github/RustCrypto/hashes/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/hashes -[msrv-1.81]: https://img.shields.io/badge/rustc-1.81.0+-blue.svg +[msrv-1.85]: https://img.shields.io/badge/rustc-1.85.0+-blue.svg [//]: # (crates) @@ -10049,7 +9989,7 @@ https://github.com/seanmonstar/try-lock The MIT License (MIT) -Copyright (c) 2018-2023 Sean McArthur +Copyright (c) 2018-2025 Sean McArthur Copyright (c) 2016 Alex Crichton Permission is hereby granted, free of charge, to any person obtaining a copy @@ -10261,7 +10201,7 @@ DEALINGS IN THE SOFTWARE. url 2.5.4 - MIT OR Apache-2.0 https://github.com/servo/rust-url -Copyright (c) 2013-2022 The rust-url developers +Copyright (c) 2013-2025 The rust-url developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -11829,16 +11769,6 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [deps-image]: https://deps.rs/repo/github/RustCrypto/utils/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/utils -[msrv-1.39]: https://img.shields.io/badge/rustc-1.39.0+-blue.svg -[msrv-1.40]: https://img.shields.io/badge/rustc-1.40.0+-blue.svg -[msrv-1.41]: https://img.shields.io/badge/rustc-1.41.0+-blue.svg -[msrv-1.45]: https://img.shields.io/badge/rustc-1.45.0+-blue.svg -[msrv-1.51]: https://img.shields.io/badge/rustc-1.51.0+-blue.svg -[msrv-1.56]: https://img.shields.io/badge/rustc-1.56.0+-blue.svg -[msrv-1.57]: https://img.shields.io/badge/rustc-1.57.0+-blue.svg -[msrv-1.59]: https://img.shields.io/badge/rustc-1.59.0+-blue.svg -[msrv-1.60]: https://img.shields.io/badge/rustc-1.60.0+-blue.svg - [//]: # (crates) [`blobby`]: ./blobby diff --git a/cli/src/auth.rs b/cli/src/auth.rs index 9308fa3283ba..d4d62a8bf104 100644 --- a/cli/src/auth.rs +++ b/cli/src/auth.rs @@ -104,7 +104,7 @@ impl AuthProvider { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct StoredCredential { #[serde(rename = "p")] - provider: AuthProvider, + pub(crate) provider: AuthProvider, #[serde(rename = "a")] access_token: String, #[serde(rename = "r")] @@ -665,12 +665,12 @@ impl Auth { .into(); } - return StatusError { + StatusError { body: String::from_utf8_lossy(&body).to_string(), status_code, url: url.to_string(), } - .into(); + .into() } /// Implements the device code flow, returning the credentials upon success. async fn do_device_code_flow(&self) -> Result { diff --git a/cli/src/commands/args.rs b/cli/src/commands/args.rs index b9f7b3b7875d..52020627ca59 100644 --- a/cli/src/commands/args.rs +++ b/cli/src/commands/args.rs @@ -216,12 +216,6 @@ pub struct ServeWebArgs { /// Specifies the directory that server data is kept in. #[clap(long)] pub server_data_dir: Option, - /// Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code. - #[clap(long)] - pub user_data_dir: Option, - /// Set the root path for extensions. - #[clap(long)] - pub extensions_dir: Option, } #[derive(Args, Debug, Clone)] diff --git a/cli/src/commands/serve_web.rs b/cli/src/commands/serve_web.rs index ddef3eef3421..2ddefe130833 100644 --- a/cli/src/commands/serve_web.rs +++ b/cli/src/commands/serve_web.rs @@ -778,14 +778,6 @@ impl ConnectionManager { cmd.arg("--server-data-dir"); cmd.arg(a); } - if let Some(a) = &args.args.user_data_dir { - cmd.arg("--user-data-dir"); - cmd.arg(a); - } - if let Some(a) = &args.args.extensions_dir { - cmd.arg("--extensions-dir"); - cmd.arg(a); - } if args.args.without_connection_token { cmd.arg("--without-connection-token"); } diff --git a/cli/src/commands/tunnels.rs b/cli/src/commands/tunnels.rs index f52fa714793b..06d8dc842262 100644 --- a/cli/src/commands/tunnels.rs +++ b/cli/src/commands/tunnels.rs @@ -329,8 +329,8 @@ pub async fn user(ctx: CommandContext, user_args: TunnelUserSubCommands) -> Resu auth.clear_credentials()?; } TunnelUserSubCommands::Show => { - if let Ok(Some(_)) = auth.get_current_credential() { - ctx.log.result("logged in"); + if let Ok(Some(sc)) = auth.get_current_credential() { + ctx.log.result(format!("logged in with provider {}", sc.provider)); } else { ctx.log.result("not logged in"); return Ok(1); diff --git a/cli/src/log.rs b/cli/src/log.rs index 538827ed1242..f58f49b21764 100644 --- a/cli/src/log.rs +++ b/cli/src/log.rs @@ -282,7 +282,7 @@ pub struct DownloadLogger<'a> { logger: &'a Logger, } -impl<'a> crate::util::io::ReportCopyProgress for DownloadLogger<'a> { +impl crate::util::io::ReportCopyProgress for DownloadLogger<'_> { fn report_progress(&mut self, bytes_so_far: u64, total_bytes: u64) { if total_bytes > 0 { self.logger.emit( diff --git a/cli/src/tunnels/singleton_server.rs b/cli/src/tunnels/singleton_server.rs index 7fbd00d04d34..f183f935ce30 100644 --- a/cli/src/tunnels/singleton_server.rs +++ b/cli/src/tunnels/singleton_server.rs @@ -142,7 +142,7 @@ pub fn make_singleton_server( } } -pub async fn start_singleton_server<'a>( +pub async fn start_singleton_server( args: SingletonServerArgs<'_>, ) -> Result { let shutdown_rx = ShutdownRequest::create_rx([ diff --git a/cli/src/util/io.rs b/cli/src/util/io.rs index c5816ae55adb..4b8118a219f8 100644 --- a/cli/src/util/io.rs +++ b/cli/src/util/io.rs @@ -235,6 +235,7 @@ mod tests { .write(true) .read(true) .create(true) + .truncate(true) .open(&file_path) .unwrap(); @@ -271,6 +272,7 @@ mod tests { .write(true) .read(true) .create(true) + .truncate(true) .open(&file_path) .unwrap(); @@ -305,6 +307,7 @@ mod tests { .write(true) .read(true) .create(true) + .truncate(true) .open(&file_path) .unwrap(); let mut rng = rand::thread_rng(); diff --git a/cli/src/util/prereqs.rs b/cli/src/util/prereqs.rs index f8eff34ec39c..44c859772e38 100644 --- a/cli/src/util/prereqs.rs +++ b/cli/src/util/prereqs.rs @@ -20,19 +20,16 @@ lazy_static! { static ref LIBSTD_CXX_VERSION_RE: BinRegex = BinRegex::new(r"GLIBCXX_([0-9]+)\.([0-9]+)(?:\.([0-9]+))?").unwrap(); static ref MIN_LDD_VERSION: SimpleSemver = SimpleSemver::new(2, 28, 0); - static ref MIN_LEGACY_LDD_VERSION: SimpleSemver = SimpleSemver::new(2, 17, 0); } #[cfg(target_arch = "arm")] lazy_static! { static ref MIN_CXX_VERSION: SimpleSemver = SimpleSemver::new(3, 4, 26); - static ref MIN_LEGACY_CXX_VERSION: SimpleSemver = SimpleSemver::new(3, 4, 22); } #[cfg(not(target_arch = "arm"))] lazy_static! { static ref MIN_CXX_VERSION: SimpleSemver = SimpleSemver::new(3, 4, 25); - static ref MIN_LEGACY_CXX_VERSION: SimpleSemver = SimpleSemver::new(3, 4, 19); } const NIXOS_TEST_PATH: &str = "/etc/NIXOS"; @@ -74,12 +71,11 @@ impl PreReqChecker { } else { println!("!!! WARNING: Skipping server pre-requisite check !!!"); println!("!!! Server stability is not guaranteed. Proceed at your own risk. !!!"); - // Use the legacy server for #210029 (Ok(true), Ok(true)) }; match (&gnu_a, &gnu_b, is_nixos) { - (Ok(false), Ok(false), _) | (_, _, true) => { + (Ok(true), Ok(true), _) | (_, _, true) => { return Ok(if cfg!(target_arch = "x86_64") { Platform::LinuxX64 } else if cfg!(target_arch = "arm") { @@ -88,15 +84,6 @@ impl PreReqChecker { Platform::LinuxARM64 }); } - (Ok(_), Ok(_), _) => { - return Ok(if cfg!(target_arch = "x86_64") { - Platform::LinuxX64Legacy - } else if cfg!(target_arch = "arm") { - Platform::LinuxARM32Legacy - } else { - Platform::LinuxARM64Legacy - }); - } _ => {} }; @@ -149,7 +136,7 @@ async fn check_musl_interpreter() -> Result<(), String> { Ok(()) } -/// Checks the glibc version, returns "true" if the legacy server is required. +/// Checks the glibc version, returns "true" if the default server is required. #[cfg(target_os = "linux")] async fn check_glibc_version() -> Result { #[cfg(target_env = "gnu")] @@ -169,8 +156,6 @@ async fn check_glibc_version() -> Result { if let Some(v) = version { return if v >= *MIN_LDD_VERSION { - Ok(false) - } else if v >= *MIN_LEGACY_LDD_VERSION { Ok(true) } else { Err(format!( @@ -192,10 +177,17 @@ async fn check_is_nixos() -> bool { /// Do not remove this check. /// Provides a way to skip the server glibc requirements check from -/// outside the install flow. A system process can create this -/// file before the server is downloaded and installed. +/// outside the install flow. +/// +/// 1) A system process can create this +/// file before the server is downloaded and installed. +/// +/// 2) An environment variable declared in host +/// that contains path to a glibc sysroot satisfying the +/// minimum requirements. #[cfg(not(windows))] pub async fn skip_requirements_check() -> bool { + std::env::var("VSCODE_SERVER_CUSTOM_GLIBC_LINKER").is_ok() || fs::metadata("/tmp/vscode-skip-server-requirements-check") .await .is_ok() @@ -206,7 +198,7 @@ pub async fn skip_requirements_check() -> bool { false } -/// Checks the glibc++ version, returns "true" if the legacy server is required. +/// Checks the glibc++ version, returns "true" if the default server is required. #[cfg(target_os = "linux")] async fn check_glibcxx_version() -> Result { let mut libstdc_path: Option = None; @@ -250,10 +242,6 @@ fn check_for_sufficient_glibcxx_versions(contents: Vec) -> Result= &*MIN_CXX_VERSION { - return Ok(false); - } - - if max_version >= &*MIN_LEGACY_CXX_VERSION { return Ok(true); } } diff --git a/eslint.config.js b/eslint.config.js index b3167b40a5c7..8e3d288967b3 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -224,15 +224,12 @@ export default tseslint.config( 'src/vs/platform/registry/test/common/platform.test.ts', 'src/vs/platform/workspace/test/common/workspace.test.ts', 'src/vs/platform/workspaces/test/electron-main/workspaces.test.ts', - 'src/vs/workbench/api/test/browser/mainThreadConfiguration.test.ts', - 'src/vs/workbench/api/test/node/extHostTunnelService.test.ts', 'src/vs/workbench/contrib/bulkEdit/test/browser/bulkCellEdits.test.ts', 'src/vs/workbench/contrib/chat/test/common/chatWordCounter.test.ts', 'src/vs/workbench/contrib/extensions/test/common/extensionQuery.test.ts', 'src/vs/workbench/contrib/notebook/test/browser/notebookExecutionService.test.ts', 'src/vs/workbench/contrib/notebook/test/browser/notebookExecutionStateService.test.ts', 'src/vs/workbench/contrib/tasks/test/common/problemMatcher.test.ts', - 'src/vs/workbench/contrib/tasks/test/common/taskConfiguration.test.ts', 'src/vs/workbench/services/commands/test/common/commandService.test.ts', 'src/vs/workbench/services/userActivity/test/browser/domActivityTracker.test.ts', 'src/vs/workbench/test/browser/quickAccess.test.ts' @@ -268,7 +265,6 @@ export default tseslint.config( 'local/vscode-dts-cancellation': 'warn', 'local/vscode-dts-use-export': 'warn', 'local/vscode-dts-use-thenable': 'warn', - 'local/vscode-dts-region-comments': 'warn', 'local/vscode-dts-vscode-in-comments': 'warn', 'local/vscode-dts-provider-naming': [ 'warn', diff --git a/extensions/coffeescript/package.json b/extensions/coffeescript/package.json index 8480ca1f9ab0..615138a280a9 100644 --- a/extensions/coffeescript/package.json +++ b/extensions/coffeescript/package.json @@ -50,7 +50,7 @@ "configurationDefaults": { "[coffeescript]": { "diffEditor.ignoreTrimWhitespace": false, - "editor.defaultColorDecorators": false + "editor.defaultColorDecorators": "never" } } }, diff --git a/extensions/configuration-editing/package-lock.json b/extensions/configuration-editing/package-lock.json index 199dcf7f7554..cba3a0fece64 100644 --- a/extensions/configuration-editing/package-lock.json +++ b/extensions/configuration-editing/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@octokit/rest": "19.0.4", + "@octokit/rest": "^21.1.1", "jsonc-parser": "^3.2.0", "tunnel": "^0.0.6" }, @@ -21,173 +21,157 @@ } }, "node_modules/@octokit/auth-token": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", - "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", + "license": "MIT", "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz", - "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz", + "integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==", + "license": "MIT", "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.1.2", + "@octokit/request": "^9.2.1", + "@octokit/request-error": "^6.1.7", + "@octokit/types": "^13.6.2", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/endpoint": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", - "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz", + "integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==", + "license": "MIT", "dependencies": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" + "@octokit/types": "^13.6.2", + "universal-user-agent": "^7.0.2" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/graphql": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", - "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.1.tgz", + "integrity": "sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==", + "license": "MIT", "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" + "@octokit/request": "^9.2.2", + "@octokit/types": "^13.8.0", + "universal-user-agent": "^7.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/openapi-types": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", - "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==" + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-4.3.1.tgz", - "integrity": "sha512-h8KKxESmSFTcXX409CAxlaOYscEDvN2KGQRsLCGT1NSqRW+D6EXLVQ8vuHhFznS9MuH9QYw1GfsUN30bg8hjVA==", + "version": "11.4.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.2.tgz", + "integrity": "sha512-BXJ7XPCTDXFF+wxcg/zscfgw2O/iDPtNSkwwR1W1W5c4Mb3zav/M2XvxQ23nVmKj7jpweB4g8viMeCQdm7LMVA==", + "license": "MIT", "dependencies": { - "@octokit/types": "^7.5.0" + "@octokit/types": "^13.7.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=4" - } - }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { - "version": "13.13.1", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.13.1.tgz", - "integrity": "sha512-4EuKSk3N95UBWFau3Bz9b3pheQ8jQYbKmBL5+GSuY8YDPDwu03J4BjI+66yNi8aaX/3h1qDpb0mbBkLdr+cfGQ==" - }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.5.1.tgz", - "integrity": "sha512-Zk4OUMLCSpXNI8KZZn47lVLJSsgMyCimsWWQI5hyjZg7hdYm0kjotaIkbG0Pp8SfU2CofMBzonboTqvzn3FrJA==", - "dependencies": { - "@octokit/openapi-types": "^13.11.0" + "@octokit/core": ">=6" } }, "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "@octokit/core": ">=3" + "@octokit/core": ">=6" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.8.1.tgz", - "integrity": "sha512-QrlaTm8Lyc/TbU7BL/8bO49vp+RZ6W3McxxmmQTgYxf2sWkO8ZKuj4dLhPNJD6VCUW1hetCmeIM0m6FTVpDiEg==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.1.tgz", + "integrity": "sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ==", + "license": "MIT", "dependencies": { - "@octokit/types": "^8.1.1", - "deprecation": "^2.3.1" + "@octokit/types": "^13.8.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.2.1.tgz", - "integrity": "sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==", - "dependencies": { - "@octokit/openapi-types": "^14.0.0" + "@octokit/core": ">=6" } }, "node_modules/@octokit/request": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz", - "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz", + "integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==", + "license": "MIT", "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" + "@octokit/endpoint": "^10.1.3", + "@octokit/request-error": "^6.1.7", + "@octokit/types": "^13.6.2", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz", + "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==", + "license": "MIT", "dependencies": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" + "@octokit/types": "^13.6.2" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/rest": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.4.tgz", - "integrity": "sha512-LwG668+6lE8zlSYOfwPj4FxWdv/qFXYBpv79TWIQEpBLKA9D/IMcWsF/U9RGpA3YqMVDiTxpgVpEW3zTFfPFTA==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz", + "integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==", + "license": "MIT", "dependencies": { - "@octokit/core": "^4.0.0", - "@octokit/plugin-paginate-rest": "^4.0.0", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^6.0.0" + "@octokit/core": "^6.1.4", + "@octokit/plugin-paginate-rest": "^11.4.2", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.3.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/types": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", - "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^18.0.0" + "@octokit/openapi-types": "^23.0.1" } }, "node_modules/@types/node": { @@ -200,60 +184,32 @@ } }, "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "engines": { - "node": ">=0.10.0" - } + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "license": "Apache-2.0" + }, + "node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, "node_modules/tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", @@ -269,28 +225,10 @@ "dev": true }, "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", + "license": "ISC" } } } diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index f6bfd7518957..531ba21fe063 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -25,8 +25,8 @@ "watch": "gulp watch-extension:configuration-editing" }, "dependencies": { + "@octokit/rest": "^21.1.1", "jsonc-parser": "^3.2.0", - "@octokit/rest": "19.0.4", "tunnel": "^0.0.6" }, "capabilities": { @@ -49,6 +49,7 @@ "settings.json", "launch.json", "tasks.json", + "mcp.json", "keybindings.json", "extensions.json", "argv.json", @@ -56,7 +57,8 @@ "devcontainer.json", ".devcontainer.json" ] - }, { + }, + { "id": "json", "extensions": [ ".code-profile" @@ -116,6 +118,10 @@ "fileMatch": "/.vscode/tasks.json", "url": "vscode://schemas/tasks" }, + { + "fileMatch": "/.vscode/mcp.json", + "url": "vscode://schemas/mcp" + }, { "fileMatch": "%APP_SETTINGS_HOME%/tasks.json", "url": "vscode://schemas/tasks" diff --git a/extensions/configuration-editing/src/settingsDocumentHelper.ts b/extensions/configuration-editing/src/settingsDocumentHelper.ts index 6135df5315a5..12b50f31759d 100644 --- a/extensions/configuration-editing/src/settingsDocumentHelper.ts +++ b/extensions/configuration-editing/src/settingsDocumentHelper.ts @@ -127,7 +127,7 @@ export class SettingsDocument { completions.push(this.newSimpleCompletionItem(getText('separator'), range, vscode.l10n.t("a conditional separator (' - ') that only shows when surrounded by variables with values"))); completions.push(this.newSimpleCompletionItem(getText('activeRepositoryName'), range, vscode.l10n.t("the name of the active repository (e.g. vscode)"))); completions.push(this.newSimpleCompletionItem(getText('activeRepositoryBranchName'), range, vscode.l10n.t("the name of the active branch in the active repository (e.g. main)"))); - + completions.push(this.newSimpleCompletionItem(getText('activeEditorState'), range, vscode.l10n.t("the state of the active editor (e.g. modified)."))); return completions; } diff --git a/extensions/csharp/cgmanifest.json b/extensions/csharp/cgmanifest.json index fefe63e47868..58ae5ece50ae 100644 --- a/extensions/csharp/cgmanifest.json +++ b/extensions/csharp/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "dotnet/csharp-tmLanguage", "repositoryUrl": "https://github.com/dotnet/csharp-tmLanguage", - "commitHash": "62026a70f9fcc42d9222eccfec34ed5ee0784f3d" + "commitHash": "1381bedfb087c18aca67af8278050d11bc9d9349" } }, "license": "MIT", diff --git a/extensions/csharp/syntaxes/csharp.tmLanguage.json b/extensions/csharp/syntaxes/csharp.tmLanguage.json index c4d9a2519dc3..1afcc3053b60 100644 --- a/extensions/csharp/syntaxes/csharp.tmLanguage.json +++ b/extensions/csharp/syntaxes/csharp.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/dotnet/csharp-tmLanguage/commit/62026a70f9fcc42d9222eccfec34ed5ee0784f3d", + "version": "https://github.com/dotnet/csharp-tmLanguage/commit/1381bedfb087c18aca67af8278050d11bc9d9349", "name": "C#", "scopeName": "source.cs", "patterns": [ @@ -714,11 +714,11 @@ }, "enum-declaration": { "begin": "(?=\\benum\\b)", - "end": "(?<=\\})", + "end": "(?<=\\})|(?=;)", "patterns": [ { "begin": "(?=enum)", - "end": "(?=\\{)", + "end": "(?=\\{)|(?=;)", "patterns": [ { "include": "#comment" @@ -805,7 +805,7 @@ }, "interface-declaration": { "begin": "(?=\\binterface\\b)", - "end": "(?<=\\})", + "end": "(?<=\\})|(?=;)", "patterns": [ { "begin": "(?x)\n(interface)\\b\\s+\n(@?[_[:alpha:]][_[:alnum:]]*)", @@ -817,7 +817,7 @@ "name": "entity.name.type.interface.cs" } }, - "end": "(?=\\{)", + "end": "(?=\\{)|(?=;)", "patterns": [ { "include": "#comment" diff --git a/extensions/css-language-features/client/tsconfig.json b/extensions/css-language-features/client/tsconfig.json index 5cf131d0677c..5284e0938583 100644 --- a/extensions/css-language-features/client/tsconfig.json +++ b/extensions/css-language-features/client/tsconfig.json @@ -9,7 +9,6 @@ }, "include": [ "src/**/*", - "../../../src/vscode-dts/vscode.d.ts", - "../../../src/vscode-dts/vscode.proposed.documentPaste.d.ts" + "../../../src/vscode-dts/vscode.d.ts" ] } diff --git a/extensions/css-language-features/package-lock.json b/extensions/css-language-features/package-lock.json index a645c2ab11af..cee5706d59db 100644 --- a/extensions/css-language-features/package-lock.json +++ b/extensions/css-language-features/package-lock.json @@ -34,9 +34,10 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } diff --git a/extensions/debug-server-ready/src/extension.ts b/extensions/debug-server-ready/src/extension.ts index 22a8ff836d34..40155f306bc8 100644 --- a/extensions/debug-server-ready/src/extension.ts +++ b/extensions/debug-server-ready/src/extension.ts @@ -23,7 +23,14 @@ interface ServerReadyAction { } // From src/vs/base/common/strings.ts -const CSI_SEQUENCE = /(?:(?:\x1b\[|\x9B)[=?>!]?[\d;:]*["$#'* ]?[a-zA-Z@^`{}|~])|(:?\x1b\].*?\x07)/g; +const CSI_SEQUENCE = /(?:\x1b\[|\x9b)[=?>!]?[\d;:]*["$#'* ]?[a-zA-Z@^`{}|~]/; +const OSC_SEQUENCE = /(?:\x1b\]|\x9d).*?(?:\x1b\\|\x07|\x9c)/; +const ESC_SEQUENCE = /\x1b(?:[ #%\(\)\*\+\-\.\/]?[a-zA-Z0-9\|}~@])/; +const CONTROL_SEQUENCES = new RegExp('(?:' + [ + CSI_SEQUENCE.source, + OSC_SEQUENCE.source, + ESC_SEQUENCE.source, +].join('|') + ')', 'g'); /** * Froms vs/base/common/strings.ts in core @@ -31,7 +38,7 @@ const CSI_SEQUENCE = /(?:(?:\x1b\[|\x9B)[=?>!]?[\d;:]*["$#'* ]?[a-zA-Z@^`{}|~])| */ function removeAnsiEscapeCodes(str: string): string { if (str) { - str = str.replace(CSI_SEQUENCE, ''); + str = str.replace(CONTROL_SEQUENCES, ''); } return str; diff --git a/extensions/git/package.json b/extensions/git/package.json index 600196ef2ce2..a117e45d0259 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -21,7 +21,6 @@ "contribSourceControlInputBoxMenu", "contribSourceControlTitleMenu", "contribViewsWelcome", - "diffCommand", "editSessionIdentityProvider", "quickDiffProvider", "quickInputButtonLocation", @@ -490,6 +489,12 @@ "category": "Git", "enablement": "!operationInProgress" }, + { + "command": "git.deleteRemoteBranch", + "title": "%command.deleteRemoteBranch%", + "category": "Git", + "enablement": "!operationInProgress" + }, { "command": "git.renameBranch", "title": "%command.renameBranch%", @@ -1224,6 +1229,10 @@ "command": "git.deleteBranch", "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0" }, + { + "command": "git.deleteRemoteBranch", + "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0" + }, { "command": "git.renameBranch", "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0" @@ -2066,7 +2075,7 @@ }, { "command": "git.graph.deleteBranch", - "when": "scmProvider == git && scmHistoryItemRef =~ /^refs\\/heads\\//", + "when": "scmProvider == git && scmHistoryItemRef =~ /^refs\\/heads\\/|^refs\\/remotes\\//", "group": "2_branch@2" }, { @@ -2437,6 +2446,10 @@ "command": "git.deleteBranch", "group": "3_modify@2" }, + { + "command": "git.deleteRemoteBranch", + "group": "3_modify@3" + }, { "command": "git.publish", "group": "4_publish@1" @@ -3283,6 +3296,35 @@ "maximum": 40, "markdownDescription": "%config.commitShortHashLength%", "scope": "resource" + }, + "git.diagnosticsCommitHook.Enabled": { + "type": "boolean", + "default": false, + "markdownDescription": "%config.diagnosticsCommitHook.Enabled%", + "scope": "resource" + }, + "git.diagnosticsCommitHook.Sources": { + "type": "object", + "additionalProperties": { + "type": "string", + "enum": [ + "error", + "warning", + "information", + "hint", + "none" + ] + }, + "default": { + "*": "error" + }, + "markdownDescription": "%config.diagnosticsCommitHook.Sources%", + "scope": "resource" + }, + "git.discardUntrackedChangesToTrash": { + "type": "boolean", + "default": true, + "markdownDescription": "%config.discardUntrackedChangesToTrash%" } } }, @@ -3391,10 +3433,10 @@ "id": "git.blame.editorDecorationForeground", "description": "%colors.blameEditorDecoration%", "defaults": { - "dark": "editorCodeLens.foreground", - "light": "editorCodeLens.foreground", - "highContrast": "editorCodeLens.foreground", - "highContrastLight": "editorCodeLens.foreground" + "dark": "editorInlayHint.foreground", + "light": "editorInlayHint.foreground", + "highContrast": "editorInlayHint.foreground", + "highContrastLight": "editorInlayHint.foreground" } } ], diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 5cfb2b1a7b24..101618a8e451 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -65,6 +65,7 @@ "command.branch": "Create Branch...", "command.branchFrom": "Create Branch From...", "command.deleteBranch": "Delete Branch...", + "command.deleteRemoteBranch": "Delete Remote Branch...", "command.renameBranch": "Rename Branch...", "command.cherryPick": "Cherry Pick...", "command.cherryPickAbort": "Abort Cherry Pick", @@ -285,6 +286,9 @@ "config.blameStatusBarItem.enabled": "Controls whether to show blame information in the status bar.", "config.blameStatusBarItem.template": "Template for the blame information status bar item. Supported variables:\n\n* `hash`: Commit hash\n\n* `hashShort`: First N characters of the commit hash according to `#git.commitShortHashLength#`\n\n* `subject`: First line of the commit message\n\n* `authorName`: Author name\n\n* `authorEmail`: Author email\n\n* `authorDate`: Author date\n\n* `authorDateAgo`: Time difference between now and the author date\n\n", "config.commitShortHashLength": "Controls the length of the commit short hash.", + "config.diagnosticsCommitHook.Enabled": "Controls whether to check for unresolved diagnostics before committing.", + "config.diagnosticsCommitHook.Sources": "Controls the list of sources (**Item**) and the minimum severity (**Value**) to be considered before committing. **Note:** To ignore diagnostics from a particular source, add the source to the list and set the minimum severity to `none`.", + "config.discardUntrackedChangesToTrash": "Controls whether discarding untracked changes moves the file(s) to the Recycle Bin (Windows), Trash (macOS, Linux) instead of deleting them permanently. **Note:** This setting has no effect when connected to a remote or when running in Linux as a snap package.", "submenu.explorer": "Git", "submenu.commit": "Commit", "submenu.commit.amend": "Amend", diff --git a/extensions/git/src/actionButton.ts b/extensions/git/src/actionButton.ts index 0c94636fff2b..63eefb1de028 100644 --- a/extensions/git/src/actionButton.ts +++ b/extensions/git/src/actionButton.ts @@ -262,7 +262,6 @@ export class ActionButton { const isCommitInProgress = this.repository.operations.isRunning(OperationKind.Commit) || this.repository.operations.isRunning(OperationKind.PostCommitCommand) || - this.repository.operations.isRunning(OperationKind.MergeContinue) || this.repository.operations.isRunning(OperationKind.RebaseContinue); const isSyncInProgress = diff --git a/extensions/git/src/blame.ts b/extensions/git/src/blame.ts index f29212c51a84..12182f1de8d8 100644 --- a/extensions/git/src/blame.ts +++ b/extensions/git/src/blame.ts @@ -69,6 +69,41 @@ function isResourceSchemeSupported(uri: Uri): boolean { return uri.scheme === 'file' || isGitUri(uri); } +function isResourceBlameInformationEqual(a: ResourceBlameInformation | undefined, b: ResourceBlameInformation | undefined): boolean { + if (a === b) { + return true; + } + + if (!a || !b || + a.resource.toString() !== b.resource.toString() || + a.blameInformation.length !== b.blameInformation.length) { + return false; + } + + for (let index = 0; index < a.blameInformation.length; index++) { + if (a.blameInformation[index].lineNumber !== b.blameInformation[index].lineNumber) { + return false; + } + + const aBlameInformation = a.blameInformation[index].blameInformation; + const bBlameInformation = b.blameInformation[index].blameInformation; + + if (typeof aBlameInformation === 'string' && typeof bBlameInformation === 'string') { + if (aBlameInformation !== bBlameInformation) { + return false; + } + } else if (typeof aBlameInformation !== 'string' && typeof bBlameInformation !== 'string') { + if (aBlameInformation.hash !== bBlameInformation.hash) { + return false; + } + } else { + return false; + } + } + + return true; +} + type BlameInformationTemplateTokens = { readonly hash: string; readonly hashShort: string; @@ -79,6 +114,11 @@ type BlameInformationTemplateTokens = { readonly authorDateAgo: string; }; +interface ResourceBlameInformation { + readonly resource: Uri; + readonly blameInformation: readonly LineBlameInformation[]; +} + interface LineBlameInformation { readonly lineNumber: number; readonly blameInformation: BlameInformation | string; @@ -116,11 +156,15 @@ export class GitBlameController { private readonly _onDidChangeBlameInformation = new EventEmitter(); public readonly onDidChangeBlameInformation = this._onDidChangeBlameInformation.event; - private _textEditorBlameInformation: LineBlameInformation[] | undefined; - get textEditorBlameInformation(): readonly LineBlameInformation[] | undefined { + private _textEditorBlameInformation: ResourceBlameInformation | undefined; + get textEditorBlameInformation(): ResourceBlameInformation | undefined { return this._textEditorBlameInformation; } - private set textEditorBlameInformation(blameInformation: LineBlameInformation[] | undefined) { + private set textEditorBlameInformation(blameInformation: ResourceBlameInformation | undefined) { + if (isResourceBlameInformationEqual(this._textEditorBlameInformation, blameInformation)) { + return; + } + this._textEditorBlameInformation = blameInformation; this._onDidChangeBlameInformation.fire(); } @@ -318,7 +362,7 @@ export class GitBlameController { } window.onDidChangeActiveTextEditor(e => this._updateTextEditorBlameInformation(e), this, this._enablementDisposables); - window.onDidChangeTextEditorSelection(e => this._updateTextEditorBlameInformation(e.textEditor, true), this, this._enablementDisposables); + window.onDidChangeTextEditorSelection(e => this._updateTextEditorBlameInformation(e.textEditor, 'selection'), this, this._enablementDisposables); window.onDidChangeTextEditorDiffInformation(e => this._updateTextEditorBlameInformation(e.textEditor), this, this._enablementDisposables); } } else { @@ -377,7 +421,7 @@ export class GitBlameController { } @throttle - private async _updateTextEditorBlameInformation(textEditor: TextEditor | undefined, showBlameInformationForPositionZero = false): Promise { + private async _updateTextEditorBlameInformation(textEditor: TextEditor | undefined, reason?: 'selection'): Promise { if (textEditor) { if (!textEditor.diffInformation || textEditor !== window.activeTextEditor) { return; @@ -401,7 +445,7 @@ export class GitBlameController { // Do not show blame information when there is a single selection and it is at the beginning // of the file [0, 0, 0, 0] unless the user explicitly navigates the cursor there. We do this // to avoid showing blame information when the editor is not focused. - if (!showBlameInformationForPositionZero && textEditor.selections.length === 1 && + if (reason !== 'selection' && textEditor.selections.length === 1 && textEditor.selections[0].start.line === 0 && textEditor.selections[0].start.character === 0 && textEditor.selections[0].end.line === 0 && textEditor.selections[0].end.character === 0) { this.textEditorBlameInformation = undefined; @@ -426,8 +470,11 @@ export class GitBlameController { // Resource on the right-hand side of the diff editor when viewing a resource from the index. const diffInformationWorkingTreeAndIndex = getWorkingTreeAndIndexDiffInformation(textEditor); - // Working tree + index diff information is present and it is stale + // Working tree + index diff information is present and it is stale. Diff information + // may be stale when the selection changes because of a content change and the diff + // information is not yet updated. if (diffInformationWorkingTreeAndIndex && diffInformationWorkingTreeAndIndex.isStale) { + this.textEditorBlameInformation = undefined; return; } @@ -440,16 +487,22 @@ export class GitBlameController { // Working tree diff information. Diff Editor (Working Tree) -> Text Editor const diffInformationWorkingTree = getWorkingTreeDiffInformation(textEditor); - // Working tree diff information is not present or it is stale + // Working tree diff information is not present or it is stale. Diff information + // may be stale when the selection changes because of a content change and the diff + // information is not yet updated. if (!diffInformationWorkingTree || diffInformationWorkingTree.isStale) { + this.textEditorBlameInformation = undefined; return; } // Working tree + index diff information const diffInformationWorkingTreeAndIndex = getWorkingTreeAndIndexDiffInformation(textEditor); - // Working tree + index diff information is present and it is stale + // Working tree + index diff information is present and it is stale. Diff information + // may be stale when the selection changes because of a content change and the diff + // information is not yet updated. if (diffInformationWorkingTreeAndIndex && diffInformationWorkingTreeAndIndex.isStale) { + this.textEditorBlameInformation = undefined; return; } @@ -482,7 +535,10 @@ export class GitBlameController { for (const lineNumber of new Set(textEditor.selections.map(s => s.active.line))) { // Check if the line is contained in the working tree diff information if (lineRangesContainLine(workingTreeChanges, lineNumber + 1)) { - lineBlameInformation.push({ lineNumber, blameInformation: l10n.t('Not Committed Yet') }); + if (reason === 'selection') { + // Only show the `Not Committed Yet` message upon selection change due to navigation + lineBlameInformation.push({ lineNumber, blameInformation: l10n.t('Not Committed Yet') }); + } continue; } @@ -505,7 +561,10 @@ export class GitBlameController { } } - this.textEditorBlameInformation = lineBlameInformation; + this.textEditorBlameInformation = { + resource: textEditor.document.uri, + blameInformation: lineBlameInformation + }; } dispose() { @@ -555,7 +614,7 @@ class GitBlameEditorDecoration implements HoverProvider { } // Get blame information - const blameInformation = this._controller.textEditorBlameInformation; + const blameInformation = this._controller.textEditorBlameInformation?.blameInformation; const lineBlameInformation = blameInformation?.find(blame => blame.lineNumber === position.line); if (!lineBlameInformation || typeof lineBlameInformation.blameInformation === 'string') { @@ -601,8 +660,8 @@ class GitBlameEditorDecoration implements HoverProvider { } // Get blame information - const blameInformation = this._controller.textEditorBlameInformation; - if (!blameInformation) { + const blameInformation = this._controller.textEditorBlameInformation?.blameInformation; + if (!blameInformation || blameInformation.length === 0) { textEditor.setDecorations(this._decoration, []); return; } @@ -680,7 +739,7 @@ class GitBlameStatusBarItem { return; } - const blameInformation = this._controller.textEditorBlameInformation; + const blameInformation = this._controller.textEditorBlameInformation?.blameInformation; if (!blameInformation || blameInformation.length === 0) { this._statusBarItem.hide(); return; diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index b7a1a85bb4f7..d94649559396 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -5,16 +5,16 @@ import * as os from 'os'; import * as path from 'path'; -import { Command, commands, Disposable, LineChange, MessageOptions, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider, InputBoxValidationSeverity, TabInputText, TabInputTextMerge, QuickPickItemKind, TextDocument, LogOutputChannel, l10n, Memento, UIKind, QuickInputButton, ThemeIcon, SourceControlHistoryItem, SourceControl, InputBoxValidationMessage, Tab, TabInputNotebook, QuickInputButtonLocation } from 'vscode'; +import { Command, commands, Disposable, MessageOptions, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider, InputBoxValidationSeverity, TabInputText, TabInputTextMerge, QuickPickItemKind, TextDocument, LogOutputChannel, l10n, Memento, UIKind, QuickInputButton, ThemeIcon, SourceControlHistoryItem, SourceControl, InputBoxValidationMessage, Tab, TabInputNotebook, QuickInputButtonLocation, languages } from 'vscode'; import TelemetryReporter from '@vscode/extension-telemetry'; import { uniqueNamesGenerator, adjectives, animals, colors, NumberDictionary } from '@joaomoreno/unique-names-generator'; import { ForcePushMode, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourcePublisher, Remote } from './api/git'; import { Git, Stash } from './git'; import { Model } from './model'; import { GitResourceGroup, Repository, Resource, ResourceGroupType } from './repository'; -import { DiffEditorSelectionHunkToolbarContext, applyLineChanges, getIndexDiffInformation, getModifiedRange, getWorkingTreeDiffInformation, intersectDiffWithRange, invertLineChange, toLineChanges, toLineRanges } from './staging'; +import { DiffEditorSelectionHunkToolbarContext, LineChange, applyLineChanges, getIndexDiffInformation, getModifiedRange, getWorkingTreeDiffInformation, intersectDiffWithRange, invertLineChange, toLineChanges, toLineRanges } from './staging'; import { fromGitUri, toGitUri, isGitUri, toMergeUris, toMultiFileDiffEditorUris } from './uri'; -import { dispose, getCommitShortHash, grep, isDefined, isDescendant, pathEquals, relativePath, truncate } from './util'; +import { DiagnosticSeverityConfig, dispose, getCommitShortHash, grep, isDefined, isDescendant, isLinuxSnap, isRemote, isWindows, pathEquals, relativePath, toDiagnosticSeverity, truncate } from './util'; import { GitTimelineItem } from './timelineProvider'; import { ApiRepository } from './api/api1'; import { getRemoteSourceActions, pickRemoteSource } from './remoteSource'; @@ -155,8 +155,11 @@ class CheckoutTagItem extends RefItem { class BranchDeleteItem extends RefItem { async run(repository: Repository, force?: boolean): Promise { - if (this.ref.name) { - await repository.deleteBranch(this.ref.name, force); + if (this.ref.type === RefType.Head && this.refName) { + await repository.deleteBranch(this.refName, force); + } else if (this.ref.type === RefType.RemoteHead && this.refRemote && this.refName) { + const refName = this.refName.substring(this.refRemote.length + 1); + await repository.deleteRemoteRef(this.refRemote, refName, { force }); } } } @@ -178,7 +181,7 @@ class RemoteTagDeleteItem extends RefItem { async run(repository: Repository, remote: string): Promise { if (this.ref.name) { - await repository.deleteRemoteTag(remote, this.ref.name); + await repository.deleteRemoteRef(remote, this.ref.name); } } } @@ -272,7 +275,6 @@ class StashItem implements QuickPickItem { interface ScmCommandOptions { repository?: boolean; - diff?: boolean; } interface ScmCommand { @@ -614,6 +616,87 @@ class CommandErrorOutputTextDocumentContentProvider implements TextDocumentConte } } +async function evaluateDiagnosticsCommitHook(repository: Repository, options: CommitOptions): Promise { + const config = workspace.getConfiguration('git', Uri.file(repository.root)); + const enabled = config.get('diagnosticsCommitHook.Enabled', false) === true; + const sourceSeverity = config.get>('diagnosticsCommitHook.Sources', { '*': 'error' }); + + if (!enabled) { + return true; + } + + const changes: Uri[] = []; + if (repository.indexGroup.resourceStates.length > 0) { + // Staged files + changes.push(...repository.indexGroup.resourceStates.map(r => r.resourceUri)); + } else if (options.all === 'tracked') { + // Tracked files + changes.push(...repository.workingTreeGroup.resourceStates + .filter(r => r.type !== Status.UNTRACKED && r.type !== Status.IGNORED) + .map(r => r.resourceUri)); + } else { + // All files + changes.push(...repository.workingTreeGroup.resourceStates.map(r => r.resourceUri)); + changes.push(...repository.untrackedGroup.resourceStates.map(r => r.resourceUri)); + } + + const diagnostics = languages.getDiagnostics(); + const changesDiagnostics = diagnostics.filter(([uri, diags]) => { + // File + if (uri.scheme !== 'file' || !changes.find(c => pathEquals(c.fsPath, uri.fsPath))) { + return false; + } + + // Diagnostics + return diags.find(d => { + // No source or ignored source + if (!d.source || (Object.keys(sourceSeverity).includes(d.source) && sourceSeverity[d.source] === 'none')) { + return false; + } + + // Source severity + if (Object.keys(sourceSeverity).includes(d.source) && + d.severity <= toDiagnosticSeverity(sourceSeverity[d.source])) { + return true; + } + + // Wildcard severity + if (Object.keys(sourceSeverity).includes('*') && + d.severity <= toDiagnosticSeverity(sourceSeverity['*'])) { + return true; + } + + return false; + }); + }); + + if (changesDiagnostics.length === 0) { + return true; + } + + // Show dialog + const commit = l10n.t('Commit Anyway'); + const view = l10n.t('View Problems'); + + const message = changesDiagnostics.length === 1 + ? l10n.t('The following file has unresolved diagnostics: \'{0}\'.\n\nHow would you like to proceed?', path.basename(changesDiagnostics[0][0].fsPath)) + : l10n.t('There are {0} files that have unresolved diagnostics.\n\nHow would you like to proceed?', changesDiagnostics.length); + + const choice = await window.showWarningMessage(message, { modal: true }, commit, view); + + // Commit Anyway + if (choice === commit) { + return true; + } + + // View Problems + if (choice === view) { + commands.executeCommand('workbench.panel.markers.view.focus'); + } + + return false; +} + export class CommandCenter { private disposables: Disposable[]; @@ -628,12 +711,7 @@ export class CommandCenter { ) { this.disposables = Commands.map(({ commandId, key, method, options }) => { const command = this.createCommand(commandId, key, method, options); - - if (options.diff) { - return commands.registerDiffInformationCommand(commandId, command); - } else { - return commands.registerCommand(commandId, command); - } + return commands.registerCommand(commandId, command); }); this.disposables.push(workspace.registerTextDocumentContentProvider('git-output', this.commandErrors)); @@ -1559,8 +1637,8 @@ export class CommandCenter { await this.runByRepository(modifiedUri, async (repository, resource) => await repository.stage(resource, result)); } - @command('git.stageSelectedRanges', { diff: true }) - async stageSelectedChanges(changes: LineChange[]): Promise { + @command('git.stageSelectedRanges') + async stageSelectedChanges(): Promise { const textEditor = window.activeTextEditor; if (!textEditor) { @@ -1574,7 +1652,6 @@ export class CommandCenter { const workingTreeLineChanges = toLineChanges(workingTreeDiffInformation); - this.logger.trace(`[CommandCenter][stageSelectedChanges] changes: ${JSON.stringify(changes)}`); this.logger.trace(`[CommandCenter][stageSelectedChanges] diffInformation: ${JSON.stringify(workingTreeDiffInformation)}`); this.logger.trace(`[CommandCenter][stageSelectedChanges] diffInformation changes: ${JSON.stringify(workingTreeLineChanges)}`); @@ -1754,8 +1831,8 @@ export class CommandCenter { textEditor.selections = [new Selection(firstStagedLine, 0, firstStagedLine, 0)]; } - @command('git.revertSelectedRanges', { diff: true }) - async revertSelectedRanges(changes: LineChange[]): Promise { + @command('git.revertSelectedRanges') + async revertSelectedRanges(): Promise { const textEditor = window.activeTextEditor; if (!textEditor) { @@ -1769,7 +1846,6 @@ export class CommandCenter { const workingTreeLineChanges = toLineChanges(workingTreeDiffInformation); - this.logger.trace(`[CommandCenter][revertSelectedRanges] changes: ${JSON.stringify(changes)}`); this.logger.trace(`[CommandCenter][revertSelectedRanges] diffInformation: ${JSON.stringify(workingTreeDiffInformation)}`); this.logger.trace(`[CommandCenter][revertSelectedRanges] diffInformation changes: ${JSON.stringify(workingTreeLineChanges)}`); @@ -1844,8 +1920,8 @@ export class CommandCenter { await repository.revert([]); } - @command('git.unstageSelectedRanges', { diff: true }) - async unstageSelectedRanges(changes: LineChange[]): Promise { + @command('git.unstageSelectedRanges') + async unstageSelectedRanges(): Promise { const textEditor = window.activeTextEditor; if (!textEditor) { @@ -1865,6 +1941,17 @@ export class CommandCenter { return; } + const repository = this.model.getRepository(modifiedUri); + if (!repository) { + return; + } + + const resource = repository.indexGroup.resourceStates + .find(r => pathEquals(r.resourceUri.fsPath, modifiedUri.fsPath)); + if (!resource) { + return; + } + const indexDiffInformation = getIndexDiffInformation(textEditor); if (!indexDiffInformation) { return; @@ -1872,11 +1959,10 @@ export class CommandCenter { const indexLineChanges = toLineChanges(indexDiffInformation); - this.logger.trace(`[CommandCenter][unstageSelectedRanges] changes: ${JSON.stringify(changes)}`); this.logger.trace(`[CommandCenter][unstageSelectedRanges] diffInformation: ${JSON.stringify(indexDiffInformation)}`); this.logger.trace(`[CommandCenter][unstageSelectedRanges] diffInformation changes: ${JSON.stringify(indexLineChanges)}`); - const originalUri = toGitUri(modifiedUri, 'HEAD'); + const originalUri = toGitUri(resource.original, 'HEAD'); const originalDocument = await workspace.openTextDocument(originalUri); const selectedLines = toLineRanges(textEditor.selections, modifiedDocument); const selectedDiffs = indexLineChanges @@ -1894,7 +1980,7 @@ export class CommandCenter { this.logger.trace(`[CommandCenter][unstageSelectedRanges] invertedDiffs: ${JSON.stringify(invertedDiffs)}`); const result = applyLineChanges(modifiedDocument, originalDocument, invertedDiffs); - await this.runByRepository(modifiedUri, async (repository, resource) => await repository.stage(resource, result)); + await repository.stage(modifiedUri, result); } @command('git.unstageFile') @@ -1954,49 +2040,39 @@ export class CommandCenter { return; } - const untrackedCount = scmResources.reduce((s, r) => s + (r.type === Status.UNTRACKED ? 1 : 0), 0); - let message: string; - let yes = l10n.t('Discard Changes'); + await this._cleanAll(scmResources); + } - if (scmResources.length === 1) { - if (untrackedCount > 0) { - message = l10n.t('Are you sure you want to DELETE {0}?\nThis is IRREVERSIBLE!\nThis file will be FOREVER LOST if you proceed.', path.basename(scmResources[0].resourceUri.fsPath)); - yes = l10n.t('Delete file'); - } else { - if (scmResources[0].type === Status.DELETED) { - yes = l10n.t('Restore file'); - message = l10n.t('Are you sure you want to restore {0}?', path.basename(scmResources[0].resourceUri.fsPath)); - } else { - message = l10n.t('Are you sure you want to discard changes in {0}?', path.basename(scmResources[0].resourceUri.fsPath)); - } - } - } else { - if (scmResources.every(resource => resource.type === Status.DELETED)) { - yes = l10n.t('Restore files'); - message = l10n.t('Are you sure you want to restore {0} files?', scmResources.length); - } else { - message = l10n.t('Are you sure you want to discard changes in {0} files?', scmResources.length); - } + @command('git.cleanAll', { repository: true }) + async cleanAll(repository: Repository): Promise { + await this._cleanAll(repository.workingTreeGroup.resourceStates); + } - if (untrackedCount > 0) { - message = `${message}\n\n${l10n.t('This will DELETE {0} untracked files!\nThis is IRREVERSIBLE!\nThese files will be FOREVER LOST.', untrackedCount)}`; - } + @command('git.cleanAllTracked', { repository: true }) + async cleanAllTracked(repository: Repository): Promise { + const resources = repository.workingTreeGroup.resourceStates + .filter(r => r.type !== Status.UNTRACKED && r.type !== Status.IGNORED); + + if (resources.length === 0) { + return; } - const pick = await window.showWarningMessage(message, { modal: true }, yes); + await this._cleanTrackedChanges(resources); + } - if (pick !== yes) { + @command('git.cleanAllUntracked', { repository: true }) + async cleanAllUntracked(repository: Repository): Promise { + const resources = [...repository.workingTreeGroup.resourceStates, ...repository.untrackedGroup.resourceStates] + .filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED); + + if (resources.length === 0) { return; } - const resources = scmResources.map(r => r.resourceUri); - await this.runByRepository(resources, async (repository, resources) => repository.clean(resources)); + await this._cleanUntrackedChanges(resources); } - @command('git.cleanAll', { repository: true }) - async cleanAll(repository: Repository): Promise { - let resources = repository.workingTreeGroup.resourceStates; - + private async _cleanAll(resources: Resource[]): Promise { if (resources.length === 0) { return; } @@ -2005,24 +2081,25 @@ export class CommandCenter { const untrackedResources = resources.filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED); if (untrackedResources.length === 0) { - await this._cleanTrackedChanges(repository, resources); - } else if (resources.length === 1) { - await this._cleanUntrackedChange(repository, resources[0]); + // Tracked files only + await this._cleanTrackedChanges(resources); } else if (trackedResources.length === 0) { - await this._cleanUntrackedChanges(repository, resources); - } else { // resources.length > 1 && untrackedResources.length > 0 && trackedResources.length > 0 - const untrackedMessage = untrackedResources.length === 1 - ? l10n.t('The following untracked file will be DELETED FROM DISK if discarded: {0}.', path.basename(untrackedResources[0].resourceUri.fsPath)) - : l10n.t('There are {0} untracked files which will be DELETED FROM DISK if discarded.', untrackedResources.length); + // Untracked files only + await this._cleanUntrackedChanges(resources); + } else { + // Tracked & Untracked files + const [untrackedMessage, untrackedMessageDetail] = this.getDiscardUntrackedChangesDialogDetails(untrackedResources); - const message = l10n.t('{0}\n\nThis is IRREVERSIBLE, your current working set will be FOREVER LOST.', untrackedMessage, resources.length); + const trackedMessage = trackedResources.length === 1 + ? l10n.t('\n\nAre you sure you want to discard changes in \'{0}\'?', path.basename(trackedResources[0].resourceUri.fsPath)) + : l10n.t('\n\nAre you sure you want to discard ALL changes in {0} files?', trackedResources.length); const yesTracked = trackedResources.length === 1 - ? l10n.t('Discard 1 Tracked File', trackedResources.length) - : l10n.t('Discard {0} Tracked Files', trackedResources.length); + ? l10n.t('Discard 1 Tracked File') + : l10n.t('Discard All {0} Tracked Files', trackedResources.length); const yesAll = l10n.t('Discard All {0} Files', resources.length); - const pick = await window.showWarningMessage(message, { modal: true }, yesTracked, yesAll); + const pick = await window.showWarningMessage(`${untrackedMessage} ${untrackedMessageDetail}${trackedMessage}\n\nThis is IRREVERSIBLE!\nYour current working set will be FOREVER LOST if you proceed.`, { modal: true }, yesTracked, yesAll); if (pick === yesTracked) { resources = trackedResources; @@ -2030,76 +2107,85 @@ export class CommandCenter { return; } - await repository.clean(resources.map(r => r.resourceUri)); - } - } - - @command('git.cleanAllTracked', { repository: true }) - async cleanAllTracked(repository: Repository): Promise { - const resources = repository.workingTreeGroup.resourceStates - .filter(r => r.type !== Status.UNTRACKED && r.type !== Status.IGNORED); - - if (resources.length === 0) { - return; + const resourceUris = resources.map(r => r.resourceUri); + await this.runByRepository(resourceUris, async (repository, resources) => repository.clean(resources)); } - - await this._cleanTrackedChanges(repository, resources); } - @command('git.cleanAllUntracked', { repository: true }) - async cleanAllUntracked(repository: Repository): Promise { - const resources = [...repository.workingTreeGroup.resourceStates, ...repository.untrackedGroup.resourceStates] - .filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED); + private async _cleanTrackedChanges(resources: Resource[]): Promise { + const allResourcesDeleted = resources.every(r => r.type === Status.DELETED); - if (resources.length === 0) { - return; - } + const message = allResourcesDeleted + ? resources.length === 1 + ? l10n.t('Are you sure you want to restore \'{0}\'?', path.basename(resources[0].resourceUri.fsPath)) + : l10n.t('Are you sure you want to restore ALL {0} files?', resources.length) + : resources.length === 1 + ? l10n.t('Are you sure you want to discard changes in \'{0}\'?', path.basename(resources[0].resourceUri.fsPath)) + : l10n.t('Are you sure you want to discard ALL changes in {0} files?\n\nThis is IRREVERSIBLE!\nYour current working set will be FOREVER LOST if you proceed.', resources.length); - if (resources.length === 1) { - await this._cleanUntrackedChange(repository, resources[0]); - } else { - await this._cleanUntrackedChanges(repository, resources); - } - } + const yes = allResourcesDeleted + ? resources.length === 1 + ? l10n.t('Restore File') + : l10n.t('Restore All {0} Files', resources.length) + : resources.length === 1 + ? l10n.t('Discard File') + : l10n.t('Discard All {0} Files', resources.length); - private async _cleanTrackedChanges(repository: Repository, resources: Resource[]): Promise { - const message = resources.length === 1 - ? l10n.t('Are you sure you want to discard changes in {0}?', path.basename(resources[0].resourceUri.fsPath)) - : l10n.t('Are you sure you want to discard ALL changes in {0} files?\nThis is IRREVERSIBLE!\nYour current working set will be FOREVER LOST if you proceed.', resources.length); - const yes = resources.length === 1 - ? l10n.t('Discard 1 File') - : l10n.t('Discard All {0} Files', resources.length); const pick = await window.showWarningMessage(message, { modal: true }, yes); if (pick !== yes) { return; } - await repository.clean(resources.map(r => r.resourceUri)); + const resourceUris = resources.map(r => r.resourceUri); + await this.runByRepository(resourceUris, async (repository, resources) => repository.clean(resources)); } - private async _cleanUntrackedChange(repository: Repository, resource: Resource): Promise { - const message = l10n.t('Are you sure you want to DELETE {0}?\nThis is IRREVERSIBLE!\nThis file will be FOREVER LOST if you proceed.', path.basename(resource.resourceUri.fsPath)); - const yes = l10n.t('Delete file'); - const pick = await window.showWarningMessage(message, { modal: true }, yes); + private async _cleanUntrackedChanges(resources: Resource[]): Promise { + const [message, messageDetail, primaryAction] = this.getDiscardUntrackedChangesDialogDetails(resources); + const pick = await window.showWarningMessage(message, { detail: messageDetail, modal: true }, primaryAction); - if (pick !== yes) { + if (pick !== primaryAction) { return; } - await repository.clean([resource.resourceUri]); + const resourceUris = resources.map(r => r.resourceUri); + await this.runByRepository(resourceUris, async (repository, resources) => repository.clean(resources)); } - private async _cleanUntrackedChanges(repository: Repository, resources: Resource[]): Promise { - const message = l10n.t('Are you sure you want to DELETE {0} files?\nThis is IRREVERSIBLE!\nThese files will be FOREVER LOST if you proceed.', resources.length); - const yes = l10n.t('Delete Files'); - const pick = await window.showWarningMessage(message, { modal: true }, yes); + private getDiscardUntrackedChangesDialogDetails(resources: Resource[]): [string, string, string] { + const config = workspace.getConfiguration('git'); + const discardUntrackedChangesToTrash = config.get('discardUntrackedChangesToTrash', true) && !isRemote && !isLinuxSnap; - if (pick !== yes) { - return; - } + const messageWarning = !discardUntrackedChangesToTrash + ? resources.length === 1 + ? '\n\nThis is IRREVERSIBLE!\nThis file will be FOREVER LOST if you proceed.' + : '\n\nThis is IRREVERSIBLE!\nThese files will be FOREVER LOST if you proceed.' + : ''; - await repository.clean(resources.map(r => r.resourceUri)); + const message = resources.length === 1 + ? l10n.t('Are you sure you want to DELETE the following untracked file: \'{0}\'?{1}', path.basename(resources[0].resourceUri.fsPath), messageWarning) + : l10n.t('Are you sure you want to DELETE the {0} untracked files?{1}', resources.length, messageWarning); + + const messageDetail = discardUntrackedChangesToTrash + ? isWindows + ? resources.length === 1 + ? 'You can restore this file from the Recycle Bin.' + : 'You can restore these files from the Recycle Bin.' + : resources.length === 1 + ? 'You can restore this file from the Trash.' + : 'You can restore these files from the Trash.' + : ''; + + const primaryAction = discardUntrackedChangesToTrash + ? isWindows + ? l10n.t('Move to Recycle Bin') + : l10n.t('Move to Trash') + : resources.length === 1 + ? l10n.t('Delete File') + : l10n.t('Delete All {0} Files', resources.length); + + return [message, messageDetail, primaryAction]; } private async smartCommit( @@ -2270,7 +2356,13 @@ export class CommandCenter { opts.all = 'tracked'; } - // Branch protection + // Diagnostics commit hook + const diagnosticsResult = await evaluateDiagnosticsCommitHook(repository, opts); + if (!diagnosticsResult) { + return; + } + + // Branch protection commit hook const branchProtectionPrompt = config.get<'alwaysCommit' | 'alwaysCommitToNewBranch' | 'alwaysPrompt'>('branchProtectionPrompt')!; if (repository.isBranchProtected() && (branchProtectionPrompt === 'alwaysPrompt' || branchProtectionPrompt === 'alwaysCommitToNewBranch')) { const commitToNewBranch = l10n.t('Commit to a New Branch'); @@ -2883,7 +2975,7 @@ export class CommandCenter { @command('git.deleteBranch', { repository: true }) async deleteBranch(repository: Repository, name: string | undefined, force?: boolean): Promise { - await this._deleteBranch(repository, name, force); + await this._deleteBranch(repository, undefined, name, { remote: false, force }); } @command('git.graph.deleteBranch', { repository: true }) @@ -2893,22 +2985,76 @@ export class CommandCenter { return; } - await this._deleteBranch(repository, historyItemRef.name); + // Local branch + if (historyItemRef.id.startsWith('refs/heads/')) { + if (historyItemRef.id === repository.historyProvider.currentHistoryItemRef?.id) { + window.showInformationMessage(l10n.t('The active branch cannot be deleted.')); + return; + } + + await this._deleteBranch(repository, undefined, historyItemRef.name, { remote: false }); + return; + } + + // Remote branch + if (historyItemRef.id === repository.historyProvider.currentHistoryItemRemoteRef?.id) { + window.showInformationMessage(l10n.t('The remote branch of the active branch cannot be deleted.')); + return; + } + + const index = historyItemRef.name.indexOf('/'); + if (index === -1) { + return; + } + + const remoteName = historyItemRef.name.substring(0, index); + const refName = historyItemRef.name.substring(index + 1); + + await this._deleteBranch(repository, remoteName, refName, { remote: true }); + } + + @command('git.deleteRemoteBranch', { repository: true }) + async deleteRemoteBranch(repository: Repository): Promise { + await this._deleteBranch(repository, undefined, undefined, { remote: true }); } - private async _deleteBranch(repository: Repository, name: string | undefined, force?: boolean): Promise { + private async _deleteBranch(repository: Repository, remote: string | undefined, name: string | undefined, options: { remote: boolean; force?: boolean }): Promise { let run: (force?: boolean) => Promise; - if (typeof name === 'string') { + + if (!options.remote && typeof name === 'string') { + // Local branch run = force => repository.deleteBranch(name!, force); + } else if (options.remote && typeof remote === 'string' && typeof name === 'string') { + // Remote branch + run = force => repository.deleteRemoteRef(remote, name!, { force }); } else { const getBranchPicks = async () => { - const refs = await repository.getRefs({ pattern: 'refs/heads' }); - const currentHead = repository.HEAD && repository.HEAD.name; + const pattern = options.remote ? 'refs/remotes' : 'refs/heads'; + const refs = await repository.getRefs({ pattern }); + + const refsToExclude: string[] = []; + if (options.remote) { + refsToExclude.push('origin/HEAD'); + + if (repository.HEAD?.upstream) { + // Current branch's upstream + refsToExclude.push(`${repository.HEAD.upstream.remote}/${repository.HEAD.upstream.name}`); + } + } else { + if (repository.HEAD?.name) { + // Current branch + refsToExclude.push(repository.HEAD.name); + } + } - return refs.filter(ref => ref.name !== currentHead).map(ref => new BranchDeleteItem(ref)); + return refs.filter(ref => ref.name && !refsToExclude.includes(ref.name)) + .map(ref => new BranchDeleteItem(ref)); }; - const placeHolder = l10n.t('Select a branch to delete'); + const placeHolder = !options.remote + ? l10n.t('Select a branch to delete') + : l10n.t('Select a remote branch to delete'); + const choice = await this.pickRef(getBranchPicks(), placeHolder); if (!choice || !choice.refName) { @@ -2919,7 +3065,7 @@ export class CommandCenter { } try { - await run(force); + await run(options.force); } catch (err) { if (err.gitErrorCode !== GitErrorCodes.BranchNotFullyMerged) { throw err; diff --git a/extensions/git/src/decorators.ts b/extensions/git/src/decorators.ts index b1a25d4fd919..f89ff2327e95 100644 --- a/extensions/git/src/decorators.ts +++ b/extensions/git/src/decorators.ts @@ -98,4 +98,4 @@ export function debounce(delay: number): Function { this[timerKey] = setTimeout(() => fn.apply(this, args), delay); }; }); -} \ No newline at end of file +} diff --git a/extensions/git/src/fileSystemProvider.ts b/extensions/git/src/fileSystemProvider.ts index 8b8f9fc65afb..19928863832a 100644 --- a/extensions/git/src/fileSystemProvider.ts +++ b/extensions/git/src/fileSystemProvider.ts @@ -18,7 +18,7 @@ interface CacheRow { const THREE_MINUTES = 1000 * 60 * 3; const FIVE_MINUTES = 1000 * 60 * 5; -function sanitizeRef(ref: string, path: string, repository: Repository): string { +function sanitizeRef(ref: string, path: string, submoduleOf: string | undefined, repository: Repository): string { if (ref === '~') { const fileUri = Uri.file(path); const uriString = fileUri.toString(); @@ -30,6 +30,11 @@ function sanitizeRef(ref: string, path: string, repository: Repository): string return `:${ref[1]}`; } + // Submodule HEAD + if (submoduleOf && (ref === 'index' || ref === 'wt')) { + return 'HEAD'; + } + return ref; } @@ -141,7 +146,7 @@ export class GitFileSystemProvider implements FileSystemProvider { } try { - const details = await repository.getObjectDetails(sanitizeRef(ref, path, repository), path); + const details = await repository.getObjectDetails(sanitizeRef(ref, path, submoduleOf, repository), path); return { type: FileType.File, size: details.size, mtime: this.mtime, ctime: 0 }; } catch { // Empty tree @@ -198,7 +203,7 @@ export class GitFileSystemProvider implements FileSystemProvider { this.cache.set(uri.toString(), cacheValue); try { - return await repository.buffer(sanitizeRef(ref, path, repository), path); + return await repository.buffer(sanitizeRef(ref, path, submoduleOf, repository), path); } catch { // Empty tree if (ref === await repository.getEmptyTree()) { diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index b6d5582b8fb6..2efa507ed663 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -12,7 +12,7 @@ import which from 'which'; import { EventEmitter } from 'events'; import * as iconv from '@vscode/iconv-lite-umd'; import * as filetype from 'file-type'; -import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter, Versions, isWindows, pathEquals, isMacintosh, isDescendant } from './util'; +import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter, Versions, isWindows, pathEquals, isMacintosh, isDescendant, relativePath } from './util'; import { CancellationError, CancellationToken, ConfigurationChangeEvent, LogOutputChannel, Progress, Uri, workspace } from 'vscode'; import { detectEncoding } from './encoding'; import { Ref, RefType, Branch, Remote, ForcePushMode, GitErrorCodes, LogOptions, Change, Status, CommitOptions, RefQuery, InitOptions } from './api/git'; @@ -355,6 +355,10 @@ function sanitizePath(path: string): string { return path.replace(/^([a-z]):\\/i, (_, letter) => `${letter.toUpperCase()}:\\`); } +function sanitizeRelativePath(from: string, to: string): string { + return relativePath(from, to).replace(/\\/g, '/'); +} + const COMMIT_FORMAT = '%H%n%aN%n%aE%n%at%n%ct%n%P%n%D%n%B'; const STASH_FORMAT = '%H%n%P%n%gd%n%gs'; @@ -1330,8 +1334,8 @@ export class Repository { .filter(entry => !!entry); } - async bufferString(object: string, encoding: string = 'utf8', autoGuessEncoding = false, candidateGuessEncodings: string[] = []): Promise { - const stdout = await this.buffer(object); + async bufferString(ref: string, filePath: string, encoding: string = 'utf8', autoGuessEncoding = false, candidateGuessEncodings: string[] = []): Promise { + const stdout = await this.buffer(ref, filePath); if (autoGuessEncoding) { encoding = detectEncoding(stdout, candidateGuessEncodings) || encoding; @@ -1342,8 +1346,9 @@ export class Repository { return iconv.decode(stdout, encoding); } - async buffer(object: string): Promise { - const child = this.stream(['show', '--textconv', object]); + async buffer(ref: string, filePath: string): Promise { + const relativePath = sanitizeRelativePath(this.repositoryRoot, filePath); + const child = this.stream(['show', '--textconv', `${ref}:${relativePath}`]); if (!child.stdout) { return Promise.reject('Can\'t open file from git'); @@ -1392,13 +1397,20 @@ export class Repository { } const { mode, object, size } = elements[0]; - return { mode, object, size: parseInt(size) }; + return { mode, object, size: parseInt(size) || 0 }; } - async lstree(treeish: string, path?: string): Promise { - const args = ['ls-tree', '-l', treeish]; + async lstree(treeish: string, path?: string, options?: { recursive?: boolean }): Promise { + const args = ['ls-tree', '-l']; + + if (options?.recursive) { + args.push('-r'); + } + + args.push(treeish); + if (path) { - args.push('--', sanitizePath(path)); + args.push('--', sanitizeRelativePath(this.repositoryRoot, path)); } const { stdout } = await this.exec(args); @@ -1406,15 +1418,24 @@ export class Repository { } async lsfiles(path: string): Promise { - const { stdout } = await this.exec(['ls-files', '--stage', '--', sanitizePath(path)]); + const args = ['ls-files', '--stage']; + const relativePath = sanitizeRelativePath(this.repositoryRoot, path); + + if (relativePath) { + args.push('--', relativePath); + } + + const { stdout } = await this.exec(args); return parseLsFiles(stdout); } - async getGitRelativePath(ref: string, relativePath: string): Promise { - const relativePathLowercase = relativePath.toLowerCase(); - const dirname = path.posix.dirname(relativePath) + '/'; - const elements: { file: string }[] = ref ? await this.lstree(ref, dirname) : await this.lsfiles(dirname); - const element = elements.filter(file => file.file.toLowerCase() === relativePathLowercase)[0]; + async getGitFilePath(ref: string, filePath: string): Promise { + const elements: { file: string }[] = ref + ? await this.lstree(ref, undefined, { recursive: true }) + : await this.lsfiles(this.repositoryRoot); + + const relativePathLowercase = sanitizeRelativePath(this.repositoryRoot, filePath).toLowerCase(); + const element = elements.find(file => file.file.toLowerCase() === relativePathLowercase); if (!element) { throw new GitError({ @@ -1422,7 +1443,7 @@ export class Repository { }); } - return element.file; + return path.join(this.repositoryRoot, element.file); } async detectObjectType(object: string): Promise<{ mimetype: string; encoding?: string }> { @@ -1502,7 +1523,7 @@ export class Repository { return await this.diffFiles(false); } - const args = ['diff', '--', sanitizePath(path)]; + const args = ['diff', '--', sanitizeRelativePath(this.repositoryRoot, path)]; const result = await this.exec(args); return result.stdout; } @@ -1515,7 +1536,7 @@ export class Repository { return await this.diffFiles(false, ref); } - const args = ['diff', ref, '--', sanitizePath(path)]; + const args = ['diff', ref, '--', sanitizeRelativePath(this.repositoryRoot, path)]; const result = await this.exec(args); return result.stdout; } @@ -1528,7 +1549,7 @@ export class Repository { return await this.diffFiles(true); } - const args = ['diff', '--cached', '--', sanitizePath(path)]; + const args = ['diff', '--cached', '--', sanitizeRelativePath(this.repositoryRoot, path)]; const result = await this.exec(args); return result.stdout; } @@ -1541,7 +1562,7 @@ export class Repository { return await this.diffFiles(true, ref); } - const args = ['diff', '--cached', ref, '--', sanitizePath(path)]; + const args = ['diff', '--cached', ref, '--', sanitizeRelativePath(this.repositoryRoot, path)]; const result = await this.exec(args); return result.stdout; } @@ -1561,7 +1582,7 @@ export class Repository { return await this.diffFiles(false, range); } - const args = ['diff', range, '--', sanitizePath(path)]; + const args = ['diff', range, '--', sanitizeRelativePath(this.repositoryRoot, path)]; const result = await this.exec(args); return result.stdout.trim(); @@ -1653,7 +1674,7 @@ export class Repository { } if (paths && paths.length) { - for (const chunk of splitInChunks(paths.map(sanitizePath), MAX_CLI_LENGTH)) { + for (const chunk of splitInChunks(paths.map(p => sanitizeRelativePath(this.repositoryRoot, p)), MAX_CLI_LENGTH)) { await this.exec([...args, '--', ...chunk]); } } else { @@ -1668,13 +1689,14 @@ export class Repository { return; } - args.push(...paths.map(sanitizePath)); + args.push(...paths.map(p => sanitizeRelativePath(this.repositoryRoot, p))); await this.exec(args); } async stage(path: string, data: string, encoding: string): Promise { - const child = this.stream(['hash-object', '--stdin', '-w', '--path', sanitizePath(path)], { stdio: [null, null, null] }); + const relativePath = sanitizeRelativePath(this.repositoryRoot, path); + const child = this.stream(['hash-object', '--stdin', '-w', '--path', relativePath], { stdio: [null, null, null] }); child.stdin!.end(iconv.encode(data, encoding)); const { exitCode, stdout } = await exec(child); @@ -1703,7 +1725,7 @@ export class Repository { add = '--add'; } - await this.exec(['update-index', add, '--cacheinfo', mode, hash, path]); + await this.exec(['update-index', add, '--cacheinfo', mode, hash, relativePath]); } async checkout(treeish: string, paths: string[], opts: { track?: boolean; detached?: boolean } = Object.create(null)): Promise { @@ -1723,7 +1745,7 @@ export class Repository { try { if (paths && paths.length > 0) { - for (const chunk of splitInChunks(paths.map(sanitizePath), MAX_CLI_LENGTH)) { + for (const chunk of splitInChunks(paths.map(p => sanitizeRelativePath(this.repositoryRoot, p)), MAX_CLI_LENGTH)) { await this.exec([...args, '--', ...chunk]); } } else { @@ -1896,16 +1918,6 @@ export class Repository { await this.exec(['merge', '--abort']); } - async mergeContinue(): Promise { - const args = ['merge', '--continue']; - - try { - await this.exec(args, { env: { GIT_EDITOR: 'true' } }); - } catch (commitErr) { - await this.handleCommitError(commitErr); - } - } - async tag(options: { name: string; message?: string; ref?: string }): Promise { let args = ['tag']; @@ -1927,8 +1939,14 @@ export class Repository { await this.exec(args); } - async deleteRemoteTag(remoteName: string, tagName: string): Promise { - const args = ['push', '--delete', remoteName, tagName]; + async deleteRemoteRef(remoteName: string, refName: string, options?: { force?: boolean }): Promise { + const args = ['push', remoteName, '--delete']; + + if (options?.force) { + args.push('--force'); + } + + args.push(refName); await this.exec(args); } @@ -1941,7 +1959,7 @@ export class Repository { const args = ['clean', '-f', '-q']; for (const paths of groups) { - for (const chunk of splitInChunks(paths.map(sanitizePath), MAX_CLI_LENGTH)) { + for (const chunk of splitInChunks(paths.map(p => sanitizeRelativePath(this.repositoryRoot, p)), MAX_CLI_LENGTH)) { promises.push(limiter.queue(() => this.exec([...args, '--', ...chunk]))); } } @@ -1981,7 +1999,7 @@ export class Repository { try { if (paths && paths.length > 0) { - for (const chunk of splitInChunks(paths.map(sanitizePath), MAX_CLI_LENGTH)) { + for (const chunk of splitInChunks(paths.map(p => sanitizeRelativePath(this.repositoryRoot, p)), MAX_CLI_LENGTH)) { await this.exec([...args, '--', ...chunk]); } } else { @@ -2226,7 +2244,7 @@ export class Repository { async blame(path: string): Promise { try { - const args = ['blame', sanitizePath(path)]; + const args = ['blame', '--', sanitizeRelativePath(this.repositoryRoot, path)]; const result = await this.exec(args); return result.stdout.trim(); } catch (err) { @@ -2246,7 +2264,7 @@ export class Repository { args.push(ref); } - args.push('--', sanitizePath(path)); + args.push('--', sanitizeRelativePath(this.repositoryRoot, path)); const result = await this.exec(args); @@ -2753,7 +2771,7 @@ export class Repository { return { type: RefType.Head, name: branchName, - upstream: upstream ? { + upstream: upstream !== '' && status !== '[gone]' ? { name: upstreamRef ? upstreamRef.substring(11) : upstream.substring(index + 1), remote: remoteName ? remoteName : upstream.substring(0, index) } : undefined, @@ -2857,7 +2875,7 @@ export class Repository { } async getCommit(ref: string): Promise { - const result = await this.exec(['show', '-s', '--decorate=full', '--shortstat', `--format=${COMMIT_FORMAT}`, '-z', ref]); + const result = await this.exec(['show', '-s', '--decorate=full', '--shortstat', `--format=${COMMIT_FORMAT}`, '-z', ref, '--']); const commits = parseGitCommits(result.stdout); if (commits.length === 0) { return Promise.reject('bad commit format'); @@ -2896,7 +2914,7 @@ export class Repository { async updateSubmodules(paths: string[]): Promise { const args = ['submodule', 'update']; - for (const chunk of splitInChunks(paths.map(sanitizePath), MAX_CLI_LENGTH)) { + for (const chunk of splitInChunks(paths.map(p => sanitizeRelativePath(this.repositoryRoot, p)), MAX_CLI_LENGTH)) { await this.exec([...args, '--', ...chunk]); } } diff --git a/extensions/git/src/gitEditor.ts b/extensions/git/src/gitEditor.ts index 6291e5152a72..38001136956e 100644 --- a/extensions/git/src/gitEditor.ts +++ b/extensions/git/src/gitEditor.ts @@ -67,7 +67,7 @@ export class GitEditor implements IIPCHandler, ITerminalEnvironmentProvider { } export class GitEditorDocumentLinkProvider implements DocumentLinkProvider { - private readonly _regex = /^#\s+(modified|new file|deleted|renamed|copied|type change):\s+(?.*?)(?:\s+->\s+(?.*))*$/gm; + constructor(private readonly _model: Model) { } diff --git a/extensions/git/src/historyProvider.ts b/extensions/git/src/historyProvider.ts index f15c5899fdaf..8e5a8f9d2f14 100644 --- a/extensions/git/src/historyProvider.ts +++ b/extensions/git/src/historyProvider.ts @@ -163,7 +163,7 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec // Compute base if the branch has changed const mergeBase = await this.resolveHEADMergeBase(); - this._currentHistoryItemBaseRef = mergeBase && + this._currentHistoryItemBaseRef = mergeBase && mergeBase.name && mergeBase.remote && (mergeBase.remote !== this.repository.HEAD.upstream?.remote || mergeBase.name !== this.repository.HEAD.upstream?.name) ? { id: `refs/remotes/${mergeBase.remote}/${mergeBase.name}`, @@ -408,6 +408,10 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec const references: SourceControlHistoryItemRef[] = []; for (const ref of commit.refNames) { + if (ref === 'refs/remotes/origin/HEAD') { + continue; + } + switch (true) { case ref.startsWith('HEAD -> refs/heads/'): references.push({ diff --git a/extensions/git/src/operation.ts b/extensions/git/src/operation.ts index 65a932f77020..d8b2773f1c28 100644 --- a/extensions/git/src/operation.ts +++ b/extensions/git/src/operation.ts @@ -20,7 +20,7 @@ export const enum OperationKind { Config = 'Config', DeleteBranch = 'DeleteBranch', DeleteRef = 'DeleteRef', - DeleteRemoteTag = 'DeleteRemoteTag', + DeleteRemoteRef = 'DeleteRemoteRef', DeleteTag = 'DeleteTag', Diff = 'Diff', Fetch = 'Fetch', @@ -39,7 +39,6 @@ export const enum OperationKind { Merge = 'Merge', MergeAbort = 'MergeAbort', MergeBase = 'MergeBase', - MergeContinue = 'MergeContinue', Move = 'Move', PostCommitCommand = 'PostCommitCommand', Pull = 'Pull', @@ -67,13 +66,13 @@ export const enum OperationKind { export type Operation = AddOperation | ApplyOperation | BlameOperation | BranchOperation | CheckIgnoreOperation | CherryPickOperation | CheckoutOperation | CheckoutTrackingOperation | CleanOperation | CommitOperation | ConfigOperation | DeleteBranchOperation | - DeleteRefOperation | DeleteRemoteTagOperation | DeleteTagOperation | DiffOperation | FetchOperation | FindTrackingBranchesOperation | + DeleteRefOperation | DeleteRemoteRefOperation | DeleteTagOperation | DiffOperation | FetchOperation | FindTrackingBranchesOperation | GetBranchOperation | GetBranchesOperation | GetCommitTemplateOperation | GetObjectDetailsOperation | GetObjectFilesOperation | GetRefsOperation | GetRemoteRefsOperation | HashObjectOperation | IgnoreOperation | LogOperation | LogFileOperation | MergeOperation | MergeAbortOperation | - MergeBaseOperation | MergeContinueOperation | MoveOperation | PostCommitCommandOperation | PullOperation | PushOperation | RemoteOperation | - RenameBranchOperation | RemoveOperation | ResetOperation | RebaseOperation | RebaseAbortOperation | RebaseContinueOperation | RefreshOperation | - RevertFilesOperation | RevListOperation | RevParseOperation | SetBranchUpstreamOperation | ShowOperation | StageOperation | StatusOperation | - StashOperation | SubmoduleUpdateOperation | SyncOperation | TagOperation; + MergeBaseOperation | MoveOperation | PostCommitCommandOperation | PullOperation | PushOperation | RemoteOperation | RenameBranchOperation | + RemoveOperation | ResetOperation | RebaseOperation | RebaseAbortOperation | RebaseContinueOperation | RefreshOperation | RevertFilesOperation | + RevListOperation | RevParseOperation | SetBranchUpstreamOperation | ShowOperation | StageOperation | StatusOperation | StashOperation | + SubmoduleUpdateOperation | SyncOperation | TagOperation; type BaseOperation = { kind: OperationKind; blocking: boolean; readOnly: boolean; remote: boolean; retry: boolean; showProgress: boolean }; export type AddOperation = BaseOperation & { kind: OperationKind.Add }; @@ -89,7 +88,7 @@ export type CommitOperation = BaseOperation & { kind: OperationKind.Commit }; export type ConfigOperation = BaseOperation & { kind: OperationKind.Config }; export type DeleteBranchOperation = BaseOperation & { kind: OperationKind.DeleteBranch }; export type DeleteRefOperation = BaseOperation & { kind: OperationKind.DeleteRef }; -export type DeleteRemoteTagOperation = BaseOperation & { kind: OperationKind.DeleteRemoteTag }; +export type DeleteRemoteRefOperation = BaseOperation & { kind: OperationKind.DeleteRemoteRef }; export type DeleteTagOperation = BaseOperation & { kind: OperationKind.DeleteTag }; export type DiffOperation = BaseOperation & { kind: OperationKind.Diff }; export type FetchOperation = BaseOperation & { kind: OperationKind.Fetch }; @@ -108,7 +107,6 @@ export type LogFileOperation = BaseOperation & { kind: OperationKind.LogFile }; export type MergeOperation = BaseOperation & { kind: OperationKind.Merge }; export type MergeAbortOperation = BaseOperation & { kind: OperationKind.MergeAbort }; export type MergeBaseOperation = BaseOperation & { kind: OperationKind.MergeBase }; -export type MergeContinueOperation = BaseOperation & { kind: OperationKind.MergeContinue }; export type MoveOperation = BaseOperation & { kind: OperationKind.Move }; export type PostCommitCommandOperation = BaseOperation & { kind: OperationKind.PostCommitCommand }; export type PullOperation = BaseOperation & { kind: OperationKind.Pull }; @@ -147,7 +145,7 @@ export const Operation = { Config: (readOnly: boolean) => ({ kind: OperationKind.Config, blocking: false, readOnly, remote: false, retry: false, showProgress: false } as ConfigOperation), DeleteBranch: { kind: OperationKind.DeleteBranch, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as DeleteBranchOperation, DeleteRef: { kind: OperationKind.DeleteRef, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as DeleteRefOperation, - DeleteRemoteTag: { kind: OperationKind.DeleteRemoteTag, blocking: false, readOnly: false, remote: true, retry: false, showProgress: true } as DeleteRemoteTagOperation, + DeleteRemoteRef: { kind: OperationKind.DeleteRemoteRef, blocking: false, readOnly: false, remote: true, retry: false, showProgress: true } as DeleteRemoteRefOperation, DeleteTag: { kind: OperationKind.DeleteTag, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as DeleteTagOperation, Diff: { kind: OperationKind.Diff, blocking: false, readOnly: true, remote: false, retry: false, showProgress: false } as DiffOperation, Fetch: (showProgress: boolean) => ({ kind: OperationKind.Fetch, blocking: false, readOnly: false, remote: true, retry: true, showProgress } as FetchOperation), @@ -166,7 +164,6 @@ export const Operation = { Merge: { kind: OperationKind.Merge, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as MergeOperation, MergeAbort: { kind: OperationKind.MergeAbort, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as MergeAbortOperation, MergeBase: { kind: OperationKind.MergeBase, blocking: false, readOnly: true, remote: false, retry: false, showProgress: true } as MergeBaseOperation, - MergeContinue: { kind: OperationKind.MergeContinue, blocking: true, readOnly: false, remote: false, retry: false, showProgress: true } as MergeAbortOperation, Move: { kind: OperationKind.Move, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as MoveOperation, PostCommitCommand: { kind: OperationKind.PostCommitCommand, blocking: false, readOnly: false, remote: false, retry: false, showProgress: true } as PostCommitCommandOperation, Pull: { kind: OperationKind.Pull, blocking: true, readOnly: false, remote: true, retry: true, showProgress: true } as PullOperation, diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 560477c586d5..f32d915d7151 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -23,7 +23,7 @@ import { IPushErrorHandlerRegistry } from './pushError'; import { IRemoteSourcePublisherRegistry } from './remotePublisher'; import { StatusBarCommands } from './statusbar'; import { toGitUri } from './uri'; -import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, getCommitShortHash, IDisposable, isDescendant, onceEvent, pathEquals, relativePath } from './util'; +import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, getCommitShortHash, IDisposable, isDescendant, isLinuxSnap, isRemote, Limiter, onceEvent, pathEquals, relativePath } from './util'; import { IFileWatcher, watch } from './watch'; import { detectEncoding } from './encoding'; import { ISourceControlHistoryItemDetailsProviderRegistry } from './historyItemDetailsProvider'; @@ -1223,7 +1223,6 @@ export class Repository implements Disposable { } async stage(resource: Uri, contents: string): Promise { - const path = relativePath(this.repository.root, resource.fsPath).replace(/\\/g, '/'); await this.run(Operation.Stage, async () => { const configFiles = workspace.getConfiguration('files', Uri.file(resource.fsPath)); let encoding = configFiles.get('encoding') ?? 'utf8'; @@ -1235,7 +1234,7 @@ export class Repository implements Disposable { } encoding = iconv.encodingExists(encoding) ? encoding : 'utf8'; - await this.repository.stage(path, contents, encoding); + await this.repository.stage(resource.fsPath, contents, encoding); this._onDidChangeOriginalResource.fire(resource); this.closeDiffEditors([], [...resource.fsPath]); @@ -1294,20 +1293,7 @@ export class Repository implements Disposable { const workingGroupResources = opts.all && opts.all !== 'tracked' ? [...this.workingTreeGroup.resourceStates.map(r => r.resourceUri.fsPath)] : []; - if (this.mergeInProgress) { - await this.run( - Operation.MergeContinue, - async () => { - if (opts.all) { - const addOpts = opts.all === 'tracked' ? { update: true } : {}; - await this.repository.add([], addOpts); - } - - await this.repository.mergeContinue(); - await this.commitOperationCleanup(message, indexResources, workingGroupResources); - }, - () => this.commitOperationGetOptimisticResourceGroups(opts)); - } else if (this.rebaseCommit) { + if (this.rebaseCommit) { await this.run( Operation.RebaseContinue, async () => { @@ -1373,6 +1359,9 @@ export class Repository implements Disposable { } async clean(resources: Uri[]): Promise { + const config = workspace.getConfiguration('git'); + const discardUntrackedChangesToTrash = config.get('discardUntrackedChangesToTrash', true) && !isRemote && !isLinuxSnap; + await this.run( Operation.Clean(!this.optimisticUpdateEnabled()), async () => { @@ -1410,7 +1399,14 @@ export class Repository implements Disposable { } }); - await this.repository.clean(toClean); + if (discardUntrackedChangesToTrash) { + const limiter = new Limiter(5); + await Promise.all(toClean.map(fsPath => limiter.queue( + async () => await workspace.fs.delete(Uri.file(fsPath), { useTrash: true })))); + } else { + await this.repository.clean(toClean); + } + try { await this.repository.checkout('', toCheckout); } catch (err) { @@ -1536,7 +1532,11 @@ export class Repository implements Disposable { try { const mergeBase = await this.getConfig(mergeBaseConfigKey); const branchFromConfig = mergeBase !== '' ? await this.getBranch(mergeBase) : undefined; - if (branchFromConfig) { + + // There was a brief period of time when we would consider local branches as a valid + // merge base. Since then we have fixed the issue and only remote branches can be used + // as a merge base so we are adding an additional check. + if (branchFromConfig && branchFromConfig.remote) { return branchFromConfig; } } catch (err) { } @@ -1667,8 +1667,8 @@ export class Repository implements Disposable { await this.run(Operation.DeleteTag, () => this.repository.deleteTag(name)); } - async deleteRemoteTag(remoteName: string, tagName: string): Promise { - await this.run(Operation.DeleteRemoteTag, () => this.repository.deleteRemoteTag(remoteName, tagName)); + async deleteRemoteRef(remoteName: string, refName: string, options?: { force?: boolean }): Promise { + await this.run(Operation.DeleteRemoteRef, () => this.repository.deleteRemoteRef(remoteName, refName, options)); } async checkout(treeish: string, opts?: { detached?: boolean; pullBeforeCheckout?: boolean }): Promise { @@ -1976,18 +1976,17 @@ export class Repository implements Disposable { async show(ref: string, filePath: string): Promise { return await this.run(Operation.Show, async () => { - const path = relativePath(this.repository.root, filePath).replace(/\\/g, '/'); const configFiles = workspace.getConfiguration('files', Uri.file(filePath)); const defaultEncoding = configFiles.get('encoding'); const autoGuessEncoding = configFiles.get('autoGuessEncoding'); const candidateGuessEncodings = configFiles.get('candidateGuessEncodings'); try { - return await this.repository.bufferString(`${ref}:${path}`, defaultEncoding, autoGuessEncoding, candidateGuessEncodings); + return await this.repository.bufferString(ref, filePath, defaultEncoding, autoGuessEncoding, candidateGuessEncodings); } catch (err) { if (err.gitErrorCode === GitErrorCodes.WrongCase) { - const gitRelativePath = await this.repository.getGitRelativePath(ref, path); - return await this.repository.bufferString(`${ref}:${gitRelativePath}`, defaultEncoding, autoGuessEncoding, candidateGuessEncodings); + const gitFilePath = await this.repository.getGitFilePath(ref, filePath); + return await this.repository.bufferString(ref, gitFilePath, defaultEncoding, autoGuessEncoding, candidateGuessEncodings); } throw err; @@ -1996,18 +1995,15 @@ export class Repository implements Disposable { } async buffer(ref: string, filePath: string): Promise { - return this.run(Operation.Show, () => { - const path = relativePath(this.repository.root, filePath).replace(/\\/g, '/'); - return this.repository.buffer(`${ref}:${path}`); - }); + return this.run(Operation.Show, () => this.repository.buffer(ref, filePath)); } getObjectFiles(ref: string): Promise { return this.run(Operation.GetObjectFiles, () => this.repository.lstree(ref)); } - getObjectDetails(ref: string, filePath: string): Promise<{ mode: string; object: string; size: number }> { - return this.run(Operation.GetObjectDetails, () => this.repository.getObjectDetails(ref, filePath)); + getObjectDetails(ref: string, path: string): Promise<{ mode: string; object: string; size: number }> { + return this.run(Operation.GetObjectDetails, () => this.repository.getObjectDetails(ref, path)); } detectObjectType(object: string): Promise<{ mimetype: string; encoding?: string }> { diff --git a/extensions/git/src/staging.ts b/extensions/git/src/staging.ts index 14e4e379e478..ec7232bec44a 100644 --- a/extensions/git/src/staging.ts +++ b/extensions/git/src/staging.ts @@ -3,9 +3,16 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { TextDocument, Range, LineChange, Selection, Uri, TextEditor, TextEditorDiffInformation } from 'vscode'; +import { TextDocument, Range, Selection, Uri, TextEditor, TextEditorDiffInformation } from 'vscode'; import { fromGitUri, isGitUri } from './uri'; +export interface LineChange { + readonly originalStartLineNumber: number; + readonly originalEndLineNumber: number; + readonly modifiedStartLineNumber: number; + readonly modifiedEndLineNumber: number; +} + export function applyLineChanges(original: TextDocument, modified: TextDocument, diffs: LineChange[]): string { const result: string[] = []; let currentLine = 0; diff --git a/extensions/git/src/util.ts b/extensions/git/src/util.ts index 759ccdf82def..7dd1cbafbdf0 100644 --- a/extensions/git/src/util.ts +++ b/extensions/git/src/util.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Event, Disposable, EventEmitter, SourceControlHistoryItemRef, l10n, workspace, Uri } from 'vscode'; +import { Event, Disposable, EventEmitter, SourceControlHistoryItemRef, l10n, workspace, Uri, DiagnosticSeverity, env } from 'vscode'; import { dirname, sep, relative } from 'path'; import { Readable } from 'stream'; import { promises as fs, createReadStream } from 'fs'; @@ -11,6 +11,9 @@ import byline from 'byline'; export const isMacintosh = process.platform === 'darwin'; export const isWindows = process.platform === 'win32'; +export const isRemote = env.remoteName !== undefined; +export const isLinux = process.platform === 'linux'; +export const isLinuxSnap = isLinux && !!process.env['SNAP'] && !!process.env['SNAP_REVISION']; export function log(...args: any[]): void { console.log.apply(console, ['git:', ...args]); @@ -772,3 +775,15 @@ export function getCommitShortHash(scope: Uri, hash: string): string { const shortHashLength = config.get('commitShortHashLength', 7); return hash.substring(0, shortHashLength); } + +export type DiagnosticSeverityConfig = 'error' | 'warning' | 'information' | 'hint' | 'none'; + +export function toDiagnosticSeverity(value: DiagnosticSeverityConfig): DiagnosticSeverity { + return value === 'error' + ? DiagnosticSeverity.Error + : value === 'warning' + ? DiagnosticSeverity.Warning + : value === 'information' + ? DiagnosticSeverity.Information + : DiagnosticSeverity.Hint; +} diff --git a/extensions/git/tsconfig.json b/extensions/git/tsconfig.json index 42218d8decb0..c79be520be97 100644 --- a/extensions/git/tsconfig.json +++ b/extensions/git/tsconfig.json @@ -11,7 +11,6 @@ "src/**/*", "../../src/vscode-dts/vscode.d.ts", "../../src/vscode-dts/vscode.proposed.canonicalUriProvider.d.ts", - "../../src/vscode-dts/vscode.proposed.diffCommand.d.ts", "../../src/vscode-dts/vscode.proposed.editSessionIdentityProvider.d.ts", "../../src/vscode-dts/vscode.proposed.quickDiffProvider.d.ts", "../../src/vscode-dts/vscode.proposed.quickInputButtonLocation.d.ts", diff --git a/extensions/github-authentication/package-lock.json b/extensions/github-authentication/package-lock.json index cbc9e16b75f3..2aa199e80407 100644 --- a/extensions/github-authentication/package-lock.json +++ b/extensions/github-authentication/package-lock.json @@ -191,6 +191,20 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k= sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -212,36 +226,219 @@ "node": ">=0.4.0" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { - "mime-db": "1.44.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" diff --git a/extensions/github-authentication/package.json b/extensions/github-authentication/package.json index 80b5d2c920e8..96fbcd75d400 100644 --- a/extensions/github-authentication/package.json +++ b/extensions/github-authentication/package.json @@ -39,11 +39,12 @@ } ], "configuration": [{ - "title": "GitHub Enterprise Server Authentication Provider", + "title": "%config.github-enterprise.title%", "properties": { "github-enterprise.uri": { "type": "string", - "description": "GitHub Enterprise Server URI" + "markdownDescription": "%config.github-enterprise.uri.description%", + "pattern": "^(?:$|(https?)://(?!github\\.com).*)" } } } diff --git a/extensions/github-authentication/package.nls.json b/extensions/github-authentication/package.nls.json index 592a413b9a50..e326f00f5c91 100644 --- a/extensions/github-authentication/package.nls.json +++ b/extensions/github-authentication/package.nls.json @@ -1,4 +1,6 @@ { "displayName": "GitHub Authentication", - "description": "GitHub Authentication Provider" + "description": "GitHub Authentication Provider", + "config.github-enterprise.title": "GHE.com & GitHub Enterprise Server Authentication", + "config.github-enterprise.uri.description": "The URI for your GHE.com or GitHub Enterprise Server instance.\n\nExamples:\n* GHE.com: `https://octocat.ghe.com`\n* GitHub Enterprise Server: `https://github.octocat.com`\n\n> **Note:** This should _not_ be set to a GitHub.com URI. If your account exists on GitHub.com or is a GitHub Enterprise Managed User, you do not need any additional configuration and can simply log in to GitHub." } diff --git a/extensions/github-authentication/src/config.ts b/extensions/github-authentication/src/config.ts index 30b9dd662653..8cd3a9ed7931 100644 --- a/extensions/github-authentication/src/config.ts +++ b/extensions/github-authentication/src/config.ts @@ -10,6 +10,10 @@ export interface IConfig { } // For easy access to mixin client ID and secret +// +// NOTE: GitHub client secrets cannot be secured when running in a native client so in other words, the client secret is +// not really a secret... so we allow the client secret in code. It is brought in before we publish VS Code. Reference: +// https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/best-practices-for-creating-an-oauth-app#client-secrets export const Config: IConfig = { gitHubClientId: '01ab8ac9400c4e429b23' }; diff --git a/extensions/github/package-lock.json b/extensions/github/package-lock.json index 1b7dc727a928..cf7317a40a42 100644 --- a/extensions/github/package-lock.json +++ b/extensions/github/package-lock.json @@ -9,9 +9,9 @@ "version": "0.0.1", "license": "MIT", "dependencies": { - "@octokit/graphql": "5.0.5", + "@octokit/graphql": "8.2.0", "@octokit/graphql-schema": "14.4.0", - "@octokit/rest": "19.0.4", + "@octokit/rest": "21.1.0", "@vscode/extension-telemetry": "^0.9.8", "tunnel": "^0.0.6" }, @@ -147,96 +147,57 @@ "license": "MIT" }, "node_modules/@octokit/auth-token": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.1.tgz", - "integrity": "sha512-/USkK4cioY209wXRpund6HZzHo9GmjakpV9ycOkpMcMxMk7QVcVFVyCMtzvXYiHsB2crgDgrtNYSELYFBXhhaA==", - "dependencies": { - "@octokit/types": "^7.0.0" - }, + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", + "license": "MIT", "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-token/node_modules/@octokit/openapi-types": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.6.0.tgz", - "integrity": "sha512-bxftLwoZ2J6zsU1rzRvk0O32j7lVB0NWWn+P5CDHn9zPzytasR3hdAeXlTngRDkqv1LyEeuy5psVnDkmOSwrcQ==" - }, - "node_modules/@octokit/auth-token/node_modules/@octokit/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.2.0.tgz", - "integrity": "sha512-pYQ/a1U6mHptwhGyp6SvsiM4bWP2s3V95olUeTxas85D/2kN78yN5C8cGN+P4LwJSWUqIEyvq0Qn2WUn6NQRjw==", - "dependencies": { - "@octokit/openapi-types": "^13.6.0" + "node": ">= 18" } }, "node_modules/@octokit/core": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.0.5.tgz", - "integrity": "sha512-4R3HeHTYVHCfzSAi0C6pbGXV8UDI5Rk+k3G7kLVNckswN9mvpOzW9oENfjfH3nEmzg8y3AmKmzs8Sg6pLCeOCA==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz", + "integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==", + "license": "MIT", "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^7.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.1.2", + "@octokit/request": "^9.2.1", + "@octokit/request-error": "^6.1.7", + "@octokit/types": "^13.6.2", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.6.0.tgz", - "integrity": "sha512-bxftLwoZ2J6zsU1rzRvk0O32j7lVB0NWWn+P5CDHn9zPzytasR3hdAeXlTngRDkqv1LyEeuy5psVnDkmOSwrcQ==" - }, - "node_modules/@octokit/core/node_modules/@octokit/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.2.0.tgz", - "integrity": "sha512-pYQ/a1U6mHptwhGyp6SvsiM4bWP2s3V95olUeTxas85D/2kN78yN5C8cGN+P4LwJSWUqIEyvq0Qn2WUn6NQRjw==", - "dependencies": { - "@octokit/openapi-types": "^13.6.0" + "node": ">= 18" } }, "node_modules/@octokit/endpoint": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.1.tgz", - "integrity": "sha512-/wTXAJwt0HzJ2IeE4kQXO+mBScfzyCkI0hMtkIaqyXd9zg76OpOfNQfHL9FlaxAV2RsNiOXZibVWloy8EexENg==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz", + "integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==", + "license": "MIT", "dependencies": { - "@octokit/types": "^7.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" + "@octokit/types": "^13.6.2", + "universal-user-agent": "^7.0.2" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.6.0.tgz", - "integrity": "sha512-bxftLwoZ2J6zsU1rzRvk0O32j7lVB0NWWn+P5CDHn9zPzytasR3hdAeXlTngRDkqv1LyEeuy5psVnDkmOSwrcQ==" - }, - "node_modules/@octokit/endpoint/node_modules/@octokit/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.2.0.tgz", - "integrity": "sha512-pYQ/a1U6mHptwhGyp6SvsiM4bWP2s3V95olUeTxas85D/2kN78yN5C8cGN+P4LwJSWUqIEyvq0Qn2WUn6NQRjw==", - "dependencies": { - "@octokit/openapi-types": "^13.6.0" + "node": ">= 18" } }, "node_modules/@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.0.tgz", + "integrity": "sha512-gejfDywEml/45SqbWTWrhfwvLBrcGYhOn50sPOjIeVvH6i7D16/9xcFA8dAJNp2HMcd+g4vru41g4E2RBiZvfQ==", + "license": "MIT", "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" + "@octokit/request": "^9.1.4", + "@octokit/types": "^13.8.0", + "universal-user-agent": "^7.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/graphql-schema": { @@ -249,148 +210,103 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.1.0.tgz", - "integrity": "sha512-rnI26BAITDZTo5vqFOmA7oX4xRd18rO+gcK4MiTpJmsRMxAw0JmevNjPsjpry1bb9SVNo56P/0kbiyXXa4QluA==" + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-4.2.0.tgz", - "integrity": "sha512-8otLCIK9esfmOCY14CBnG/xPqv0paf14rc+s9tHpbOpeFwrv5CnECKW1qdqMAT60ngAa9eB1bKQ+l2YCpi0HPQ==", + "version": "11.4.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.2.tgz", + "integrity": "sha512-BXJ7XPCTDXFF+wxcg/zscfgw2O/iDPtNSkwwR1W1W5c4Mb3zav/M2XvxQ23nVmKj7jpweB4g8viMeCQdm7LMVA==", + "license": "MIT", "dependencies": { - "@octokit/types": "^7.2.0" + "@octokit/types": "^13.7.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=4" - } - }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.6.0.tgz", - "integrity": "sha512-bxftLwoZ2J6zsU1rzRvk0O32j7lVB0NWWn+P5CDHn9zPzytasR3hdAeXlTngRDkqv1LyEeuy5psVnDkmOSwrcQ==" - }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.2.0.tgz", - "integrity": "sha512-pYQ/a1U6mHptwhGyp6SvsiM4bWP2s3V95olUeTxas85D/2kN78yN5C8cGN+P4LwJSWUqIEyvq0Qn2WUn6NQRjw==", - "dependencies": { - "@octokit/openapi-types": "^13.6.0" + "@octokit/core": ">=6" } }, "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "@octokit/core": ">=3" + "@octokit/core": ">=6" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.4.0.tgz", - "integrity": "sha512-YP4eUqZ6vORy/eZOTdil1ZSrMt0kv7i/CVw+HhC2C0yJN+IqTc/rot957JQ7JfyeJD6HZOjLg6Jp1o9cPhI9KA==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.1.tgz", + "integrity": "sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ==", + "license": "MIT", "dependencies": { - "@octokit/types": "^7.2.0", - "deprecation": "^2.3.1" + "@octokit/types": "^13.8.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.6.0.tgz", - "integrity": "sha512-bxftLwoZ2J6zsU1rzRvk0O32j7lVB0NWWn+P5CDHn9zPzytasR3hdAeXlTngRDkqv1LyEeuy5psVnDkmOSwrcQ==" - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.2.0.tgz", - "integrity": "sha512-pYQ/a1U6mHptwhGyp6SvsiM4bWP2s3V95olUeTxas85D/2kN78yN5C8cGN+P4LwJSWUqIEyvq0Qn2WUn6NQRjw==", - "dependencies": { - "@octokit/openapi-types": "^13.6.0" + "@octokit/core": ">=6" } }, "node_modules/@octokit/request": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.1.tgz", - "integrity": "sha512-gYKRCia3cpajRzDSU+3pt1q2OcuC6PK8PmFIyxZDWCzRXRSIBH8jXjFJ8ZceoygBIm0KsEUg4x1+XcYBz7dHPQ==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.1.tgz", + "integrity": "sha512-TqHLIdw1KFvx8WvLc7Jv94r3C3+AzKY2FWq7c20zvrxmCIa6MCVkLCE/826NCXnml3LFJjLsidDh1BhMaGEDQw==", + "license": "MIT", "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^7.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" + "@octokit/endpoint": "^10.1.3", + "@octokit/request-error": "^6.1.6", + "@octokit/types": "^13.6.2", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/request-error": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.1.tgz", - "integrity": "sha512-ym4Bp0HTP7F3VFssV88WD1ZyCIRoE8H35pXSKwLeMizcdZAYc/t6N9X9Yr9n6t3aG9IH75XDnZ6UeZph0vHMWQ==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz", + "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==", + "license": "MIT", "dependencies": { - "@octokit/types": "^7.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" + "@octokit/types": "^13.6.2" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.6.0.tgz", - "integrity": "sha512-bxftLwoZ2J6zsU1rzRvk0O32j7lVB0NWWn+P5CDHn9zPzytasR3hdAeXlTngRDkqv1LyEeuy5psVnDkmOSwrcQ==" - }, - "node_modules/@octokit/request-error/node_modules/@octokit/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.2.0.tgz", - "integrity": "sha512-pYQ/a1U6mHptwhGyp6SvsiM4bWP2s3V95olUeTxas85D/2kN78yN5C8cGN+P4LwJSWUqIEyvq0Qn2WUn6NQRjw==", - "dependencies": { - "@octokit/openapi-types": "^13.6.0" - } - }, - "node_modules/@octokit/request/node_modules/@octokit/openapi-types": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-13.6.0.tgz", - "integrity": "sha512-bxftLwoZ2J6zsU1rzRvk0O32j7lVB0NWWn+P5CDHn9zPzytasR3hdAeXlTngRDkqv1LyEeuy5psVnDkmOSwrcQ==" - }, - "node_modules/@octokit/request/node_modules/@octokit/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-7.2.0.tgz", - "integrity": "sha512-pYQ/a1U6mHptwhGyp6SvsiM4bWP2s3V95olUeTxas85D/2kN78yN5C8cGN+P4LwJSWUqIEyvq0Qn2WUn6NQRjw==", - "dependencies": { - "@octokit/openapi-types": "^13.6.0" + "node": ">= 18" } }, "node_modules/@octokit/rest": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.4.tgz", - "integrity": "sha512-LwG668+6lE8zlSYOfwPj4FxWdv/qFXYBpv79TWIQEpBLKA9D/IMcWsF/U9RGpA3YqMVDiTxpgVpEW3zTFfPFTA==", + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.0.tgz", + "integrity": "sha512-93iLxcKDJboUpmnUyeJ6cRIi7z7cqTZT1K7kRK4LobGxwTwpsa+2tQQbRQNGy7IFDEAmrtkf4F4wBj3D5rVlJQ==", + "license": "MIT", "dependencies": { - "@octokit/core": "^4.0.0", - "@octokit/plugin-paginate-rest": "^4.0.0", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^6.0.0" + "@octokit/core": "^6.1.3", + "@octokit/plugin-paginate-rest": "^11.4.0", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.3.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/types": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.0.tgz", - "integrity": "sha512-xySzJG4noWrIBFyMu4lg4tu9vAgNg9S0aoLRONhAEz6ueyi1evBzb40HitIosaYS4XOexphG305IVcLrIX/30g==", + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^17.1.0" + "@octokit/openapi-types": "^23.0.1" } }, "node_modules/@types/node": { @@ -417,14 +333,26 @@ } }, "node_modules/before-after-hook": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", - "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "license": "Apache-2.0" + }, + "node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" }, "node_modules/graphql": { "version": "16.8.1", @@ -448,46 +376,6 @@ "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E= sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, "node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", @@ -508,28 +396,10 @@ "dev": true }, "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0= sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", + "license": "ISC" } } } diff --git a/extensions/github/package.json b/extensions/github/package.json index 524cee5bbea6..86adc2ddc4ed 100644 --- a/extensions/github/package.json +++ b/extensions/github/package.json @@ -227,9 +227,9 @@ "watch": "gulp watch-extension:github" }, "dependencies": { - "@octokit/graphql": "5.0.5", + "@octokit/graphql": "8.2.0", "@octokit/graphql-schema": "14.4.0", - "@octokit/rest": "19.0.4", + "@octokit/rest": "21.1.0", "tunnel": "^0.0.6", "@vscode/extension-telemetry": "^0.9.8" }, diff --git a/extensions/html-language-features/package-lock.json b/extensions/html-language-features/package-lock.json index 20b145615338..b4c79e11ea3f 100644 --- a/extensions/html-language-features/package-lock.json +++ b/extensions/html-language-features/package-lock.json @@ -173,9 +173,10 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c= sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg==" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } diff --git a/extensions/ipynb/package.json b/extensions/ipynb/package.json index 1cf1efd4e913..f43a494f66b0 100644 --- a/extensions/ipynb/package.json +++ b/extensions/ipynb/package.json @@ -71,6 +71,12 @@ "title": "%copyCellOutput.title%", "category": "Notebook" }, + { + "command": "notebook.cellOutput.addToChat", + "title": "%addCellOutputToChat.title%", + "category": "Notebook", + "enablement": "chatIsEnabled" + }, { "command": "notebook.cellOutput.openInTextEditor", "title": "%openCellOutput.title%", @@ -130,12 +136,18 @@ "webview/context": [ { "command": "notebook.cellOutput.copy", - "when": "webviewId == 'notebook.output' && webviewSection == 'image'" + "when": "webviewId == 'notebook.output' && webviewSection == 'image'", + "group": "context@1" }, { "command": "notebook.cellOutput.copy", "when": "webviewId == 'notebook.output' && webviewSection == 'text'" }, + { + "command": "notebook.cellOutput.addToChat", + "when": "webviewId == 'notebook.output' && webviewSection == 'image'", + "group": "context@2" + }, { "command": "notebook.cellOutput.openInTextEditor", "when": "webviewId == 'notebook.output' && webviewSection == 'text'" diff --git a/extensions/ipynb/package.nls.json b/extensions/ipynb/package.nls.json index 61eb74e242df..85ca7c5f2b3f 100644 --- a/extensions/ipynb/package.nls.json +++ b/extensions/ipynb/package.nls.json @@ -8,6 +8,7 @@ "openIpynbInNotebookEditor.title": "Open IPYNB File In Notebook Editor", "cleanInvalidImageAttachment.title": "Clean Invalid Image Attachment Reference", "copyCellOutput.title": "Copy Cell Output", + "addCellOutputToChat.title": "Add Cell Output to Chat", "openCellOutput.title": "Open Cell Output in Text Editor", "markdownAttachmentRenderer.displayName": { "message": "Markdown-It ipynb Cell Attachment renderer", diff --git a/extensions/ipynb/src/constants.ts b/extensions/ipynb/src/constants.ts index 9a82ccfae390..b72185968a81 100644 --- a/extensions/ipynb/src/constants.ts +++ b/extensions/ipynb/src/constants.ts @@ -5,7 +5,7 @@ import type { DocumentSelector } from 'vscode'; -export const defaultNotebookFormat = { major: 4, minor: 2 }; +export const defaultNotebookFormat = { major: 4, minor: 5 }; export const ATTACHMENT_CLEANUP_COMMANDID = 'ipynb.cleanInvalidImageAttachment'; export const JUPYTER_NOTEBOOK_MARKDOWN_SELECTOR: DocumentSelector = { notebookType: 'jupyter-notebook', language: 'markdown' }; diff --git a/extensions/ipynb/src/helper.ts b/extensions/ipynb/src/helper.ts index beab091f5c69..6d67b7d529fa 100644 --- a/extensions/ipynb/src/helper.ts +++ b/extensions/ipynb/src/helper.ts @@ -147,13 +147,15 @@ export interface ITask { /** * Copied from src/vs/base/common/uuid.ts */ -export function generateUuid() { - // use `randomValues` if possible - function getRandomValues(bucket: Uint8Array): Uint8Array { - for (let i = 0; i < bucket.length; i++) { - bucket[i] = Math.floor(Math.random() * 256); - } - return bucket; +export function generateUuid(): string { + // use `randomUUID` if possible + if (typeof crypto.randomUUID === 'function') { + // see https://developer.mozilla.org/en-US/docs/Web/API/Window/crypto + // > Although crypto is available on all windows, the returned Crypto object only has one + // > usable feature in insecure contexts: the getRandomValues() method. + // > In general, you should use this API only in secure contexts. + + return crypto.randomUUID.bind(crypto)(); } // prep-work @@ -164,7 +166,7 @@ export function generateUuid() { } // get data - getRandomValues(_data); + crypto.getRandomValues(_data); // set version bits _data[6] = (_data[6] & 0x0f) | 0x40; diff --git a/extensions/ipynb/src/ipynbMain.ts b/extensions/ipynb/src/ipynbMain.ts index e4fe302d1882..cc55d39e112a 100644 --- a/extensions/ipynb/src/ipynbMain.ts +++ b/extensions/ipynb/src/ipynbMain.ts @@ -8,6 +8,7 @@ import { activate as keepNotebookModelStoreInSync } from './notebookModelStoreSy import { notebookImagePasteSetup } from './notebookImagePaste'; import { AttachmentCleaner } from './notebookAttachmentCleaner'; import { serializeNotebookToString } from './serializers'; +import { defaultNotebookFormat } from './constants'; // From {nbformat.INotebookMetadata} in @jupyterlab/coreutils type NotebookMetadata = { @@ -86,8 +87,8 @@ export function activate(context: vscode.ExtensionContext, serializer: vscode.No data.metadata = { cells: [], metadata: {}, - nbformat: 4, - nbformat_minor: 2 + nbformat: defaultNotebookFormat.major, + nbformat_minor: defaultNotebookFormat.minor, }; const doc = await vscode.workspace.openNotebookDocument('jupyter-notebook', data); await vscode.window.showNotebookDocument(doc); diff --git a/extensions/ipynb/src/test/notebookModelStoreSync.test.ts b/extensions/ipynb/src/test/notebookModelStoreSync.test.ts index eab921672150..7174678ad61c 100644 --- a/extensions/ipynb/src/test/notebookModelStoreSync.test.ts +++ b/extensions/ipynb/src/test/notebookModelStoreSync.test.ts @@ -101,7 +101,8 @@ suite(`Notebook Model Store Sync`, () => { assert.strictEqual(editsApplied.length, 0); assert.strictEqual(cellMetadataUpdates.length, 0); }); - test('Adding cell will result in an update to the metadata', async () => { + test('Adding cell to nbformat 4.2 notebook will result in adding empty metadata', async () => { + sinon.stub(notebook, 'metadata').get(() => ({ nbformat: 4, nbformat_minor: 2 })); const cell: NotebookCell = { document: {} as any, executionSummary: {}, @@ -131,7 +132,7 @@ suite(`Notebook Model Store Sync`, () => { const newMetadata = cellMetadataUpdates[0].newCellMetadata; assert.deepStrictEqual(newMetadata, { execution_count: null, metadata: {} }); }); - test('Add cell id if nbformat is 4.5', async () => { + test('Added cell will have a cell id if nbformat is 4.5', async () => { sinon.stub(notebook, 'metadata').get(() => ({ nbformat: 4, nbformat_minor: 5 })); const cell: NotebookCell = { document: {} as any, diff --git a/extensions/ipynb/tsconfig.json b/extensions/ipynb/tsconfig.json index 2a6cc47eeeb9..ee21f68d22a2 100644 --- a/extensions/ipynb/tsconfig.json +++ b/extensions/ipynb/tsconfig.json @@ -6,7 +6,6 @@ }, "include": [ "src/**/*", - "../../src/vscode-dts/vscode.d.ts", - "../../src/vscode-dts/vscode.proposed.documentPaste.d.ts" + "../../src/vscode-dts/vscode.d.ts" ] } diff --git a/extensions/javascript/javascript-language-configuration.json b/extensions/javascript/javascript-language-configuration.json index c2444c453b2b..20827982072c 100644 --- a/extensions/javascript/javascript-language-configuration.json +++ b/extensions/javascript/javascript-language-configuration.json @@ -231,7 +231,7 @@ // Add // when pressing enter from inside line comment { "beforeText": { - "pattern": "(? { getRawData('data-initial-md-content'), 'text/html' ); - document.body.appendChild(markDownHtml.body); + document.body.append(...markDownHtml.body.children); // Restore const scrollProgress = state.scrollProgress; @@ -206,7 +207,8 @@ window.addEventListener('message', async event => { const root = document.querySelector('.markdown-body')!; const parser = new DOMParser(); - const newContent = parser.parseFromString(data.content, 'text/html'); // CodeQL [SM03712] This renderers content from the workspace into the Markdown preview. Webviews (and the markdown preview) have many other security measures in place to make this safe + const sanitizedContent = DOMPurify.sanitize(data.content); + const newContent = parser.parseFromString(sanitizedContent, 'text/html'); // CodeQL [SM03712] This renderers content from the workspace into the Markdown preview. Webviews (and the markdown preview) have many other security measures in place to make this safe // Strip out meta http-equiv tags for (const metaElement of Array.from(newContent.querySelectorAll('meta'))) { diff --git a/extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts b/extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts index 273fa56a6bb5..17f7ad1b8050 100644 --- a/extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts +++ b/extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts @@ -302,7 +302,7 @@ function escapeMarkdownLinkPath(mdPath: string): string { } function escapeBrackets(value: string): string { - value = value.replace(/[\[\]]/g, '\\$&'); // CodeQL [SM02383] The Markdown is fully sanitized after being rendered. + value = value.replace(/\\/g, '\\\\').replace(/[\[\]]/g, '\\$&'); // CodeQL [SM02383] The Markdown is fully sanitized after being rendered. return value; } diff --git a/extensions/markdown-language-features/src/languageFeatures/copyFiles/snippets.ts b/extensions/markdown-language-features/src/languageFeatures/copyFiles/snippets.ts index 854cf2175d0c..2430d21c342d 100644 --- a/extensions/markdown-language-features/src/languageFeatures/copyFiles/snippets.ts +++ b/extensions/markdown-language-features/src/languageFeatures/copyFiles/snippets.ts @@ -7,7 +7,7 @@ * Resolves variables in a VS Code snippet style string */ export function resolveSnippet(snippetString: string, vars: ReadonlyMap): string { - return snippetString.replaceAll(/(?\\\$)|(?\w+)(?:\/(?(?:\\\/|[^\}])+?)\/(?(?:\\\/|[^\}])+?)\/)?\}/g, (match, _escape, name, pattern, replacement, _offset, _str, groups) => { + return snippetString.replaceAll(/(?\\\$)|(?\w+)(?:\/(?(?:\\\/|[^\/}])+?)\/(?(?:\\\/|[^\/}])+?)\/)?\}/g, (match, _escape, name, pattern, replacement, _offset, _str, groups) => { if (groups?.['escape']) { return '$'; } diff --git a/extensions/markdown-language-features/src/logging.ts b/extensions/markdown-language-features/src/logging.ts index 6c114ae40e57..b5ea76f36081 100644 --- a/extensions/markdown-language-features/src/logging.ts +++ b/extensions/markdown-language-features/src/logging.ts @@ -6,87 +6,24 @@ import * as vscode from 'vscode'; import { Disposable } from './util/dispose'; -enum Trace { - Off, - Verbose -} - -namespace Trace { - export function fromString(value: string): Trace { - value = value.toLowerCase(); - switch (value) { - case 'off': - return Trace.Off; - case 'verbose': - return Trace.Verbose; - default: - return Trace.Off; - } - } -} export interface ILogger { - verbose(title: string, message: string, data?: any): void; + trace(title: string, message: string, data?: any): void; } export class VsCodeOutputLogger extends Disposable implements ILogger { - private _trace?: Trace; - - private _outputChannelValue?: vscode.OutputChannel; + private _outputChannelValue?: vscode.LogOutputChannel; private get _outputChannel() { - this._outputChannelValue ??= this._register(vscode.window.createOutputChannel('Markdown')); + this._outputChannelValue ??= this._register(vscode.window.createOutputChannel('Markdown', { log: true })); return this._outputChannelValue; } constructor() { super(); - - this._register(vscode.workspace.onDidChangeConfiguration(() => { - this._updateConfiguration(); - })); - - this._updateConfiguration(); - } - - public verbose(title: string, message: string, data?: any): void { - if (this._trace === Trace.Verbose) { - this._appendLine(`[Verbose ${this._now()}] ${title}: ${message}`); - if (data) { - this._appendLine(VsCodeOutputLogger._data2String(data)); - } - } - } - - private _now(): string { - const now = new Date(); - return String(now.getUTCHours()).padStart(2, '0') - + ':' + String(now.getMinutes()).padStart(2, '0') - + ':' + String(now.getUTCSeconds()).padStart(2, '0') + '.' + String(now.getMilliseconds()).padStart(3, '0'); - } - - private _updateConfiguration(): void { - this._trace = this._readTrace(); - } - - private _appendLine(value: string): void { - this._outputChannel.appendLine(value); - } - - private _readTrace(): Trace { - return Trace.fromString(vscode.workspace.getConfiguration().get('markdown.trace.extension', 'off')); } - private static _data2String(data: any): string { - if (data instanceof Error) { - if (typeof data.stack === 'string') { - return data.stack; - } - return data.message; - } - if (typeof data === 'string') { - return data; - } - return JSON.stringify(data, undefined, 2); + public trace(title: string, message: string, data?: any): void { + this._outputChannel.trace(`${title}: ${message}`, ...(data ? [JSON.stringify(data, null, 4)] : [])); } } diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index 83925eab1324..89363a77a86d 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -186,7 +186,7 @@ export class MarkdownItEngine implements IMdParser { return cached; } - this._logger.verbose('MarkdownItEngine', `tokenizeDocument - ${document.uri}`); + this._logger.trace('MarkdownItEngine', `tokenizeDocument - ${document.uri}`); const tokens = this._tokenizeString(document.getText(), engine); this._tokenCache.update(document, config, tokens); return tokens; diff --git a/extensions/markdown-language-features/src/preview/documentRenderer.ts b/extensions/markdown-language-features/src/preview/documentRenderer.ts index eeab8e19d9d6..8a39c9cdf4d3 100644 --- a/extensions/markdown-language-features/src/preview/documentRenderer.ts +++ b/extensions/markdown-language-features/src/preview/documentRenderer.ts @@ -79,7 +79,7 @@ export class MdDocumentRenderer { webviewResourceRoot: resourceProvider.asWebviewUri(markdownDocument.uri).toString(), }; - this._logger.verbose('DocumentRenderer', `provideTextDocumentContent - ${markdownDocument.uri}`, initialData); + this._logger.trace('DocumentRenderer', `provideTextDocumentContent - ${markdownDocument.uri}`, initialData); // Content Security Policy const nonce = getNonce(); diff --git a/extensions/markdown-language-features/src/preview/preview.ts b/extensions/markdown-language-features/src/preview/preview.ts index 7ccbc625b473..2d4186df9ae3 100644 --- a/extensions/markdown-language-features/src/preview/preview.ts +++ b/extensions/markdown-language-features/src/preview/preview.ts @@ -221,7 +221,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { return; } - this._logger.verbose('MarkdownPreview', 'updateForView', { markdownFile: this._resource }); + this._logger.trace('MarkdownPreview', 'updateForView', { markdownFile: this._resource }); this._line = topLine; this.postMessage({ type: 'updateView', diff --git a/extensions/markdown-language-features/src/test/nulLogging.ts b/extensions/markdown-language-features/src/test/nulLogging.ts index a786ab83b4f2..035e7d74c6dc 100644 --- a/extensions/markdown-language-features/src/test/nulLogging.ts +++ b/extensions/markdown-language-features/src/test/nulLogging.ts @@ -6,7 +6,7 @@ import { ILogger } from '../logging'; export const nulLogger = new class implements ILogger { - verbose(): void { + trace(): void { // noop } }; diff --git a/extensions/markdown-language-features/tsconfig.json b/extensions/markdown-language-features/tsconfig.json index 75edc8fdacfa..fcd79775de5f 100644 --- a/extensions/markdown-language-features/tsconfig.json +++ b/extensions/markdown-language-features/tsconfig.json @@ -5,7 +5,6 @@ }, "include": [ "src/**/*", - "../../src/vscode-dts/vscode.d.ts", - "../../src/vscode-dts/vscode.proposed.documentPaste.d.ts" + "../../src/vscode-dts/vscode.d.ts" ] } diff --git a/extensions/media-preview/media/imagePreview.js b/extensions/media-preview/media/imagePreview.js index ab8ad542a2d9..282e2a82cb94 100644 --- a/extensions/media-preview/media/imagePreview.js +++ b/extensions/media-preview/media/imagePreview.js @@ -311,7 +311,45 @@ document.body.classList.remove('loading'); }); - image.src = settings.src; + /** + * Validate and ensure only safe image sources can be used. + * @param {string} src + * @return {boolean} + */ + function isSafeImageSrc(src) { + try { + if (typeof src !== 'string' || src.length > 2048) { + return false; + } + // Allow http, https, file, and data URIs for images only + const allowedSchemes = ['http:', 'https:', 'file:']; + const urlMatch = src.match(/^([a-zA-Z0-9+.-]+):/); + if (!urlMatch) { + return false; + } + const scheme = urlMatch[1].toLowerCase() + ':'; + if (allowedSchemes.includes(scheme)) { + return true; + } + if (scheme === 'data:') { + // Allow only image media types in data URLs + // Disallow SVG images for data URIs to mitigate XSS + return /^data:image\/(png|jpe?g|gif|bmp|webp);base64,/.test(src); + } + return false; + } catch { + return false; + } + } + + if (isSafeImageSrc(settings.src)) { + image.src = settings.src; + } else { + console.error('Unsafe image src detected:', settings.src); + image.src = ''; + document.body.classList.add('error'); + document.body.classList.remove('loading'); + } document.querySelector('.open-file-link')?.addEventListener('click', (e) => { e.preventDefault(); diff --git a/extensions/media-preview/media/videoPreview.js b/extensions/media-preview/media/videoPreview.js index eeed26972a31..8ff6ddcb8d52 100644 --- a/extensions/media-preview/media/videoPreview.js +++ b/extensions/media-preview/media/videoPreview.js @@ -5,6 +5,18 @@ // @ts-check "use strict"; +// Returns true if src is a safe URL for video.src +function isSafeVideoSrc(src) { + try { + const allowedProtocols = ['http:', 'https:', 'blob:', 'filesystem:', '']; + // If relative URL, use document.baseURI as base + const url = new URL(src, document.baseURI); + return allowedProtocols.includes(url.protocol); + } catch { + return false; + } +} + (function () { // @ts-ignore const vscode = acquireVsCodeApi(); @@ -28,7 +40,7 @@ // Elements const video = document.createElement('video'); - if (settings.src !== null) { + if (settings.src !== null && isSafeVideoSrc(settings.src)) { video.src = settings.src; } video.playsInline = true; diff --git a/extensions/microsoft-authentication/package-lock.json b/extensions/microsoft-authentication/package-lock.json index 4aae40c5f170..69a49fe4a8c6 100644 --- a/extensions/microsoft-authentication/package-lock.json +++ b/extensions/microsoft-authentication/package-lock.json @@ -269,6 +269,20 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -290,6 +304,21 @@ "node": ">=0.4.0" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -298,20 +327,176 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -391,22 +576,34 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { - "mime-db": "1.44.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json index 4170a7787cfa..928ffa688899 100644 --- a/extensions/microsoft-authentication/package.json +++ b/extensions/microsoft-authentication/package.json @@ -115,23 +115,6 @@ "tags": [ "onExP" ] - }, - "microsoft-authentication.clientIdVersion": { - "type": "string", - "default": "v1", - "enum": [ - "v2", - "v1" - ], - "enumDescriptions": [ - "%microsoft-authentication.clientIdVersion.enumDescriptions.v2%", - "%microsoft-authentication.clientIdVersion.enumDescriptions.v1%" - ], - "markdownDescription": "%microsoft-authentication.clientIdVersion.description%", - "tags": [ - "onExP", - "experimental" - ] } } } diff --git a/extensions/microsoft-authentication/package.nls.json b/extensions/microsoft-authentication/package.nls.json index ece95ac75c30..c8e0189c08f9 100644 --- a/extensions/microsoft-authentication/package.nls.json +++ b/extensions/microsoft-authentication/package.nls.json @@ -12,9 +12,6 @@ }, "microsoft-authentication.implementation.enumDescriptions.msal": "Use the Microsoft Authentication Library (MSAL) to sign in with a Microsoft account.", "microsoft-authentication.implementation.enumDescriptions.classic": "(deprecated) Use the classic authentication flow to sign in with a Microsoft account.", - "microsoft-authentication.clientIdVersion.description": "The version of the Microsoft Account client ID to use for signing in with a Microsoft account. Only change this if you have been asked to. The default is `v1`.", - "microsoft-authentication.clientIdVersion.enumDescriptions.v1": "Use the v1 Microsoft Account client ID to sign in with a Microsoft account.", - "microsoft-authentication.clientIdVersion.enumDescriptions.v2": "Use the v2 Microsoft Account client ID to sign in with a Microsoft account.", "microsoft-sovereign-cloud.environment.description": { "message": "The Sovereign Cloud to use for authentication. If you select `custom`, you must also set the `#microsoft-sovereign-cloud.customEnvironment#` setting.", "comment": [ diff --git a/extensions/microsoft-authentication/src/common/accountAccess.ts b/extensions/microsoft-authentication/src/common/accountAccess.ts index a8fdeefef987..27d56b0bc1b7 100644 --- a/extensions/microsoft-authentication/src/common/accountAccess.ts +++ b/extensions/microsoft-authentication/src/common/accountAccess.ts @@ -3,35 +3,52 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable, Event, EventEmitter, SecretStorage } from 'vscode'; +import { Disposable, Event, EventEmitter, LogOutputChannel, SecretStorage } from 'vscode'; import { AccountInfo } from '@azure/msal-node'; -interface IAccountAccess { +export interface IAccountAccess { onDidAccountAccessChange: Event; isAllowedAccess(account: AccountInfo): boolean; - setAllowedAccess(account: AccountInfo, allowed: boolean): void; + setAllowedAccess(account: AccountInfo, allowed: boolean): Promise; } -export class ScopedAccountAccess implements IAccountAccess { +export class ScopedAccountAccess implements IAccountAccess, Disposable { private readonly _onDidAccountAccessChangeEmitter = new EventEmitter(); readonly onDidAccountAccessChange = this._onDidAccountAccessChangeEmitter.event; - private readonly _accountAccessSecretStorage: AccountAccessSecretStorage; - private value = new Array(); - constructor( - private readonly _secretStorage: SecretStorage, - private readonly _cloudName: string, - private readonly _clientId: string, - private readonly _authority: string + private readonly _disposable: Disposable; + + private constructor( + private readonly _accountAccessSecretStorage: IAccountAccessSecretStorage, + disposables: Disposable[] = [] ) { - this._accountAccessSecretStorage = new AccountAccessSecretStorage(this._secretStorage, this._cloudName, this._clientId, this._authority); - this._accountAccessSecretStorage.onDidChange(() => this.update()); + this._disposable = Disposable.from( + ...disposables, + this._onDidAccountAccessChangeEmitter, + this._accountAccessSecretStorage.onDidChange(() => this.update()) + ); } - initialize() { - return this.update(); + static async create( + secretStorage: SecretStorage, + cloudName: string, + logger: LogOutputChannel, + migrations: { clientId: string; authority: string }[] | undefined, + ): Promise { + const storage = await AccountAccessSecretStorage.create(secretStorage, cloudName, logger, migrations); + const access = new ScopedAccountAccess(storage, [storage]); + await access.initialize(); + return access; + } + + dispose() { + this._disposable.dispose(); + } + + private async initialize(): Promise { + await this.update(); } isAllowedAccess(account: AccountInfo): boolean { @@ -60,19 +77,26 @@ export class ScopedAccountAccess implements IAccountAccess { } } -export class AccountAccessSecretStorage { +interface IAccountAccessSecretStorage { + get(): Promise; + store(value: string[]): Thenable; + delete(): Thenable; + onDidChange: Event; +} + +class AccountAccessSecretStorage implements IAccountAccessSecretStorage, Disposable { private _disposable: Disposable; - private readonly _onDidChangeEmitter = new EventEmitter; + private readonly _onDidChangeEmitter = new EventEmitter(); readonly onDidChange: Event = this._onDidChangeEmitter.event; - private readonly _key = `accounts-${this._cloudName}-${this._clientId}-${this._authority}`; + private readonly _key = `accounts-${this._cloudName}`; - constructor( + private constructor( private readonly _secretStorage: SecretStorage, private readonly _cloudName: string, - private readonly _clientId: string, - private readonly _authority: string + private readonly _logger: LogOutputChannel, + private readonly _migrations?: { clientId: string; authority: string }[], ) { this._disposable = Disposable.from( this._onDidChangeEmitter, @@ -84,6 +108,48 @@ export class AccountAccessSecretStorage { ); } + static async create( + secretStorage: SecretStorage, + cloudName: string, + logger: LogOutputChannel, + migrations?: { clientId: string; authority: string }[], + ): Promise { + const storage = new AccountAccessSecretStorage(secretStorage, cloudName, logger, migrations); + await storage.initialize(); + return storage; + } + + /** + * TODO: Remove this method after a release with the migration + */ + private async initialize(): Promise { + if (!this._migrations) { + return; + } + const current = await this.get(); + // If the secret storage already has the new key, we have already run the migration + if (current) { + return; + } + try { + const allValues = new Set(); + for (const { clientId, authority } of this._migrations) { + const oldKey = `accounts-${this._cloudName}-${clientId}-${authority}`; + const value = await this._secretStorage.get(oldKey); + if (value) { + const parsed = JSON.parse(value) as string[]; + parsed.forEach(v => allValues.add(v)); + } + } + if (allValues.size > 0) { + await this.store(Array.from(allValues)); + } + } catch (e) { + // Migration is best effort + this._logger.error(`Failed to migrate account access secret storage: ${e}`); + } + } + async get(): Promise { const value = await this._secretStorage.get(this._key); if (!value) { diff --git a/extensions/microsoft-authentication/src/common/cachePlugin.ts b/extensions/microsoft-authentication/src/common/cachePlugin.ts index 91b4f0ee6a8e..b87fdb78d9b5 100644 --- a/extensions/microsoft-authentication/src/common/cachePlugin.ts +++ b/extensions/microsoft-authentication/src/common/cachePlugin.ts @@ -6,7 +6,7 @@ import { ICachePlugin, TokenCacheContext } from '@azure/msal-node'; import { Disposable, EventEmitter, SecretStorage } from 'vscode'; -export class SecretStorageCachePlugin implements ICachePlugin { +export class SecretStorageCachePlugin implements ICachePlugin, Disposable { private readonly _onDidChange: EventEmitter = new EventEmitter(); readonly onDidChange = this._onDidChange.event; diff --git a/extensions/microsoft-authentication/src/common/publicClientCache.ts b/extensions/microsoft-authentication/src/common/publicClientCache.ts index 925a4d1a88c3..acc8ba0d3077 100644 --- a/extensions/microsoft-authentication/src/common/publicClientCache.ts +++ b/extensions/microsoft-authentication/src/common/publicClientCache.ts @@ -2,23 +2,22 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import type { AccountInfo, AuthenticationResult, InteractiveRequest, SilentFlowRequest } from '@azure/msal-node'; +import type { AccountInfo, AuthenticationResult, InteractiveRequest, RefreshTokenRequest, SilentFlowRequest } from '@azure/msal-node'; import type { Disposable, Event } from 'vscode'; -export interface ICachedPublicClientApplication extends Disposable { - initialize(): Promise; +export interface ICachedPublicClientApplication { onDidAccountsChange: Event<{ added: AccountInfo[]; changed: AccountInfo[]; deleted: AccountInfo[] }>; onDidRemoveLastAccount: Event; acquireTokenSilent(request: SilentFlowRequest): Promise; acquireTokenInteractive(request: InteractiveRequest): Promise; + acquireTokenByRefreshToken(request: RefreshTokenRequest): Promise; removeAccount(account: AccountInfo): Promise; accounts: AccountInfo[]; clientId: string; - authority: string; } export interface ICachedPublicClientApplicationManager { onDidAccountsChange: Event<{ added: AccountInfo[]; changed: AccountInfo[]; deleted: AccountInfo[] }>; - getOrCreate(clientId: string, authority: string): Promise; + getOrCreate(clientId: string, refreshTokensToMigrate?: string[]): Promise; getAll(): ICachedPublicClientApplication[]; } diff --git a/extensions/microsoft-authentication/src/common/scopeData.ts b/extensions/microsoft-authentication/src/common/scopeData.ts index a43f2c431dd4..88a0aad68cc1 100644 --- a/extensions/microsoft-authentication/src/common/scopeData.ts +++ b/extensions/microsoft-authentication/src/common/scopeData.ts @@ -3,21 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { workspace } from 'vscode'; - -const DEFAULT_CLIENT_ID_V1 = 'aebc6443-996d-45c2-90f0-388ff96faa56'; -const DEFAULT_TENANT_V1 = 'organizations'; -const DEFAULT_CLIENT_ID_V2 = 'c27c220f-ce2f-4904-927d-333864217eeb'; -const DEFAULT_TENANT_V2 = 'common'; +const DEFAULT_CLIENT_ID = 'aebc6443-996d-45c2-90f0-388ff96faa56'; +const DEFAULT_TENANT = 'organizations'; const OIDC_SCOPES = ['openid', 'email', 'profile', 'offline_access']; const GRAPH_TACK_ON_SCOPE = 'User.Read'; export class ScopeData { - - private readonly _defaultClientId: string; - private readonly _defaultTenant: string; - /** * The full list of scopes including: * * the original scopes passed to the constructor @@ -42,47 +34,57 @@ export class ScopeData { readonly clientId: string; /** - * The tenant ID to use for the token request. This is the value of the `VSCODE_TENANT:...` scope if present, otherwise the default tenant ID. + * The tenant ID or `organizations`, `common`, `consumers` to use for the token request. This is the value of the `VSCODE_TENANT:...` scope if present, otherwise it's the default. */ readonly tenant: string; - constructor(readonly originalScopes: readonly string[] = []) { - if (workspace.getConfiguration('microsoft-authentication').get<'v1' | 'v2'>('clientIdVersion') === 'v2') { - this._defaultClientId = DEFAULT_CLIENT_ID_V2; - this._defaultTenant = DEFAULT_TENANT_V2; - } else { - this._defaultClientId = DEFAULT_CLIENT_ID_V1; - this._defaultTenant = DEFAULT_TENANT_V1; - } + /** + * The tenant ID to use for the token request. This will only ever be a GUID if one was specified via the `VSCODE_TENANT:...` scope, otherwise undefined. + */ + readonly tenantId: string | undefined; + constructor(readonly originalScopes: readonly string[] = []) { const modifiedScopes = [...originalScopes]; modifiedScopes.sort(); this.allScopes = modifiedScopes; this.scopeStr = modifiedScopes.join(' '); this.scopesToSend = this.getScopesToSend(modifiedScopes); this.clientId = this.getClientId(this.allScopes); - this.tenant = this.getTenantId(this.allScopes); + this.tenant = this.getTenant(this.allScopes); + this.tenantId = this.getTenantId(this.tenant); } - private getClientId(scopes: string[]) { + private getClientId(scopes: string[]): string { return scopes.reduce((prev, current) => { if (current.startsWith('VSCODE_CLIENT_ID:')) { return current.split('VSCODE_CLIENT_ID:')[1]; } return prev; - }, undefined) ?? this._defaultClientId; + }, undefined) ?? DEFAULT_CLIENT_ID; } - private getTenantId(scopes: string[]) { + private getTenant(scopes: string[]): string { return scopes.reduce((prev, current) => { if (current.startsWith('VSCODE_TENANT:')) { return current.split('VSCODE_TENANT:')[1]; } return prev; - }, undefined) ?? this._defaultTenant; + }, undefined) ?? DEFAULT_TENANT; + } + + private getTenantId(tenant: string): string | undefined { + switch (tenant) { + case 'organizations': + case 'common': + case 'consumers': + // These are not valid tenant IDs, so we return undefined + return undefined; + default: + return this.tenant; + } } - private getScopesToSend(scopes: string[]) { + private getScopesToSend(scopes: string[]): string[] { const scopesToSend = scopes.filter(s => !s.startsWith('VSCODE_')); const set = new Set(scopesToSend); diff --git a/extensions/microsoft-authentication/src/common/test/scopeData.test.ts b/extensions/microsoft-authentication/src/common/test/scopeData.test.ts index 9250d7cecbda..4c70e4fd07c8 100644 --- a/extensions/microsoft-authentication/src/common/test/scopeData.test.ts +++ b/extensions/microsoft-authentication/src/common/test/scopeData.test.ts @@ -56,4 +56,21 @@ suite('ScopeData', () => { const scopeData = new ScopeData(['custom_scope', 'VSCODE_TENANT:some_tenant']); assert.strictEqual(scopeData.tenant, 'some_tenant'); }); + + test('should have tenantId be undefined if no VSCODE_TENANT scope is present', () => { + const scopeData = new ScopeData(['custom_scope']); + assert.strictEqual(scopeData.tenantId, undefined); + }); + + test('should have tenantId be undefined if typical tenant values are present', () => { + for (const element of ['common', 'organizations', 'consumers']) { + const scopeData = new ScopeData(['custom_scope', `VSCODE_TENANT:${element}`]); + assert.strictEqual(scopeData.tenantId, undefined); + } + }); + + test('should have tenantId be the value of VSCODE_TENANT scope if set to a specific value', () => { + const scopeData = new ScopeData(['custom_scope', 'VSCODE_TENANT:some_guid']); + assert.strictEqual(scopeData.tenantId, 'some_guid'); + }); }); diff --git a/extensions/microsoft-authentication/src/extensionV2.ts b/extensions/microsoft-authentication/src/extensionV2.ts index 9610af37977c..978603ad1322 100644 --- a/extensions/microsoft-authentication/src/extensionV2.ts +++ b/extensions/microsoft-authentication/src/extensionV2.ts @@ -49,14 +49,13 @@ async function initMicrosoftSovereignCloudAuthProvider( return undefined; } - const authProvider = new MsalAuthProvider( + const authProvider = await MsalAuthProvider.create( context, new MicrosoftSovereignCloudAuthenticationTelemetryReporter(context.extension.packageJSON.aiKey), window.createOutputChannel(l10n.t('Microsoft Sovereign Cloud Authentication'), { log: true }), uriHandler, env ); - await authProvider.initialize(); const disposable = authentication.registerAuthenticationProvider( 'microsoft-sovereign-cloud', authProviderName, @@ -70,13 +69,12 @@ async function initMicrosoftSovereignCloudAuthProvider( export async function activate(context: ExtensionContext, mainTelemetryReporter: MicrosoftAuthenticationTelemetryReporter) { const uriHandler = new UriEventHandler(); context.subscriptions.push(uriHandler); - const authProvider = new MsalAuthProvider( + const authProvider = await MsalAuthProvider.create( context, mainTelemetryReporter, Logger, uriHandler ); - await authProvider.initialize(); context.subscriptions.push(authentication.registerAuthenticationProvider( 'microsoft', 'Microsoft', diff --git a/extensions/microsoft-authentication/src/node/authProvider.ts b/extensions/microsoft-authentication/src/node/authProvider.ts index 40000e086200..a26008fb7802 100644 --- a/extensions/microsoft-authentication/src/node/authProvider.ts +++ b/extensions/microsoft-authentication/src/node/authProvider.ts @@ -7,7 +7,7 @@ import { AuthenticationGetSessionOptions, AuthenticationProvider, Authentication import { Environment } from '@azure/ms-rest-azure-env'; import { CachedPublicClientApplicationManager } from './publicClientCache'; import { UriEventHandler } from '../UriEventHandler'; -import { ICachedPublicClientApplication } from '../common/publicClientCache'; +import { ICachedPublicClientApplication, ICachedPublicClientApplicationManager } from '../common/publicClientCache'; import { MicrosoftAccountType, MicrosoftAuthenticationTelemetryReporter } from '../common/telemetryReporter'; import { ScopeData } from '../common/scopeData'; import { EventBufferer } from '../common/event'; @@ -22,7 +22,6 @@ const MSA_PASSTHRU_TID = 'f8cdef31-a31e-4b4a-93e4-5f571e91255a'; export class MsalAuthProvider implements AuthenticationProvider { private readonly _disposables: { dispose(): void }[]; - private readonly _publicClientManager: CachedPublicClientApplicationManager; private readonly _eventBufferer = new EventBufferer(); /** @@ -43,20 +42,15 @@ export class MsalAuthProvider implements AuthenticationProvider { */ onDidChangeSessions = this._onDidChangeSessionsEmitter.event; - constructor( + private constructor( private readonly _context: ExtensionContext, private readonly _telemetryReporter: MicrosoftAuthenticationTelemetryReporter, private readonly _logger: LogOutputChannel, private readonly _uriHandler: UriEventHandler, + private readonly _publicClientManager: ICachedPublicClientApplicationManager, private readonly _env: Environment = Environment.AzureCloud ) { this._disposables = _context.subscriptions; - this._publicClientManager = new CachedPublicClientApplicationManager( - _context.globalState, - _context.secrets, - this._logger, - this._env.name - ); const accountChangeEvent = this._eventBufferer.wrapEvent( this._publicClientManager.onDidAccountsChange, (last, newEvent) => { @@ -81,11 +75,24 @@ export class MsalAuthProvider implements AuthenticationProvider { )(e => this._handleAccountChange(e)); this._disposables.push( this._onDidChangeSessionsEmitter, - this._publicClientManager, accountChangeEvent ); } + static async create( + context: ExtensionContext, + telemetryReporter: MicrosoftAuthenticationTelemetryReporter, + logger: LogOutputChannel, + uriHandler: UriEventHandler, + env: Environment = Environment.AzureCloud + ): Promise { + const publicClientManager = await CachedPublicClientApplicationManager.create(context.secrets, logger, env.name); + context.subscriptions.push(publicClientManager); + const authProvider = new MsalAuthProvider(context, telemetryReporter, logger, uriHandler, publicClientManager, env); + await authProvider.initialize(); + return authProvider; + } + /** * Migrate sessions from the old secret storage to MSAL. * TODO: MSAL Migration. Remove this when we remove the old flow. @@ -109,14 +116,12 @@ export class MsalAuthProvider implements AuthenticationProvider { clientTenantMap.get(key)!.refreshTokens.push(session.refreshToken); } - for (const { clientId, tenant, refreshTokens } of clientTenantMap.values()) { - await this.getOrCreatePublicClientApplication(clientId, tenant, refreshTokens); + for (const { clientId, refreshTokens } of clientTenantMap.values()) { + await this._publicClientManager.getOrCreate(clientId, refreshTokens); } } - async initialize(): Promise { - await this._eventBufferer.bufferEventsAsync(() => this._publicClientManager.initialize()); - + private async initialize(): Promise { if (!this._context.globalState.get('msalMigration', false)) { await this._migrateSessions(); } @@ -173,8 +178,8 @@ export class MsalAuthProvider implements AuthenticationProvider { return allSessions; } - const cachedPca = await this.getOrCreatePublicClientApplication(scopeData.clientId, scopeData.tenant); - const sessions = await this.getAllSessionsForPca(cachedPca, scopeData.originalScopes, scopeData.scopesToSend, options?.account); + const cachedPca = await this._publicClientManager.getOrCreate(scopeData.clientId); + const sessions = await this.getAllSessionsForPca(cachedPca, scopeData, options?.account); this._logger.info(`[getSessions] [${scopeData.scopeStr}] returned ${sessions.length} session(s)`); return sessions; @@ -185,7 +190,7 @@ export class MsalAuthProvider implements AuthenticationProvider { // Do NOT use `scopes` beyond this place in the code. Use `scopeData` instead. this._logger.info('[createSession]', `[${scopeData.scopeStr}]`, 'starting'); - const cachedPca = await this.getOrCreatePublicClientApplication(scopeData.clientId, scopeData.tenant); + const cachedPca = await this._publicClientManager.getOrCreate(scopeData.clientId); // Used for showing a friendlier message to the user when the explicitly cancel a flow. let userCancelled: boolean | undefined; @@ -211,6 +216,7 @@ export class MsalAuthProvider implements AuthenticationProvider { : ExtensionHost.WebWorker, }); + const authority = new URL(scopeData.tenant, this._env.activeDirectoryEndpointUrl).toString(); let lastError: Error | undefined; for (const flow of flows) { if (flow !== flows[0]) { @@ -223,6 +229,7 @@ export class MsalAuthProvider implements AuthenticationProvider { try { const result = await flow.trigger({ cachedPca, + authority, scopes: scopeData.scopesToSend, loginHint: options.account?.label, windowHandle: window.nativeHandle ? Buffer.from(window.nativeHandle) : undefined, @@ -260,7 +267,7 @@ export class MsalAuthProvider implements AuthenticationProvider { if (account.homeAccountId === sessionId) { this._telemetryReporter.sendLogoutEvent(); promises.push(cachedPca.removeAccount(account)); - this._logger.info(`[removeSession] [${sessionId}] [${cachedPca.clientId}] [${cachedPca.authority}] removing session...`); + this._logger.info(`[removeSession] [${sessionId}] [${cachedPca.clientId}] removing session...`); } } } @@ -281,26 +288,69 @@ export class MsalAuthProvider implements AuthenticationProvider { //#endregion - private async getOrCreatePublicClientApplication(clientId: string, tenant: string, refreshTokensToMigrate?: string[]): Promise { - const authority = new URL(tenant, this._env.activeDirectoryEndpointUrl).toString(); - return await this._publicClientManager.getOrCreate(clientId, authority, refreshTokensToMigrate); - } - private async getAllSessionsForPca( cachedPca: ICachedPublicClientApplication, - originalScopes: readonly string[], - scopesToSend: string[], + scopeData: ScopeData, accountFilter?: AuthenticationSessionAccountInformation ): Promise { - const accounts = accountFilter + let filteredAccounts = accountFilter ? cachedPca.accounts.filter(a => a.homeAccountId === accountFilter.id) : cachedPca.accounts; + + // Group accounts by homeAccountId + const accountGroups = new Map(); + for (const account of filteredAccounts) { + const existing = accountGroups.get(account.homeAccountId) || []; + existing.push(account); + accountGroups.set(account.homeAccountId, existing); + } + + // Filter to one account per homeAccountId + filteredAccounts = Array.from(accountGroups.values()).map(accounts => { + if (accounts.length === 1) { + return accounts[0]; + } + + // If we have a specific tenant to target, prefer that one + if (scopeData.tenantId) { + const matchingTenant = accounts.find(a => a.tenantId === scopeData.tenantId); + if (matchingTenant) { + return matchingTenant; + } + } + + // Otherwise prefer the home tenant + return accounts.find(a => a.tenantId === a.idTokenClaims?.tid) || accounts[0]; + }); + + const authority = new URL(scopeData.tenant, this._env.activeDirectoryEndpointUrl).toString(); const sessions: AuthenticationSession[] = []; return this._eventBufferer.bufferEventsAsync(async () => { - for (const account of accounts) { + for (const account of filteredAccounts) { try { - const result = await cachedPca.acquireTokenSilent({ account, scopes: scopesToSend, redirectUri }); - sessions.push(this.sessionFromAuthenticationResult(result, originalScopes)); + let forceRefresh: true | undefined; + if (scopeData.tenantId) { + // If the tenants do not match, then we need to skip the cache + // to get a new token for the new tenant + if (account.tenantId !== scopeData.tenantId) { + forceRefresh = true; + } + } else { + // If we are requesting the home tenant and we don't yet have + // a token for the home tenant, we need to skip the cache + // to get a new token for the home tenant + if (account.tenantId !== account.idTokenClaims?.tid) { + forceRefresh = true; + } + } + const result = await cachedPca.acquireTokenSilent({ + account, + authority, + scopes: scopeData.scopesToSend, + redirectUri, + forceRefresh + }); + sessions.push(this.sessionFromAuthenticationResult(result, scopeData.originalScopes)); } catch (e) { // If we can't get a token silently, the account is probably in a bad state so we should skip it // MSAL will log this already, so we don't need to log it again diff --git a/extensions/microsoft-authentication/src/node/cachedPublicClientApplication.ts b/extensions/microsoft-authentication/src/node/cachedPublicClientApplication.ts index 8d081f1a825b..f0f4eb7b9bcd 100644 --- a/extensions/microsoft-authentication/src/node/cachedPublicClientApplication.ts +++ b/extensions/microsoft-authentication/src/node/cachedPublicClientApplication.ts @@ -3,14 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { PublicClientApplication, AccountInfo, Configuration, SilentFlowRequest, AuthenticationResult, InteractiveRequest, LogLevel, RefreshTokenRequest } from '@azure/msal-node'; +import { PublicClientApplication, AccountInfo, SilentFlowRequest, AuthenticationResult, InteractiveRequest, LogLevel, RefreshTokenRequest } from '@azure/msal-node'; import { NativeBrokerPlugin } from '@azure/msal-node-extensions'; -import { Disposable, Memento, SecretStorage, LogOutputChannel, window, ProgressLocation, l10n, EventEmitter } from 'vscode'; +import { Disposable, SecretStorage, LogOutputChannel, window, ProgressLocation, l10n, EventEmitter } from 'vscode'; import { raceCancellationAndTimeoutError } from '../common/async'; import { SecretStorageCachePlugin } from '../common/cachePlugin'; import { MsalLoggerOptions } from '../common/loggerOptions'; import { ICachedPublicClientApplication } from '../common/publicClientCache'; -import { ScopedAccountAccess } from '../common/accountAccess'; +import { IAccountAccess } from '../common/accountAccess'; export class CachedPublicClientApplication implements ICachedPublicClientApplication { // Core properties @@ -23,11 +23,10 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica private readonly _secretStorageCachePlugin = new SecretStorageCachePlugin( this._secretStorage, // Include the prefix as a differentiator to other secrets - `pca:${JSON.stringify({ clientId: this._clientId, authority: this._authority })}` + `pca:${this._clientId}` ); // Broker properties - private readonly _accountAccess = new ScopedAccountAccess(this._secretStorage, this._cloudName, this._clientId, this._authority); private readonly _isBrokerAvailable: boolean; //#region Events @@ -40,24 +39,20 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica //#endregion - constructor( + private constructor( private readonly _clientId: string, - private readonly _authority: string, - private readonly _cloudName: string, - private readonly _globalMemento: Memento, private readonly _secretStorage: SecretStorage, - private readonly _logger: LogOutputChannel + private readonly _accountAccess: IAccountAccess, + private readonly _logger: LogOutputChannel, ) { - // TODO:@TylerLeonhardt clean up old use of memento. Remove this in an iteration - this._globalMemento.update(`lastRemoval:${this._clientId}:${this._authority}`, undefined); const loggerOptions = new MsalLoggerOptions(_logger); const nativeBrokerPlugin = new NativeBrokerPlugin(); - this._isBrokerAvailable = nativeBrokerPlugin.isBrokerAvailable ?? false; + this._isBrokerAvailable = nativeBrokerPlugin.isBrokerAvailable; this._pca = new PublicClientApplication({ - auth: { clientId: _clientId, authority: _authority }, + auth: { clientId: _clientId }, system: { loggerOptions: { - correlationId: `${_clientId}] [${_authority}`, + correlationId: _clientId, loggerCallback: (level, message, containsPii) => loggerOptions.loggerCallback(level, message, containsPii), logLevel: LogLevel.Trace } @@ -68,18 +63,26 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica this._disposable = Disposable.from( this._registerOnSecretStorageChanged(), this._onDidAccountsChangeEmitter, - this._onDidRemoveLastAccountEmitter + this._onDidRemoveLastAccountEmitter, + this._secretStorageCachePlugin ); } get accounts(): AccountInfo[] { return this._accounts; } get clientId(): string { return this._clientId; } - get authority(): string { return this._authority; } - async initialize(): Promise { - if (this._isBrokerAvailable) { - await this._accountAccess.initialize(); - } + static async create( + clientId: string, + secretStorage: SecretStorage, + accountAccess: IAccountAccess, + logger: LogOutputChannel + ): Promise { + const app = new CachedPublicClientApplication(clientId, secretStorage, accountAccess, logger); + await app.initialize(); + return app; + } + + private async initialize(): Promise { await this._sequencer.queue(() => this._update()); } @@ -88,9 +91,9 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica } async acquireTokenSilent(request: SilentFlowRequest): Promise { - this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${this._authority}] [${request.scopes.join(' ')}] [${request.account.username}] starting...`); + this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] starting...`); let result = await this._sequencer.queue(() => this._pca.acquireTokenSilent(request)); - this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${this._authority}] [${request.scopes.join(' ')}] [${request.account.username}] got result`); + this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] got result`); // Check expiration of id token and if it's 5min before expiration, force a refresh. // this is what MSAL does for access tokens already so we're just adding it for id tokens since we care about those. // NOTE: Once we stop depending on id tokens for some things we can remove all of this. @@ -101,13 +104,13 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica * 1000 // convert to milliseconds ); if (fiveMinutesBefore < new Date()) { - this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${this._authority}] [${request.scopes.join(' ')}] [${request.account.username}] id token is expired or about to expire. Forcing refresh...`); + this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] id token is expired or about to expire. Forcing refresh...`); const newRequest = this._isBrokerAvailable // HACK: Broker doesn't support forceRefresh so we need to pass in claims which will force a refresh ? { ...request, claims: '{ "id_token": {}}' } : { ...request, forceRefresh: true }; result = await this._sequencer.queue(() => this._pca.acquireTokenSilent(newRequest)); - this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${this._authority}] [${request.scopes.join(' ')}] [${request.account.username}] got forced result`); + this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] got forced result`); } const newIdTokenExpirationInSecs = (result.idTokenClaims as { exp?: number }).exp; if (newIdTokenExpirationInSecs) { @@ -116,15 +119,15 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica * 1000 // convert to milliseconds ); if (fiveMinutesBefore < new Date()) { - this._logger.error(`[acquireTokenSilent] [${this._clientId}] [${this._authority}] [${request.scopes.join(' ')}] [${request.account.username}] id token is still expired.`); + this._logger.error(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] id token is still expired.`); // HACK: Only for the Broker we try one more time with different claims to force a refresh. Why? We've seen the Broker caching tokens by the claims requested, thus // there has been a situation where both tokens are expired. if (this._isBrokerAvailable) { - this._logger.error(`[acquireTokenSilent] [${this._clientId}] [${this._authority}] [${request.scopes.join(' ')}] [${request.account.username}] forcing refresh with different claims...`); + this._logger.error(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] forcing refresh with different claims...`); const newRequest = { ...request, claims: '{ "access_token": {}}' }; result = await this._sequencer.queue(() => this._pca.acquireTokenSilent(newRequest)); - this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${this._authority}] [${request.scopes.join(' ')}] [${request.account.username}] got forced result with different claims`); + this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] got forced result with different claims`); const newIdTokenExpirationInSecs = (result.idTokenClaims as { exp?: number }).exp; if (newIdTokenExpirationInSecs) { const fiveMinutesBefore = new Date( @@ -132,7 +135,7 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica * 1000 // convert to milliseconds ); if (fiveMinutesBefore < new Date()) { - this._logger.error(`[acquireTokenSilent] [${this._clientId}] [${this._authority}] [${request.scopes.join(' ')}] [${request.account.username}] id token is still expired.`); + this._logger.error(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] id token is still expired.`); } } } @@ -140,15 +143,17 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica } } - if (result.account && !result.fromCache && this._verifyIfUsingBroker(result)) { - this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${this._authority}] [${request.scopes.join(' ')}] [${request.account.username}] firing event due to change`); + if (!result.account) { + this._logger.error(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] no account found in result`); + } else if (!result.fromCache && this._verifyIfUsingBroker(result)) { + this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] firing event due to change`); this._onDidAccountsChangeEmitter.fire({ added: [], changed: [result.account], deleted: [] }); } return result; } async acquireTokenInteractive(request: InteractiveRequest): Promise { - this._logger.debug(`[acquireTokenInteractive] [${this._clientId}] [${this._authority}] [${request.scopes?.join(' ')}] loopbackClientOverride: ${request.loopbackClient ? 'true' : 'false'}`); + this._logger.debug(`[acquireTokenInteractive] [${this._clientId}] [${request.authority}] [${request.scopes?.join(' ')}] loopbackClientOverride: ${request.loopbackClient ? 'true' : 'false'}`); return await window.withProgress( { location: ProgressLocation.Notification, @@ -180,9 +185,17 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica * @param request a {@link RefreshTokenRequest} object that contains the refresh token and other parameters. * @returns an {@link AuthenticationResult} object that contains the result of the token acquisition operation. */ - async acquireTokenByRefreshToken(request: RefreshTokenRequest) { - this._logger.debug(`[acquireTokenByRefreshToken] [${this._clientId}] [${this._authority}] [${request.scopes.join(' ')}]`); - const result = await this._sequencer.queue(() => this._pca.acquireTokenByRefreshToken(request)); + async acquireTokenByRefreshToken(request: RefreshTokenRequest): Promise { + this._logger.debug(`[acquireTokenByRefreshToken] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}]`); + const result = await this._sequencer.queue(async () => { + const result = await this._pca.acquireTokenByRefreshToken(request); + // Force an update so that the account cache is updated. + // TODO:@TylerLeonhardt The problem is, we use the sequencer for + // change events but we _don't_ use it for the accounts cache. + // We should probably use it for the accounts cache as well. + await this._update(); + return result; + }); if (result) { // this._setupRefresh(result); if (this._isBrokerAvailable && result.account) { @@ -213,7 +226,14 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica if (!result.fromNativeBroker) { return true; } - const key = result.account!.homeAccountId; + // The nativeAccountId is what the broker uses to differenciate all + // types of accounts. Even if the "account" is a duplicate of another because + // it's actaully a guest account in another tenant. + let key = result.account!.nativeAccountId; + if (!key) { + this._logger.error(`[verifyIfUsingBroker] [${this._clientId}] [${result.account!.username}] no nativeAccountId found. Using homeAccountId instead.`); + key = result.account!.homeAccountId; + } const lastSeen = this._lastSeen.get(key); const lastTimeAuthed = result.account!.idTokenClaims!.iat!; if (!lastSeen) { @@ -229,7 +249,7 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica private async _update() { const before = this._accounts; - this._logger.debug(`[update] [${this._clientId}] [${this._authority}] CachedPublicClientApplication update before: ${before.length}`); + this._logger.debug(`[update] [${this._clientId}] CachedPublicClientApplication update before: ${before.length}`); // Clear in-memory cache so we know we're getting account data from the SecretStorage this._pca.clearCache(); let after = await this._pca.getAllAccounts(); @@ -237,7 +257,7 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica after = after.filter(a => this._accountAccess.isAllowedAccess(a)); } this._accounts = after; - this._logger.debug(`[update] [${this._clientId}] [${this._authority}] CachedPublicClientApplication update after: ${after.length}`); + this._logger.debug(`[update] [${this._clientId}] CachedPublicClientApplication update after: ${after.length}`); const beforeSet = new Set(before.map(b => b.homeAccountId)); const afterSet = new Set(after.map(a => a.homeAccountId)); @@ -246,13 +266,13 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica const deleted = before.filter(b => !afterSet.has(b.homeAccountId)); if (added.length > 0 || deleted.length > 0) { this._onDidAccountsChangeEmitter.fire({ added, changed: [], deleted }); - this._logger.debug(`[update] [${this._clientId}] [${this._authority}] CachedPublicClientApplication accounts changed. added: ${added.length}, deleted: ${deleted.length}`); + this._logger.debug(`[update] [${this._clientId}] CachedPublicClientApplication accounts changed. added: ${added.length}, deleted: ${deleted.length}`); if (!after.length) { - this._logger.debug(`[update] [${this._clientId}] [${this._authority}] CachedPublicClientApplication final account deleted. Firing event.`); + this._logger.debug(`[update] [${this._clientId}] CachedPublicClientApplication final account deleted. Firing event.`); this._onDidRemoveLastAccountEmitter.fire(); } } - this._logger.debug(`[update] [${this._clientId}] [${this._authority}] CachedPublicClientApplication update complete`); + this._logger.debug(`[update] [${this._clientId}] CachedPublicClientApplication update complete`); } } diff --git a/extensions/microsoft-authentication/src/node/flows.ts b/extensions/microsoft-authentication/src/node/flows.ts index c6f40a943f61..ac678d8313dc 100644 --- a/extensions/microsoft-authentication/src/node/flows.ts +++ b/extensions/microsoft-authentication/src/node/flows.ts @@ -25,6 +25,7 @@ interface IMsalFlowOptions { interface IMsalFlowTriggerOptions { cachedPca: ICachedPublicClientApplication; + authority: string; scopes: string[]; loginHint?: string; windowHandle?: Buffer; @@ -45,11 +46,12 @@ class DefaultLoopbackFlow implements IMsalFlow { supportsWebWorkerExtensionHost: false }; - async trigger({ cachedPca, scopes, loginHint, windowHandle, logger }: IMsalFlowTriggerOptions): Promise { + async trigger({ cachedPca, authority, scopes, loginHint, windowHandle, logger }: IMsalFlowTriggerOptions): Promise { logger.info('Trying default msal flow...'); return await cachedPca.acquireTokenInteractive({ openBrowser: async (url: string) => { await env.openExternal(Uri.parse(url)); }, scopes, + authority, successTemplate: loopbackTemplate, errorTemplate: loopbackTemplate, loginHint, @@ -66,12 +68,13 @@ class UrlHandlerFlow implements IMsalFlow { supportsWebWorkerExtensionHost: false }; - async trigger({ cachedPca, scopes, loginHint, windowHandle, logger, uriHandler }: IMsalFlowTriggerOptions): Promise { + async trigger({ cachedPca, authority, scopes, loginHint, windowHandle, logger, uriHandler }: IMsalFlowTriggerOptions): Promise { logger.info('Trying protocol handler flow...'); const loopbackClient = new UriHandlerLoopbackClient(uriHandler, redirectUri, logger); return await cachedPca.acquireTokenInteractive({ openBrowser: (url: string) => loopbackClient.openBrowser(url), scopes, + authority, loopbackClient, loginHint, prompt: loginHint ? undefined : 'select_account', diff --git a/extensions/microsoft-authentication/src/node/publicClientCache.ts b/extensions/microsoft-authentication/src/node/publicClientCache.ts index f4f19ff8df53..16ccb80321fd 100644 --- a/extensions/microsoft-authentication/src/node/publicClientCache.ts +++ b/extensions/microsoft-authentication/src/node/publicClientCache.ts @@ -7,6 +7,7 @@ import { AccountInfo } from '@azure/msal-node'; import { SecretStorage, LogOutputChannel, Disposable, EventEmitter, Memento, Event } from 'vscode'; import { ICachedPublicClientApplication, ICachedPublicClientApplicationManager } from '../common/publicClientCache'; import { CachedPublicClientApplication } from './cachedPublicClientApplication'; +import { IAccountAccess, ScopedAccountAccess } from '../common/accountAccess'; export interface IPublicClientApplicationInfo { clientId: string; @@ -14,56 +15,68 @@ export interface IPublicClientApplicationInfo { } export class CachedPublicClientApplicationManager implements ICachedPublicClientApplicationManager { - // The key is the clientId and authority JSON stringified - private readonly _pcas = new Map(); + // The key is the clientId + private readonly _pcas = new Map(); private readonly _pcaDisposables = new Map(); private _disposable: Disposable; - private _pcasSecretStorage: PublicClientApplicationsSecretStorage; private readonly _onDidAccountsChangeEmitter = new EventEmitter<{ added: AccountInfo[]; changed: AccountInfo[]; deleted: AccountInfo[] }>(); readonly onDidAccountsChange = this._onDidAccountsChangeEmitter.event; - constructor( - private readonly _globalMemento: Memento, + private constructor( + private readonly _pcasSecretStorage: IPublicClientApplicationSecretStorage, + private readonly _accountAccess: IAccountAccess, private readonly _secretStorage: SecretStorage, private readonly _logger: LogOutputChannel, - private readonly _cloudName: string + disposables: Disposable[] ) { - this._pcasSecretStorage = new PublicClientApplicationsSecretStorage(_secretStorage, _cloudName); this._disposable = Disposable.from( - this._pcasSecretStorage, + ...disposables, this._registerSecretStorageHandler(), this._onDidAccountsChangeEmitter ); } + static async create( + secretStorage: SecretStorage, + logger: LogOutputChannel, + cloudName: string + ): Promise { + const pcasSecretStorage = await PublicClientApplicationsSecretStorage.create(secretStorage, cloudName); + // TODO: Remove the migrations in a version + const migrations = await pcasSecretStorage.getOldValue(); + const accountAccess = await ScopedAccountAccess.create(secretStorage, cloudName, logger, migrations); + const manager = new CachedPublicClientApplicationManager(pcasSecretStorage, accountAccess, secretStorage, logger, [pcasSecretStorage, accountAccess]); + await manager.initialize(); + return manager; + } + private _registerSecretStorageHandler() { return this._pcasSecretStorage.onDidChange(() => this._handleSecretStorageChange()); } - async initialize() { + private async initialize() { this._logger.debug('[initialize] Initializing PublicClientApplicationManager'); - let keys: string[] | undefined; + let clientIds: string[] | undefined; try { - keys = await this._pcasSecretStorage.get(); + clientIds = await this._pcasSecretStorage.get(); } catch (e) { // data is corrupted this._logger.error('[initialize] Error initializing PublicClientApplicationManager:', e); await this._pcasSecretStorage.delete(); } - if (!keys) { + if (!clientIds) { return; } const promises = new Array>(); - for (const key of keys) { + for (const clientId of clientIds) { try { - const { clientId, authority } = JSON.parse(key) as IPublicClientApplicationInfo; // Load the PCA in memory - promises.push(this._doCreatePublicClientApplication(clientId, authority, key)); + promises.push(this._doCreatePublicClientApplication(clientId)); } catch (e) { - this._logger.error('[initialize] Error intitializing PCA:', key); + this._logger.error('[initialize] Error intitializing PCA:', clientId); } } @@ -75,11 +88,11 @@ export class CachedPublicClientApplicationManager implements ICachedPublicClient } else { if (!result.value.accounts.length) { pcasChanged = true; - const pcaKey = JSON.stringify({ clientId: result.value.clientId, authority: result.value.authority }); - this._pcaDisposables.get(pcaKey)?.dispose(); - this._pcaDisposables.delete(pcaKey); - this._pcas.delete(pcaKey); - this._logger.debug(`[initialize] [${result.value.clientId}] [${result.value.authority}] PCA disposed because it's empty.`); + const clientId = result.value.clientId; + this._pcaDisposables.get(clientId)?.dispose(); + this._pcaDisposables.delete(clientId); + this._pcas.delete(clientId); + this._logger.debug(`[initialize] [${clientId}] PCA disposed because it's empty.`); } } } @@ -94,43 +107,39 @@ export class CachedPublicClientApplicationManager implements ICachedPublicClient Disposable.from(...this._pcaDisposables.values()).dispose(); } - async getOrCreate(clientId: string, authority: string, refreshTokensToMigrate?: string[]): Promise { - // Use the clientId and authority as the key - const pcasKey = JSON.stringify({ clientId, authority }); - let pca = this._pcas.get(pcasKey); + async getOrCreate(clientId: string, refreshTokensToMigrate?: string[]): Promise { + let pca = this._pcas.get(clientId); if (pca) { - this._logger.debug(`[getOrCreate] [${clientId}] [${authority}] PublicClientApplicationManager cache hit`); + this._logger.debug(`[getOrCreate] [${clientId}] PublicClientApplicationManager cache hit`); } else { - this._logger.debug(`[getOrCreate] [${clientId}] [${authority}] PublicClientApplicationManager cache miss, creating new PCA...`); - pca = await this._doCreatePublicClientApplication(clientId, authority, pcasKey); + this._logger.debug(`[getOrCreate] [${clientId}] PublicClientApplicationManager cache miss, creating new PCA...`); + pca = await this._doCreatePublicClientApplication(clientId); await this._storePublicClientApplications(); - this._logger.debug(`[getOrCreate] [${clientId}] [${authority}] PCA created.`); + this._logger.debug(`[getOrCreate] [${clientId}] PCA created.`); } // TODO: MSAL Migration. Remove this when we remove the old flow. if (refreshTokensToMigrate?.length) { - this._logger.debug(`[getOrCreate] [${clientId}] [${authority}] Migrating refresh tokens to PCA...`); + this._logger.debug(`[getOrCreate] [${clientId}] Migrating refresh tokens to PCA...`); for (const refreshToken of refreshTokensToMigrate) { try { // Use the refresh token to acquire a result. This will cache the refresh token for future operations. // The scopes don't matter here since we can create any token from the refresh token. const result = await pca.acquireTokenByRefreshToken({ refreshToken, forceCache: true, scopes: [] }); if (result?.account) { - this._logger.debug(`[getOrCreate] [${clientId}] [${authority}] Refresh token migrated to PCA.`); + this._logger.debug(`[getOrCreate] [${clientId}] Refresh token migrated to PCA.`); } } catch (e) { - this._logger.error(`[getOrCreate] [${clientId}] [${authority}] Error migrating refresh token:`, e); + this._logger.error(`[getOrCreate] [${clientId}] Error migrating refresh token:`, e); } } - // reinitialize the PCA so the account is properly cached - await pca.initialize(); } return pca; } - private async _doCreatePublicClientApplication(clientId: string, authority: string, pcasKey: string) { - const pca = new CachedPublicClientApplication(clientId, authority, this._cloudName, this._globalMemento, this._secretStorage, this._logger); - this._pcas.set(pcasKey, pca); + private async _doCreatePublicClientApplication(clientId: string): Promise { + const pca = await CachedPublicClientApplication.create(clientId, this._secretStorage, this._accountAccess, this._logger); + this._pcas.set(clientId, pca); const disposable = Disposable.from( pca, pca.onDidAccountsChange(e => this._onDidAccountsChangeEmitter.fire(e)), @@ -138,15 +147,17 @@ export class CachedPublicClientApplicationManager implements ICachedPublicClient // The PCA has no more accounts, so we can dispose it so we're not keeping it // around forever. disposable.dispose(); - this._pcaDisposables.delete(pcasKey); - this._pcas.delete(pcasKey); - this._logger.debug(`[_doCreatePublicClientApplication] [${clientId}] [${authority}] PCA disposed. Firing off storing of PCAs...`); + this._pcaDisposables.delete(clientId); + this._pcas.delete(clientId); + this._logger.debug(`[_doCreatePublicClientApplication] [${clientId}] PCA disposed. Firing off storing of PCAs...`); void this._storePublicClientApplications(); }) ); - this._pcaDisposables.set(pcasKey, disposable); - // Intialize the PCA after the `onDidAccountsChange` is set so we get initial state. - await pca.initialize(); + this._pcaDisposables.set(clientId, disposable); + // Fire for the initial state and only if accounts exist + if (pca.accounts.length > 0) { + this._onDidAccountsChangeEmitter.fire({ added: pca.accounts, changed: [], deleted: [] }); + } return pca; } @@ -183,15 +194,14 @@ export class CachedPublicClientApplicationManager implements ICachedPublicClient } // Handle the new ones - for (const newPca of pcaKeysFromStorage) { + for (const clientId of pcaKeysFromStorage) { try { - const { clientId, authority } = JSON.parse(newPca); - this._logger.debug(`[_handleSecretStorageChange] [${clientId}] [${authority}] Creating new PCA that was created in another window...`); - await this._doCreatePublicClientApplication(clientId, authority, newPca); - this._logger.debug(`[_handleSecretStorageChange] [${clientId}] [${authority}] PCA created.`); + this._logger.debug(`[_handleSecretStorageChange] [${clientId}] Creating new PCA that was created in another window...`); + await this._doCreatePublicClientApplication(clientId); + this._logger.debug(`[_handleSecretStorageChange] [${clientId}] PCA created.`); } catch (_e) { // This really shouldn't happen, but should we do something about this? - this._logger.error(`Failed to parse new PublicClientApplication: ${newPca}`); + this._logger.error(`Failed to create new PublicClientApplication: ${clientId}`); continue; } } @@ -204,15 +214,24 @@ export class CachedPublicClientApplicationManager implements ICachedPublicClient } } -class PublicClientApplicationsSecretStorage { +interface IPublicClientApplicationSecretStorage { + get(): Promise; + getOldValue(): Promise<{ clientId: string; authority: string }[] | undefined>; + store(value: string[]): Thenable; + delete(): Thenable; + onDidChange: Event; +} + +class PublicClientApplicationsSecretStorage implements IPublicClientApplicationSecretStorage, Disposable { private _disposable: Disposable; private readonly _onDidChangeEmitter = new EventEmitter; readonly onDidChange: Event = this._onDidChangeEmitter.event; - private readonly _key = `publicClientApplications-${this._cloudName}`; + private readonly _oldKey = `publicClientApplications-${this._cloudName}`; + private readonly _key = `publicClients-${this._cloudName}`; - constructor(private readonly _secretStorage: SecretStorage, private readonly _cloudName: string) { + private constructor(private readonly _secretStorage: SecretStorage, private readonly _cloudName: string) { this._disposable = Disposable.from( this._onDidChangeEmitter, this._secretStorage.onDidChange(e => { @@ -223,6 +242,30 @@ class PublicClientApplicationsSecretStorage { ); } + static async create(secretStorage: SecretStorage, cloudName: string): Promise { + const storage = new PublicClientApplicationsSecretStorage(secretStorage, cloudName); + await storage.initialize(); + return storage; + } + + /** + * Runs the migration. + * TODO: Remove this after a version. + */ + private async initialize() { + const oldValue = await this.getOldValue(); + if (!oldValue) { + return; + } + const newValue = await this.get() ?? []; + for (const { clientId } of oldValue) { + if (!newValue.includes(clientId)) { + newValue.push(clientId); + } + } + await this.store(newValue); + } + async get(): Promise { const value = await this._secretStorage.get(this._key); if (!value) { @@ -231,6 +274,25 @@ class PublicClientApplicationsSecretStorage { return JSON.parse(value); } + /** + * Old representation of data that included the authority. This should be removed in a version or 2. + * @returns An array of objects with clientId and authority + */ + async getOldValue(): Promise<{ clientId: string; authority: string }[] | undefined> { + const value = await this._secretStorage.get(this._oldKey); + if (!value) { + return undefined; + } + const result: { clientId: string; authority: string }[] = []; + for (const stringifiedObj of JSON.parse(value)) { + const obj = JSON.parse(stringifiedObj); + if (obj.clientId && obj.authority) { + result.push(obj); + } + } + return result; + } + store(value: string[]): Thenable { return this._secretStorage.store(this._key, JSON.stringify(value)); } diff --git a/extensions/notebook-renderers/package-lock.json b/extensions/notebook-renderers/package-lock.json index 8dbc5f5ad4c2..7f7e0270ed27 100644 --- a/extensions/notebook-renderers/package-lock.json +++ b/extensions/notebook-renderers/package-lock.json @@ -111,6 +111,20 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -200,6 +214,21 @@ "node": ">=12" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/entities": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", @@ -212,6 +241,55 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escodegen": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", @@ -272,19 +350,126 @@ "dev": true }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -400,6 +585,16 @@ "node": ">= 0.8.0" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", diff --git a/extensions/notebook-renderers/src/ansi.ts b/extensions/notebook-renderers/src/ansi.ts index ee26d37d1f6d..90abdb73b5f1 100644 --- a/extensions/notebook-renderers/src/ansi.ts +++ b/extensions/notebook-renderers/src/ansi.ts @@ -59,7 +59,7 @@ export function handleANSIOutput(text: string, linkOptions: LinkOptions): HTMLSp * Certain ranges that are matched here do not contain real graphics rendition sequences. For * the sake of having a simpler expression, they have been included anyway. */ - if (ansiSequence.match(/^(?:[34][0-8]|9[0-7]|10[0-7]|[0-9]|2[1-5,7-9]|[34]9|5[8,9]|1[0-9])(?:;[349][0-7]|10[0-7]|[013]|[245]|[34]9)?(?:;[012]?[0-9]?[0-9])*;?m$/)) { + if (ansiSequence.match(/^(?:[34][0-8]|9[0-7]|10[0-7]|[0-9]|2[1-5,7-9]|[34]9|5[8,9]|1[0-9])(?:;[349][0-7]|10[0-7]|[013]|[245]|[34]9)?(?:;[0-9]{1,3})*;?m$/)) { const styleCodes: number[] = ansiSequence.slice(0, -1) // Remove final 'm' character. .split(';') // Separate style codes. diff --git a/extensions/npm/.vscode/launch.json b/extensions/npm/.vscode/launch.json index 017c87624153..b5cc96144bc8 100644 --- a/extensions/npm/.vscode/launch.json +++ b/extensions/npm/.vscode/launch.json @@ -9,10 +9,7 @@ "args": [ "--extensionDevelopmentPath=${workspaceFolder}" ], - "stopOnEntry": false, "sourceMaps": true, - "outFiles": ["${workspaceFolder}/client/out/**/*.js"], - "preLaunchTask": "npm" } ] -} \ No newline at end of file +} diff --git a/extensions/npm/README.md b/extensions/npm/README.md index 215ca927ff43..d5538706019b 100644 --- a/extensions/npm/README.md +++ b/extensions/npm/README.md @@ -34,7 +34,8 @@ The extension fetches data from and treeDataProvider = registerExplorer(context); context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e) => { - if (e.affectsConfiguration('npm.exclude') || e.affectsConfiguration('npm.autoDetect') || e.affectsConfiguration('npm.scriptExplorerExclude')) { + if (e.affectsConfiguration('npm.exclude') || e.affectsConfiguration('npm.autoDetect') || e.affectsConfiguration('npm.scriptExplorerExclude') || e.affectsConfiguration('npm.runSilent') || e.affectsConfiguration('npm.packageManager') || e.affectsConfiguration('npm.scriptRunner')) { invalidateTasksCache(); if (treeDataProvider) { treeDataProvider.refresh(); @@ -63,9 +63,15 @@ export async function activate(context: vscode.ExtensionContext): Promise context.subscriptions.push(vscode.commands.registerCommand('npm.refresh', () => { invalidateScriptCaches(); })); + context.subscriptions.push(vscode.commands.registerCommand('npm.scriptRunner', (args) => { + if (args instanceof vscode.Uri) { + return getScriptRunner(args, context, true); + } + return ''; + })); context.subscriptions.push(vscode.commands.registerCommand('npm.packageManager', (args) => { if (args instanceof vscode.Uri) { - return getPackageManager(context, args); + return getPackageManager(args, context, true); } return ''; })); diff --git a/extensions/npm/src/npmScriptLens.ts b/extensions/npm/src/npmScriptLens.ts index c8e506904f88..84dfeca86aa0 100644 --- a/extensions/npm/src/npmScriptLens.ts +++ b/extensions/npm/src/npmScriptLens.ts @@ -15,8 +15,8 @@ import { workspace, l10n } from 'vscode'; -import { findPreferredPM } from './preferred-pm'; import { readScripts } from './readScripts'; +import { getRunScriptCommand } from './tasks'; const enum Constants { @@ -87,18 +87,20 @@ export class NpmScriptLensProvider implements CodeLensProvider, Disposable { } if (this.lensLocation === 'all') { - const packageManager = await findPreferredPM(Uri.joinPath(document.uri, '..').fsPath); - return tokens.scripts.map( - ({ name, nameRange }) => - new CodeLens( + const folder = Uri.joinPath(document.uri, '..'); + return Promise.all(tokens.scripts.map( + async ({ name, nameRange }) => { + const runScriptCommand = await getRunScriptCommand(name, folder); + return new CodeLens( nameRange, { title, command: 'extension.js-debug.createDebuggerTerminal', - arguments: [`${packageManager.name} run ${name}`, workspace.getWorkspaceFolder(document.uri), { cwd }], + arguments: [runScriptCommand.join(' '), workspace.getWorkspaceFolder(document.uri), { cwd }], }, - ), - ); + ); + }, + )); } return []; diff --git a/extensions/npm/src/npmView.ts b/extensions/npm/src/npmView.ts index e041b43f0919..027d7f60e548 100644 --- a/extensions/npm/src/npmView.ts +++ b/extensions/npm/src/npmView.ts @@ -13,9 +13,10 @@ import { } from 'vscode'; import { readScripts } from './readScripts'; import { - createTask, getPackageManager, getTaskName, isAutoDetectionEnabled, isWorkspaceFolder, INpmTaskDefinition, + createInstallationTask, getTaskName, isAutoDetectionEnabled, isWorkspaceFolder, INpmTaskDefinition, NpmTaskProvider, startDebugging, + detectPackageManager, ITaskWithLocation, INSTALL_SCRIPT } from './tasks'; @@ -150,8 +151,8 @@ export class NpmScriptsTreeDataProvider implements TreeDataProvider { } private async runScript(script: NpmScript) { - // Call getPackageManager to trigger the multiple lock files warning. - await getPackageManager(this.context, script.getFolder().uri); + // Call detectPackageManager to trigger the multiple lock files warning. + await detectPackageManager(script.getFolder().uri, this.context, true); tasks.executeTask(script.task); } @@ -181,7 +182,7 @@ export class NpmScriptsTreeDataProvider implements TreeDataProvider { if (!uri) { return; } - const task = await createTask(await getPackageManager(this.context, selection.folder.workspaceFolder.uri, true), 'install', ['install'], selection.folder.workspaceFolder, uri, undefined, []); + const task = await createInstallationTask(this.context, selection.folder.workspaceFolder, uri); tasks.executeTask(task); } diff --git a/extensions/npm/src/scriptHover.ts b/extensions/npm/src/scriptHover.ts index b3a87e051982..33f2346e8158 100644 --- a/extensions/npm/src/scriptHover.ts +++ b/extensions/npm/src/scriptHover.ts @@ -12,8 +12,8 @@ import { } from 'vscode'; import { INpmScriptInfo, readScripts } from './readScripts'; import { - createTask, - getPackageManager, startDebugging + createScriptRunnerTask, + startDebugging } from './tasks'; @@ -114,7 +114,7 @@ export class NpmScriptHoverProvider implements HoverProvider { const documentUri = args.documentUri; const folder = workspace.getWorkspaceFolder(documentUri); if (folder) { - const task = await createTask(await getPackageManager(this.context, folder.uri), script, ['run', script], folder, documentUri); + const task = await createScriptRunnerTask(this.context, script, folder, documentUri); await tasks.executeTask(task); } } diff --git a/extensions/npm/src/tasks.ts b/extensions/npm/src/tasks.ts index 6f1a1fbe649c..19a45488c077 100644 --- a/extensions/npm/src/tasks.ts +++ b/extensions/npm/src/tasks.ts @@ -71,11 +71,16 @@ export class NpmTaskProvider implements TaskProvider { } else { packageJsonUri = _task.scope.uri.with({ path: _task.scope.uri.path + '/package.json' }); } - const cmd = [kind.script]; - if (kind.script !== INSTALL_SCRIPT) { - cmd.unshift('run'); + let task: Task; + if (kind.script === INSTALL_SCRIPT) { + task = await createInstallationTask(this.context, _task.scope, packageJsonUri); + } else { + task = await createScriptRunnerTask(this.context, kind.script, _task.scope, packageJsonUri); } - return createTask(await getPackageManager(this.context, _task.scope.uri), kind, cmd, _task.scope, packageJsonUri); + // VSCode requires that task.definition must not change between resolutions + // We need to restore task.definition to its original value + task.definition = kind; + return task; } return undefined; } @@ -104,49 +109,60 @@ function isTestTask(name: string): boolean { } return false; } +const preScripts: Set = new Set([ + 'install', 'pack', 'pack', 'publish', 'restart', 'shrinkwrap', + 'stop', 'test', 'uninstall', 'version' +]); + +const postScripts: Set = new Set([ + 'install', 'pack', 'pack', 'publish', 'publishOnly', 'restart', 'shrinkwrap', + 'stop', 'test', 'uninstall', 'version' +]); + +function canHavePrePostScript(name: string): boolean { + return preScripts.has(name) || postScripts.has(name); +} -function isPrePostScript(name: string): boolean { - const prePostScripts: Set = new Set([ - 'preuninstall', 'postuninstall', 'prepack', 'postpack', 'preinstall', 'postinstall', - 'prepack', 'postpack', 'prepublish', 'postpublish', 'preversion', 'postversion', - 'prestop', 'poststop', 'prerestart', 'postrestart', 'preshrinkwrap', 'postshrinkwrap', - 'pretest', 'postest', 'prepublishOnly' - ]); +export function isWorkspaceFolder(value: any): value is WorkspaceFolder { + return value && typeof value !== 'number'; +} - const prepost = ['pre' + name, 'post' + name]; - for (const knownScript of prePostScripts) { - if (knownScript === prepost[0] || knownScript === prepost[1]) { - return true; - } +export async function getScriptRunner(folder: Uri, context?: ExtensionContext, showWarning?: boolean): Promise { + let scriptRunner = workspace.getConfiguration('npm', folder).get('scriptRunner', 'npm'); + + if (scriptRunner === 'auto') { + scriptRunner = await detectPackageManager(folder, context, showWarning); } - return false; + + return scriptRunner; } -export function isWorkspaceFolder(value: any): value is WorkspaceFolder { - return value && typeof value !== 'number'; +export async function getPackageManager(folder: Uri, context?: ExtensionContext, showWarning?: boolean): Promise { + let packageManager = workspace.getConfiguration('npm', folder).get('packageManager', 'npm'); + + if (packageManager === 'auto') { + packageManager = await detectPackageManager(folder, context, showWarning); + } + + return packageManager; } -export async function getPackageManager(extensionContext: ExtensionContext, folder: Uri, showWarning: boolean = true): Promise { - let packageManagerName = workspace.getConfiguration('npm', folder).get('packageManager', 'npm'); - - if (packageManagerName === 'auto') { - const { name, multipleLockFilesDetected: multiplePMDetected } = await findPreferredPM(folder.fsPath); - packageManagerName = name; - const neverShowWarning = 'npm.multiplePMWarning.neverShow'; - if (showWarning && multiplePMDetected && !extensionContext.globalState.get(neverShowWarning)) { - const multiplePMWarning = l10n.t('Using {0} as the preferred package manager. Found multiple lockfiles for {1}. To resolve this issue, delete the lockfiles that don\'t match your preferred package manager or change the setting "npm.packageManager" to a value other than "auto".', packageManagerName, folder.fsPath); - const neverShowAgain = l10n.t("Do not show again"); - const learnMore = l10n.t("Learn more"); - window.showInformationMessage(multiplePMWarning, learnMore, neverShowAgain).then(result => { - switch (result) { - case neverShowAgain: extensionContext.globalState.update(neverShowWarning, true); break; - case learnMore: env.openExternal(Uri.parse('https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json')); - } - }); - } +export async function detectPackageManager(folder: Uri, extensionContext?: ExtensionContext, showWarning: boolean = false): Promise { + const { name, multipleLockFilesDetected: multiplePMDetected } = await findPreferredPM(folder.fsPath); + const neverShowWarning = 'npm.multiplePMWarning.neverShow'; + if (showWarning && multiplePMDetected && extensionContext && !extensionContext.globalState.get(neverShowWarning)) { + const multiplePMWarning = l10n.t('Using {0} as the preferred package manager. Found multiple lockfiles for {1}. To resolve this issue, delete the lockfiles that don\'t match your preferred package manager or change the setting "npm.packageManager" to a value other than "auto".', name, folder.fsPath); + const neverShowAgain = l10n.t("Do not show again"); + const learnMore = l10n.t("Learn more"); + window.showInformationMessage(multiplePMWarning, learnMore, neverShowAgain).then(result => { + switch (result) { + case neverShowAgain: extensionContext.globalState.update(neverShowWarning, true); break; + case learnMore: env.openExternal(Uri.parse('https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json')); + } + }); } - return packageManagerName; + return name; } export async function hasNpmScripts(): Promise { @@ -154,49 +170,37 @@ export async function hasNpmScripts(): Promise { if (!folders) { return false; } - try { - for (const folder of folders) { - if (isAutoDetectionEnabled(folder) && !excludeRegex.test(Utils.basename(folder.uri))) { - const relativePattern = new RelativePattern(folder, '**/package.json'); - const paths = await workspace.findFiles(relativePattern, '**/node_modules/**'); - if (paths.length > 0) { - return true; - } + for (const folder of folders) { + if (isAutoDetectionEnabled(folder) && !excludeRegex.test(Utils.basename(folder.uri))) { + const relativePattern = new RelativePattern(folder, '**/package.json'); + const paths = await workspace.findFiles(relativePattern, '**/node_modules/**'); + if (paths.length > 0) { + return true; } } - return false; - } catch (error) { - return Promise.reject(error); } + return false; } -async function detectNpmScripts(context: ExtensionContext, showWarning: boolean): Promise { +async function* findNpmPackages(): AsyncGenerator { - const emptyTasks: ITaskWithLocation[] = []; - const allTasks: ITaskWithLocation[] = []; const visitedPackageJsonFiles: Set = new Set(); const folders = workspace.workspaceFolders; if (!folders) { - return emptyTasks; + return; } - try { - for (const folder of folders) { - if (isAutoDetectionEnabled(folder) && !excludeRegex.test(Utils.basename(folder.uri))) { - const relativePattern = new RelativePattern(folder, '**/package.json'); - const paths = await workspace.findFiles(relativePattern, '**/{node_modules,.vscode-test}/**'); - for (const path of paths) { - if (!isExcluded(folder, path) && !visitedPackageJsonFiles.has(path.fsPath)) { - const tasks = await provideNpmScriptsForFolder(context, path, showWarning); - visitedPackageJsonFiles.add(path.fsPath); - allTasks.push(...tasks); - } + for (const folder of folders) { + if (isAutoDetectionEnabled(folder) && !excludeRegex.test(Utils.basename(folder.uri))) { + const relativePattern = new RelativePattern(folder, '**/package.json'); + const paths = await workspace.findFiles(relativePattern, '**/{node_modules,.vscode-test}/**'); + for (const path of paths) { + if (!isExcluded(folder, path) && !visitedPackageJsonFiles.has(path.fsPath)) { + yield path; + visitedPackageJsonFiles.add(path.fsPath); } } } - return allTasks; - } catch (error) { - return Promise.reject(error); } } @@ -205,30 +209,31 @@ export async function detectNpmScriptsForFolder(context: ExtensionContext, folde const folderTasks: IFolderTaskItem[] = []; - try { - if (excludeRegex.test(Utils.basename(folder))) { - return folderTasks; - } - const relativePattern = new RelativePattern(folder.fsPath, '**/package.json'); - const paths = await workspace.findFiles(relativePattern, '**/node_modules/**'); - - const visitedPackageJsonFiles: Set = new Set(); - for (const path of paths) { - if (!visitedPackageJsonFiles.has(path.fsPath)) { - const tasks = await provideNpmScriptsForFolder(context, path, true); - visitedPackageJsonFiles.add(path.fsPath); - folderTasks.push(...tasks.map(t => ({ label: t.task.name, task: t.task }))); - } - } + if (excludeRegex.test(Utils.basename(folder))) { return folderTasks; - } catch (error) { - return Promise.reject(error); } + const relativePattern = new RelativePattern(folder.fsPath, '**/package.json'); + const paths = await workspace.findFiles(relativePattern, '**/node_modules/**'); + + const visitedPackageJsonFiles: Set = new Set(); + for (const path of paths) { + if (!visitedPackageJsonFiles.has(path.fsPath)) { + const tasks = await provideNpmScriptsForFolder(context, path, true); + visitedPackageJsonFiles.add(path.fsPath); + folderTasks.push(...tasks.map(t => ({ label: t.task.name, task: t.task }))); + } + } + return folderTasks; } export async function provideNpmScripts(context: ExtensionContext, showWarning: boolean): Promise { if (!cachedTasks) { - cachedTasks = await detectNpmScripts(context, showWarning); + const allTasks: ITaskWithLocation[] = []; + for await (const path of findNpmPackages()) { + const tasks = await provideNpmScriptsForFolder(context, path, showWarning); + allTasks.push(...tasks); + } + cachedTasks = allTasks; } return cachedTasks; } @@ -278,15 +283,13 @@ async function provideNpmScriptsForFolder(context: ExtensionContext, packageJson const result: ITaskWithLocation[] = []; - const packageManager = await getPackageManager(context, folder.uri, showWarning); - for (const { name, value, nameRange } of scripts.scripts) { - const task = await createTask(packageManager, name, ['run', name], folder!, packageJsonUri, value, undefined); + const task = await createScriptRunnerTask(context, name, folder!, packageJsonUri, value, showWarning); result.push({ task, location: new Location(packageJsonUri, nameRange) }); } if (!workspace.getConfiguration('npm', folder).get('scriptExplorerExclude', []).find(e => e.includes(INSTALL_SCRIPT))) { - result.push({ task: await createTask(packageManager, INSTALL_SCRIPT, [INSTALL_SCRIPT], folder, packageJsonUri, 'install dependencies from package', []) }); + result.push({ task: await createInstallationTask(context, folder, packageJsonUri, 'install dependencies from package', showWarning) }); } return result; } @@ -298,50 +301,56 @@ export function getTaskName(script: string, relativePath: string | undefined) { return script; } -export async function createTask(packageManager: string, script: INpmTaskDefinition | string, cmd: string[], folder: WorkspaceFolder, packageJsonUri: Uri, scriptValue?: string, matcher?: any): Promise { - let kind: INpmTaskDefinition; - if (typeof script === 'string') { - kind = { type: 'npm', script: script }; - } else { - kind = script; - } - - function getCommandLine(cmd: string[]): (string | ShellQuotedString)[] { - const result: (string | ShellQuotedString)[] = new Array(cmd.length); - for (let i = 0; i < cmd.length; i++) { - if (/\s/.test(cmd[i])) { - result[i] = { value: cmd[i], quoting: cmd[i].includes('--') ? ShellQuoting.Weak : ShellQuoting.Strong }; - } else { - result[i] = cmd[i]; - } +function escapeCommandLine(cmd: string[]): (string | ShellQuotedString)[] { + return cmd.map(arg => { + if (/\s/.test(arg)) { + return { value: arg, quoting: arg.includes('--') ? ShellQuoting.Weak : ShellQuoting.Strong }; + } else { + return arg; } - if (workspace.getConfiguration('npm', folder.uri).get('runSilent')) { - result.unshift('--silent'); + }); +} + +function getRelativePath(rootUri: Uri, packageJsonUri: Uri): string { + const absolutePath = packageJsonUri.path.substring(0, packageJsonUri.path.length - 'package.json'.length); + return absolutePath.substring(rootUri.path.length + 1); +} + +export async function getRunScriptCommand(script: string, folder: Uri, context?: ExtensionContext, showWarning = true): Promise { + const scriptRunner = await getScriptRunner(folder, context, showWarning); + + if (scriptRunner === 'node') { + return ['node', '--run', script]; + } else { + const result = [scriptRunner, 'run']; + if (workspace.getConfiguration('npm', folder).get('runSilent')) { + result.push('--silent'); } + result.push(script); return result; } +} - function getRelativePath(packageJsonUri: Uri): string { - const rootUri = folder.uri; - const absolutePath = packageJsonUri.path.substring(0, packageJsonUri.path.length - 'package.json'.length); - return absolutePath.substring(rootUri.path.length + 1); - } +export async function createScriptRunnerTask(context: ExtensionContext, script: string, folder: WorkspaceFolder, packageJsonUri: Uri, scriptValue?: string, showWarning?: boolean): Promise { + const kind: INpmTaskDefinition = { type: 'npm', script }; - const relativePackageJson = getRelativePath(packageJsonUri); + const relativePackageJson = getRelativePath(folder.uri, packageJsonUri); if (relativePackageJson.length && !kind.path) { kind.path = relativePackageJson.substring(0, relativePackageJson.length - 1); } - const taskName = getTaskName(kind.script, relativePackageJson); + const taskName = getTaskName(script, relativePackageJson); const cwd = path.dirname(packageJsonUri.fsPath); - const task = new Task(kind, folder, taskName, 'npm', new ShellExecution(packageManager, getCommandLine(cmd), { cwd: cwd }), matcher); + const args = await getRunScriptCommand(script, folder.uri, context, showWarning); + const scriptRunner = args.shift()!; + const task = new Task(kind, folder, taskName, 'npm', new ShellExecution(scriptRunner, escapeCommandLine(args), { cwd: cwd })); task.detail = scriptValue; - const lowerCaseTaskName = kind.script.toLowerCase(); + const lowerCaseTaskName = script.toLowerCase(); if (isBuildTask(lowerCaseTaskName)) { task.group = TaskGroup.Build; } else if (isTestTask(lowerCaseTaskName)) { task.group = TaskGroup.Test; - } else if (isPrePostScript(lowerCaseTaskName)) { + } else if (canHavePrePostScript(lowerCaseTaskName)) { task.group = TaskGroup.Clean; // hack: use Clean group to tag pre/post scripts } else if (scriptValue && isDebugScript(scriptValue)) { // todo@connor4312: all scripts are now debuggable, what is a 'debug script'? @@ -350,6 +359,33 @@ export async function createTask(packageManager: string, script: INpmTaskDefinit return task; } +async function getInstallDependenciesCommand(folder: Uri, context?: ExtensionContext, showWarning = true): Promise { + const packageManager = await getPackageManager(folder, context, showWarning); + const result = [packageManager, INSTALL_SCRIPT]; + if (workspace.getConfiguration('npm', folder).get('runSilent')) { + result.push('--silent'); + } + return result; +} + +export async function createInstallationTask(context: ExtensionContext, folder: WorkspaceFolder, packageJsonUri: Uri, scriptValue?: string, showWarning?: boolean): Promise { + const kind: INpmTaskDefinition = { type: 'npm', script: INSTALL_SCRIPT }; + + const relativePackageJson = getRelativePath(folder.uri, packageJsonUri); + if (relativePackageJson.length && !kind.path) { + kind.path = relativePackageJson.substring(0, relativePackageJson.length - 1); + } + const taskName = getTaskName(INSTALL_SCRIPT, relativePackageJson); + const cwd = path.dirname(packageJsonUri.fsPath); + const args = await getInstallDependenciesCommand(folder.uri, context, showWarning); + const packageManager = args.shift()!; + const task = new Task(kind, folder, taskName, 'npm', new ShellExecution(packageManager, escapeCommandLine(args), { cwd: cwd })); + task.detail = scriptValue; + task.group = TaskGroup.Clean; + + return task; +} + export function getPackageJsonUriFromTask(task: Task): Uri | null { if (isWorkspaceFolder(task.scope)) { @@ -403,15 +439,17 @@ export async function runScript(context: ExtensionContext, script: string, docum const uri = document.uri; const folder = workspace.getWorkspaceFolder(uri); if (folder) { - const task = await createTask(await getPackageManager(context, folder.uri), script, ['run', script], folder, uri); + const task = await createScriptRunnerTask(context, script, folder, uri); tasks.executeTask(task); } } export async function startDebugging(context: ExtensionContext, scriptName: string, cwd: string, folder: WorkspaceFolder) { + const runScriptCommand = await getRunScriptCommand(scriptName, folder.uri, context, true); + commands.executeCommand( 'extension.js-debug.createDebuggerTerminal', - `${await getPackageManager(context, folder.uri)} run ${scriptName}`, + runScriptCommand.join(' '), folder, { cwd }, ); diff --git a/extensions/package-lock.json b/extensions/package-lock.json index 500d78417624..e3e87e1f52d3 100644 --- a/extensions/package-lock.json +++ b/extensions/package-lock.json @@ -10,22 +10,23 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "typescript": "^5.7.3" + "typescript": "^5.8.2" }, "devDependencies": { "@parcel/watcher": "2.5.1", - "esbuild": "0.23.0", + "esbuild": "0.25.0", "vscode-grammar-updater": "^1.1.0" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", + "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" @@ -35,13 +36,14 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -51,13 +53,14 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -67,13 +70,14 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -83,13 +87,14 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -99,13 +104,14 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -115,13 +121,14 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -131,13 +138,14 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -147,13 +155,14 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -163,13 +172,14 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -179,13 +189,14 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -195,13 +206,14 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -211,13 +223,14 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -227,13 +240,14 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -243,13 +257,14 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -259,13 +274,14 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -275,13 +291,14 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -290,14 +307,32 @@ "node": ">=18" } }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", + "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -307,13 +342,14 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", + "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -323,13 +359,14 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -339,13 +376,14 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -355,13 +393,14 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -371,13 +410,14 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -387,13 +427,14 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -762,11 +803,12 @@ } }, "node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -774,30 +816,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" } }, "node_modules/fast-plist": { @@ -897,9 +940,9 @@ } }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/extensions/package.json b/extensions/package.json index f756f6a42f91..d24575b17f50 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -4,14 +4,14 @@ "license": "MIT", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "^5.7.3" + "typescript": "^5.8.2" }, "scripts": { "postinstall": "node ./postinstall.mjs" }, "devDependencies": { "@parcel/watcher": "2.5.1", - "esbuild": "0.23.0", + "esbuild": "0.25.0", "vscode-grammar-updater": "^1.1.0" }, "overrides": { diff --git a/extensions/python/package.json b/extensions/python/package.json index a1cae47db17e..9ffffb90e067 100644 --- a/extensions/python/package.json +++ b/extensions/python/package.json @@ -50,7 +50,7 @@ "configurationDefaults": { "[python]": { "diffEditor.ignoreTrimWhitespace": false, - "editor.defaultColorDecorators": false + "editor.defaultColorDecorators": "never" } } }, diff --git a/extensions/ruby/cgmanifest.json b/extensions/ruby/cgmanifest.json index 49719a8afe98..f54ddba7ce79 100644 --- a/extensions/ruby/cgmanifest.json +++ b/extensions/ruby/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "Shopify/ruby-lsp", "repositoryUrl": "https://github.com/Shopify/ruby-lsp", - "commitHash": "01a8ecf608b7d8607adcd89c32db72ae3852f33b" + "commitHash": "958bb1aa0c7aa4b6119c947b69afa7f12b19dceb" } }, "licenseDetail": [ diff --git a/extensions/ruby/package.json b/extensions/ruby/package.json index 8dc105b3481b..355e0cd58a9c 100644 --- a/extensions/ruby/package.json +++ b/extensions/ruby/package.json @@ -69,7 +69,7 @@ ], "configurationDefaults": { "[ruby]": { - "editor.defaultColorDecorators": false + "editor.defaultColorDecorators": "never" } } }, diff --git a/extensions/ruby/syntaxes/ruby.tmLanguage.json b/extensions/ruby/syntaxes/ruby.tmLanguage.json index 84fb37228e64..785b0e4a9287 100644 --- a/extensions/ruby/syntaxes/ruby.tmLanguage.json +++ b/extensions/ruby/syntaxes/ruby.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Shopify/ruby-lsp/commit/01a8ecf608b7d8607adcd89c32db72ae3852f33b", + "version": "https://github.com/Shopify/ruby-lsp/commit/958bb1aa0c7aa4b6119c947b69afa7f12b19dceb", "name": "Ruby", "scopeName": "source.ruby", "patterns": [ @@ -30,7 +30,7 @@ } }, "comment": "class Namespace::ClassName < OtherNamespace::OtherClassName", - "match": "\b(class)\\s+(([a-zA-Z0-9_]+)((::)[a-zA-Z0-9_]+)*)\\s*((<)\\s*(([a-zA-Z0-9_]+)((::)[a-zA-Z0-9_]+)*))?", + "match": "\\b(class)\\s+(([a-zA-Z0-9_]+)((::)[a-zA-Z0-9_]+)*)\\s*((<)\\s*(([a-zA-Z0-9_]+)((::)[a-zA-Z0-9_]+)*))?", "name": "meta.class.ruby" }, { @@ -45,7 +45,7 @@ "name": "punctuation.separator.namespace.ruby" } }, - "match": "\b(module)\\s+(([a-zA-Z0-9_]+)((::)[a-zA-Z0-9_]+)*)", + "match": "\\b(module)\\s+(([a-zA-Z0-9_]+)((::)[a-zA-Z0-9_]+)*)", "name": "meta.module.ruby" }, { @@ -57,7 +57,7 @@ "name": "punctuation.separator.inheritance.ruby" } }, - "match": "\b(class)\\s*(<<)\\s*", + "match": "\\b(class)\\s*(<<)\\s*", "name": "meta.class.ruby" }, { @@ -125,7 +125,7 @@ "name": "variable.ruby" } }, - "match": "^\\s*([a-z]([A-Za-z0-9_])*)\\s*=[^=>]", + "match": "^\\s*([a-z]([A-Za-z0-9_])*)\\s*(?==[^=>])", "comment": "A local variable assignment" }, { @@ -2211,7 +2211,7 @@ ] }, { - "begin": "(?<={|{\\s|[^A-Za-z0-9_:@$]do|^do|[^A-Za-z0-9_:@$]do\\s|^do\\s)(\\|)", + "begin": "(?<={|{\\s+|[^A-Za-z0-9_:@$]do|^do|[^A-Za-z0-9_:@$]do\\s+|^do\\s+)(\\|)", "name": "meta.block.parameters.ruby", "captures": { "1": { @@ -2225,16 +2225,13 @@ "end": "(?=,|\\|\\s*)", "patterns": [ { - "match": "\\G([&*]?)([a-zA-Z][\\w_]*)|(_[\\w_]*)", + "match": "\\G((?:&|\\*\\*?)?)([a-zA-Z_][\\w_]*)", "captures": { "1": { "name": "storage.type.variable.ruby" }, "2": { "name": "variable.other.block.ruby" - }, - "3": { - "name": "variable.other.block.unused.ruby variable.other.constant.ruby" } } } diff --git a/extensions/scss/cgmanifest.json b/extensions/scss/cgmanifest.json index 12247769ce22..a67a4f546096 100644 --- a/extensions/scss/cgmanifest.json +++ b/extensions/scss/cgmanifest.json @@ -6,12 +6,12 @@ "git": { "name": "atom/language-sass", "repositoryUrl": "https://github.com/atom/language-sass", - "commitHash": "f52ab12f7f9346cc2568129d8c4419bd3d506b47" + "commitHash": "303bbf0c250fe380b9e57375598cfd916110758b" } }, "license": "MIT", "description": "The file syntaxes/scss.json was derived from the Atom package https://github.com/atom/language-sass which was originally converted from the TextMate bundle https://github.com/alexsancho/SASS.tmbundle.", - "version": "0.62.1" + "version": "0.61.4" } ], "version": 1 diff --git a/extensions/shellscript/package.json b/extensions/shellscript/package.json index 22ee260005e8..ab9be7b29ad1 100644 --- a/extensions/shellscript/package.json +++ b/extensions/shellscript/package.json @@ -95,7 +95,7 @@ "configurationDefaults": { "[shellscript]": { "files.eol": "\n", - "editor.defaultColorDecorators": false + "editor.defaultColorDecorators": "never" } } }, diff --git a/extensions/simple-browser/preview-src/index.ts b/extensions/simple-browser/preview-src/index.ts index 3d804aa60fa4..106146f86579 100644 --- a/extensions/simple-browser/preview-src/index.ts +++ b/extensions/simple-browser/preview-src/index.ts @@ -90,18 +90,23 @@ onceDocumentLoaded(() => { toggleFocusLockIndicatorEnabled(settings.focusLockIndicatorEnabled); function navigateTo(rawUrl: string): void { + let safeUrl: string | null = null; try { const url = new URL(rawUrl); - - // Try to bust the cache for the iframe - // There does not appear to be any way to reliably do this except modifying the url - url.searchParams.append('vscodeBrowserReqId', Date.now().toString()); - - iframe.src = url.toString(); + if (url.protocol === 'http:' || url.protocol === 'https:') { + // Try to bust the cache for the iframe + url.searchParams.append('vscodeBrowserReqId', Date.now().toString()); + safeUrl = url.toString(); + } } catch { - iframe.src = rawUrl; + // On parse error, do not attempt to match with regex; keep safeUrl as null. + } + if (safeUrl) { + iframe.src = safeUrl; + } else { + // Optionally, display an error or set to about:blank + iframe.src = 'about:blank'; } - vscode.setState({ url: rawUrl }); } }); diff --git a/extensions/sql/cgmanifest.json b/extensions/sql/cgmanifest.json index fec241862ef0..4a1455ebd319 100644 --- a/extensions/sql/cgmanifest.json +++ b/extensions/sql/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "microsoft/vscode-mssql", "repositoryUrl": "https://github.com/microsoft/vscode-mssql", - "commitHash": "49eff02f68b6ee73025c6665c672ca1c93385dde" + "commitHash": "d07e0f838eabff968e4387841427d3c3af8aeec6" } }, "license": "MIT", - "version": "1.23.0" + "version": "1.29.0" } ], "version": 1 diff --git a/extensions/sql/syntaxes/sql.tmLanguage.json b/extensions/sql/syntaxes/sql.tmLanguage.json index 9db452210265..4341bc81528f 100644 --- a/extensions/sql/syntaxes/sql.tmLanguage.json +++ b/extensions/sql/syntaxes/sql.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/vscode-mssql/commit/49eff02f68b6ee73025c6665c672ca1c93385dde", + "version": "https://github.com/microsoft/vscode-mssql/commit/d07e0f838eabff968e4387841427d3c3af8aeec6", "name": "SQL", "scopeName": "source.sql", "patterns": [ @@ -372,7 +372,7 @@ "include": "#regexps" }, { - "match": "\\b(?i)(abort|abort_after_wait|absent|absolute|accent_sensitivity|acceptable_cursopt|acp|action|activation|add|address|admin|aes_128|aes_192|aes_256|affinity|after|aggregate|algorithm|all_constraints|all_errormsgs|all_indexes|all_levels|all_results|allow_connections|allow_dup_row|allow_encrypted_value_modifications|allow_page_locks|allow_row_locks|allow_snapshot_isolation|alter|altercolumn|always|anonymous|ansi_defaults|ansi_null_default|ansi_null_dflt_off|ansi_null_dflt_on|ansi_nulls|ansi_padding|ansi_warnings|appdomain|append|application|apply|arithabort|arithignore|array|assembly|asymmetric|asynchronous_commit|at|atan2|atomic|attach|attach_force_rebuild_log|attach_rebuild_log|audit|auth_realm|authentication|auto|auto_cleanup|auto_close|auto_create_statistics|auto_drop|auto_shrink|auto_update_statistics|auto_update_statistics_async|automated_backup_preference|automatic|autopilot|availability|availability_mode|backup|backup_priority|base64|basic|batches|batchsize|before|between|bigint|binary|binding|bit|block|blockers|blocksize|bmk|both|break|broker|broker_instance|bucket_count|buffer|buffercount|bulk_logged|by|call|caller|card|case|catalog|catch|cert|certificate|change_retention|change_tracking|change_tracking_context|changes|char|character|character_set|check_expiration|check_policy|checkconstraints|checkindex|checkpoint|checksum|cleanup_policy|clear|clear_port|close|clustered|codepage|collection|column_encryption_key|column_master_key|columnstore|columnstore_archive|colv_80_to_100|colv_100_to_80|commit_differential_base|committed|compatibility_level|compress_all_row_groups|compression|compression_delay|concat_null_yields_null|concatenate|configuration|connect|connection|containment|continue|continue_after_error|contract|contract_name|control|conversation|conversation_group_id|conversation_handle|copy|copy_only|count_rows|counter|create(\\\\s+or\\\\s+alter)?|credential|cross|cryptographic|cryptographic_provider|cube|cursor|cursor_close_on_commit|cursor_default|data|data_compression|data_flush_interval_seconds|data_mirroring|data_purity|data_source|database|database_name|database_snapshot|datafiletype|date_correlation_optimization|date|datefirst|dateformat|date_format|datetime|datetime2|datetimeoffset|day(s)?|db_chaining|dbid|dbidexec|dbo_only|deadlock_priority|deallocate|dec|decimal|declare|decrypt|decrypt_a|decryption|default_database|default_fulltext_language|default_language|default_logon_domain|default_schema|definition|delay|delayed_durability|delimitedtext|density_vector|dependent|des|description|desired_state|desx|differential|digest|disable|disable_broker|disable_def_cnst_chk|disabled|disk|distinct|distributed|distribution|drop|drop_existing|dts_buffers|dump|durability|dynamic|edition|elements|else|emergency|empty|enable|enable_broker|enabled|encoding|encrypted|encrypted_value|encryption|encryption_type|end|endpoint|endpoint_url|enhancedintegrity|entry|error_broker_conversations|errorfile|estimateonly|event|except|exec|executable|execute|exists|expand|expiredate|expiry_date|explicit|external|external_access|failover|failover_mode|failure_condition_level|fast|fast_forward|fastfirstrow|federated_service_account|fetch|field_terminator|fieldterminator|file|filelistonly|filegroup|filegrowth|filename|filestream|filestream_log|filestream_on|filetable|file_format|filter|first_row|fips_flagger|fire_triggers|first|firstrow|float|flush_interval_seconds|fmtonly|following|for|force|force_failover_allow_data_loss|force_service_allow_data_loss|forced|forceplan|formatfile|format_options|format_type|formsof|forward_only|free_cursors|free_exec_context|fullscan|fulltext|fulltextall|fulltextkey|function|generated|get|geography|geometry|global|go|goto|governor|guid|hadoop|hardening|hash|hashed|header_limit|headeronly|health_check_timeout|hidden|hierarchyid|histogram|histogram_steps|hits_cursors|hits_exec_context|hour(s)?|http|identity|identity_value|if|ifnull|ignore|ignore_constraints|ignore_dup_key|ignore_dup_row|ignore_triggers|image|immediate|implicit_transactions|include|include_null_values|incremental|index|inflectional|init|initiator|insensitive|insert|instead|int|integer|integrated|intersect|intermediate|interval_length_minutes|into|inuse_cursors|inuse_exec_context|io|is|isabout|iso_week|isolation|job_tracker_location|json|keep|keep_nulls|keep_replication|keepdefaults|keepfixed|keepidentity|keepnulls|kerberos|key|key_path|key_source|key_store_provider_name|keyset|kill|kilobytes_per_batch|labelonly|langid|language|last|lastrow|leading|legacy_cardinality_estimation|length|level|lifetime|lineage_80_to_100|lineage_100_to_80|listener_ip|listener_port|load|loadhistory|lob_compaction|local|local_service_name|locate|location|lock_escalation|lock_timeout|lockres|log|login|login_type|loop|manual|mark_in_use_for_removal|masked|master|match|matched|max_queue_readers|max_duration|max_outstanding_io_per_volume|maxdop|maxerrors|maxlength|maxtransfersize|max_plans_per_query|max_storage_size_mb|mediadescription|medianame|mediapassword|memogroup|memory_optimized|merge|message|message_forward_size|message_forwarding|microsecond|millisecond|minute(s)?|mirror_address|misses_cursors|misses_exec_context|mixed|modify|money|month|move|multi_user|must_change|name|namespace|nanosecond|native|native_compilation|nchar|ncharacter|nested_triggers|never|new_account|new_broker|newname|next|no|no_browsetable|no_checksum|no_compression|no_infomsgs|no_triggers|no_truncate|nocount|noexec|noexpand|noformat|noinit|nolock|nonatomic|nonclustered|nondurable|none|norecompute|norecovery|noreset|norewind|noskip|not|notification|nounload|now|nowait|ntext|ntlm|nulls|numeric|numeric_roundabort|nvarchar|object|objid|oem|offline|old_account|online|operation_mode|open|openjson|optimistic|option|orc|out|outer|output|over|override|owner|ownership|pad_index|page|page_checksum|page_verify|pagecount|paglock|param|parameter_sniffing|parameter_type_expansion|parameterization|parquet|parseonly|partial|partition|partner|password|path|pause|percentage|permission_set|persisted|period|physical_only|plan_forcing_mode|policy|pool|population|ports|preceding|precision|predicate|presume_abort|primary|primary_role|print|prior|priority |priority_level|private|proc(edure)?|procedure_name|profile|provider|quarter|query_capture_mode|query_governor_cost_limit|query_optimizer_hotfixes|query_store|queue|quoted_identifier|raiserror|range|raw|rcfile|rc2|rc4|rc4_128|rdbms|read_committed_snapshot|read|read_only|read_write|readcommitted|readcommittedlock|readonly|readpast|readuncommitted|readwrite|real|rebuild|receive|recmodel_70backcomp|recompile|reconfigure|recovery|recursive|recursive_triggers|redo_queue|reject_sample_value|reject_type|reject_value|relative|remote|remote_data_archive|remote_proc_transactions|remote_service_name|remove|removed_cursors|removed_exec_context|reorganize|repeat|repeatable|repeatableread|replace|replica|replicated|replnick_100_to_80|replnickarray_80_to_100|replnickarray_100_to_80|required|required_cursopt|resample|reset|resource|resource_manager_location|respect|restart|restore|restricted_user|resume|retaindays|retention|return|revert|rewind|rewindonly|returns|robust|role|rollup|root|round_robin|route|row|rowdump|rowguidcol|rowlock|row_terminator|rows|rows_per_batch|rowsets_only|rowterminator|rowversion|rsa_1024|rsa_2048|rsa_3072|rsa_4096|rsa_512|safe|safety|sample|save|scalar|schema|schemabinding|scoped|scroll|scroll_locks|sddl|second|secexpr|seconds|secondary|secondary_only|secondary_role|secret|security|securityaudit|selective|self|send|sent|sequence|serde_method|serializable|server|service|service_broker|service_name|service_objective|session_timeout|session|sessions|seterror|setopts|sets|shard_map_manager|shard_map_name|sharded|shared_memory|shortest_path|show_statistics|showplan_all|showplan_text|showplan_xml|showplan_xml_with_recompile|shrinkdb|shutdown|sid|signature|simple|single_blob|single_clob|single_nclob|single_user|singleton|site|size|size_based_cleanup_mode|skip|smalldatetime|smallint|smallmoney|snapshot|snapshot_import|snapshotrestorephase|soap|softnuma|sort_in_tempdb|sorted_data|sorted_data_reorg|spatial|sql|sql_bigint|sql_binary|sql_bit|sql_char|sql_date|sql_decimal|sql_double|sql_float|sql_guid|sql_handle|sql_longvarbinary|sql_longvarchar|sql_numeric|sql_real|sql_smallint|sql_time|sql_timestamp|sql_tinyint|sql_tsi_day|sql_tsi_frac_second|sql_tsi_hour|sql_tsi_minute|sql_tsi_month|sql_tsi_quarter|sql_tsi_second|sql_tsi_week|sql_tsi_year|sql_type_date|sql_type_time|sql_type_timestamp|sql_varbinary|sql_varchar|sql_variant|sql_wchar|sql_wlongvarchar|ssl|ssl_port|standard|standby|start|start_date|started|stat_header|state|statement|static|statistics|statistics_incremental|statistics_norecompute|statistics_only|statman|stats|stats_stream|status|stop|stop_on_error|stopat|stopatmark|stopbeforemark|stoplist|stopped|string_delimiter|subject|supplemental_logging|supported|suspend|symmetric|synchronous_commit|synonym|sysname|system|system_time|system_versioning|table|tableresults|tablock|tablockx|take|tape|target|target_index|target_partition|target_recovery_time|tcp|temporal_history_retention|text|textimage_on|then|thesaurus|throw|time|timeout|timestamp|tinyint|to|top|torn_page_detection|track_columns_updated|trailing|tran|transaction|transfer|transform_noise_words|triple_des|triple_des_3key|truncate|trustworthy|try|tsql|two_digit_year_cutoff|type|type_desc|type_warning|tzoffset|uid|unbounded|uncommitted|unique|uniqueidentifier|unlimited|unload|unlock|unsafe|updlock|url|use|useplan|useroptions|use_type_default|using|utcdatetime|valid_xml|validation|value|values|varbinary|varchar|verbose|verifyonly|version|view_metadata|virtual_device|visiblity|wait_at_low_priority|waitfor|webmethod|week|weekday|weight|well_formed_xml|when|while|widechar|widechar_ansi|widenative|window|windows|with|within|within group|witness|without|without_array_wrapper|workload|wsdl|xact_abort|xlock|xml|xmlschema|xquery|xsinil|year|zone)\\b", + "match": "\\b(?i)(abort|abort_after_wait|absent|absolute|accent_sensitivity|acceptable_cursopt|acp|action|activation|add|address|admin|aes_128|aes_192|aes_256|affinity|after|aggregate|algorithm|all_constraints|all_errormsgs|all_indexes|all_levels|all_results|allow_connections|allow_dup_row|allow_encrypted_value_modifications|allow_page_locks|allow_row_locks|allow_snapshot_isolation|alter|altercolumn|always|anonymous|ansi_defaults|ansi_null_default|ansi_null_dflt_off|ansi_null_dflt_on|ansi_nulls|ansi_padding|ansi_warnings|appdomain|append|application|apply|arithabort|arithignore|array|assembly|asymmetric|asynchronous_commit|at|atan2|atomic|attach|attach_force_rebuild_log|attach_rebuild_log|audit|auth_realm|authentication|auto|auto_cleanup|auto_close|auto_create_statistics|auto_drop|auto_shrink|auto_update_statistics|auto_update_statistics_async|automated_backup_preference|automatic|autopilot|availability|availability_mode|backup|backup_priority|base64|basic|batches|batchsize|before|between|bigint|binary|binding|bit|block|blockers|blocksize|bmk|both|break|broker|broker_instance|bucket_count|buffer|buffercount|bulk_logged|by|call|caller|card|case|catalog|catch|cert|certificate|change_retention|change_tracking|change_tracking_context|changes|char|character|character_set|check_expiration|check_policy|checkconstraints|checkindex|checkpoint|checksum|cleanup_policy|clear|clear_port|close|clustered|codepage|collection|column_encryption_key|column_master_key|columnstore|columnstore_archive|colv_80_to_100|colv_100_to_80|commit_differential_base|committed|compatibility_level|compress_all_row_groups|compression|compression_delay|concat_null_yields_null|concatenate|configuration|connect|connection|containment|continue|continue_after_error|contract|contract_name|control|conversation|conversation_group_id|conversation_handle|copy|copy_only|count_rows|counter|create(\\\\s+or\\\\s+alter)?|credential|cross|cryptographic|cryptographic_provider|cube|cursor|cursor_close_on_commit|cursor_default|data|data_compression|data_flush_interval_seconds|data_mirroring|data_purity|data_source|database|database_name|database_snapshot|datafiletype|date_correlation_optimization|date|datefirst|dateformat|date_format|datetime|datetime2|datetimeoffset|day(s)?|db_chaining|dbid|dbidexec|dbo_only|deadlock_priority|deallocate|dec|decimal|declare|decrypt|decrypt_a|decryption|default_database|default_fulltext_language|default_language|default_logon_domain|default_schema|definition|delay|delayed_durability|delimitedtext|density_vector|dependent|des|description|desired_state|desx|differential|digest|disable|disable_broker|disable_def_cnst_chk|disabled|disk|distinct|distributed|distribution|drop|drop_existing|dts_buffers|dump|durability|dynamic|edition|elements|else|emergency|empty|enable|enable_broker|enabled|encoding|encrypted|encrypted_value|encryption|encryption_type|end|endpoint|endpoint_url|enhancedintegrity|entry|error_broker_conversations|errorfile|estimateonly|event|except|exec|executable|execute|exists|expand|expiredate|expiry_date|explicit|external|external_access|failover|failover_mode|failure_condition_level|fast|fast_forward|fastfirstrow|federated_service_account|fetch|field_terminator|fieldterminator|file|filelistonly|filegroup|filegrowth|filename|filestream|filestream_log|filestream_on|filetable|file_format|filter|first_row|fips_flagger|fire_triggers|first|firstrow|float|flush_interval_seconds|fmtonly|following|for|force|force_failover_allow_data_loss|force_service_allow_data_loss|forced|forceplan|formatfile|format_options|format_type|formsof|forward_only|free_cursors|free_exec_context|fullscan|fulltext|fulltextall|fulltextkey|function|generated|get|geography|geometry|global|go|goto|governor|guid|hadoop|hardening|hash|hashed|header_limit|headeronly|health_check_timeout|hidden|hierarchyid|histogram|histogram_steps|hits_cursors|hits_exec_context|hour(s)?|http|identity|identity_value|if|ifnull|ignore|ignore_constraints|ignore_dup_key|ignore_dup_row|ignore_triggers|image|immediate|implicit_transactions|include|include_null_values|incremental|index|inflectional|init|initiator|insensitive|insert|instead|int|integer|integrated|intersect|intermediate|interval_length_minutes|into|inuse_cursors|inuse_exec_context|io|is|isabout|iso_week|isolation|job_tracker_location|json|keep|keep_nulls|keep_replication|keepdefaults|keepfixed|keepidentity|keepnulls|kerberos|key|key_path|key_source|key_store_provider_name|keyset|kill|kilobytes_per_batch|labelonly|langid|language|last|lastrow|leading|legacy_cardinality_estimation|length|level|lifetime|lineage_80_to_100|lineage_100_to_80|listener_ip|listener_port|load|loadhistory|lob_compaction|local|local_service_name|locate|location|lock_escalation|lock_timeout|lockres|log|login|login_type|loop|manual|mark_in_use_for_removal|masked|master|match|matched|max_queue_readers|max_duration|max_outstanding_io_per_volume|maxdop|maxerrors|maxlength|maxtransfersize|max_plans_per_query|max_storage_size_mb|mediadescription|medianame|mediapassword|memogroup|memory_optimized|merge|message|message_forward_size|message_forwarding|microsecond|millisecond|minute(s)?|mirror_address|misses_cursors|misses_exec_context|mixed|modify|money|month|move|multi_user|must_change|name|namespace|nanosecond|native|native_compilation|nchar|ncharacter|nested_triggers|never|new_account|new_broker|newname|next|no|no_browsetable|no_checksum|no_compression|no_infomsgs|no_triggers|no_truncate|nocount|noexec|noexpand|noformat|noinit|nolock|nonatomic|nonclustered|nondurable|none|norecompute|norecovery|noreset|norewind|noskip|not|notification|nounload|now|nowait|ntext|ntlm|nulls|numeric|numeric_roundabort|nvarchar|object|objid|oem|offline|old_account|online|operation_mode|open|openjson|optimistic|option|orc|out|outer|output|over|override|owner|ownership|pad_index|page|page_checksum|page_verify|pagecount|paglock|param|parameter_sniffing|parameter_type_expansion|parameterization|parquet|parseonly|partial|partition|partner|password|path|pause|percentage|permission_set|persisted|period|physical_only|plan_forcing_mode|policy|pool|population|ports|preceding|precision|predicate|presume_abort|primary|primary_role|print|prior|priority |priority_level|private|proc(edure)?|procedure_name|profile|provider|quarter|query_capture_mode|query_governor_cost_limit|query_optimizer_hotfixes|query_store|queue|quoted_identifier|raiserror|range|raw|rcfile|rc2|rc4|rc4_128|rdbms|read_committed_snapshot|read|read_only|read_write|readcommitted|readcommittedlock|readonly|readpast|readuncommitted|readwrite|real|rebuild|receive|recmodel_70backcomp|recompile|reconfigure|recovery|recursive|recursive_triggers|redo_queue|reject_sample_value|reject_type|reject_value|relative|remote|remote_data_archive|remote_proc_transactions|remote_service_name|remove|removed_cursors|removed_exec_context|reorganize|repeat|repeatable|repeatableread|replace|replica|replicated|replnick_100_to_80|replnickarray_80_to_100|replnickarray_100_to_80|required|required_cursopt|resample|reset|resource|resource_manager_location|respect|restart|restore|restricted_user|resume|retaindays|retention|return|revert|rewind|rewindonly|returns|robust|role|rollup|root|round_robin|route|row|rowdump|rowguidcol|rowlock|row_terminator|rows|rows_per_batch|rowsets_only|rowterminator|rowversion|rsa_1024|rsa_2048|rsa_3072|rsa_4096|rsa_512|safe|safety|sample|save|scalar|schema|schemabinding|scoped|scroll|scroll_locks|sddl|second|secexpr|seconds|secondary|secondary_only|secondary_role|secret|security|securityaudit|selective|self|send|sent|sequence|serde_method|serializable|server|service|service_broker|service_name|service_objective|session_timeout|session|sessions|seterror|setopts|sets|shard_map_manager|shard_map_name|sharded|shared_memory|shortest_path|show_statistics|showplan_all|showplan_text|showplan_xml|showplan_xml_with_recompile|shrinkdb|shutdown|sid|signature|simple|single_blob|single_clob|single_nclob|single_user|singleton|site|size|size_based_cleanup_mode|skip|smalldatetime|smallint|smallmoney|snapshot|snapshot_import|snapshotrestorephase|soap|softnuma|sort_in_tempdb|sorted_data|sorted_data_reorg|spatial|sql|sql_bigint|sql_binary|sql_bit|sql_char|sql_date|sql_decimal|sql_double|sql_float|sql_guid|sql_handle|sql_longvarbinary|sql_longvarchar|sql_numeric|sql_real|sql_smallint|sql_time|sql_timestamp|sql_tinyint|sql_tsi_day|sql_tsi_frac_second|sql_tsi_hour|sql_tsi_minute|sql_tsi_month|sql_tsi_quarter|sql_tsi_second|sql_tsi_week|sql_tsi_year|sql_type_date|sql_type_time|sql_type_timestamp|sql_varbinary|sql_varchar|sql_variant|sql_wchar|sql_wlongvarchar|ssl|ssl_port|standard|standby|start|start_date|started|stat_header|state|statement|static|statistics|statistics_incremental|statistics_norecompute|statistics_only|statman|stats|stats_stream|status|stop|stop_on_error|stopat|stopatmark|stopbeforemark|stoplist|stopped|string_delimiter|subject|supplemental_logging|supported|suspend|symmetric|synchronous_commit|synonym|sysname|system|system_time|system_versioning|table|tableresults|tablock|tablockx|take|tape|target|target_index|target_partition|target_recovery_time|tcp|temporal_history_retention|text|textimage_on|then|thesaurus|throw|time|timeout|timestamp|tinyint|to|top|torn_page_detection|track_columns_updated|trailing|tran|transaction|transfer|transform_noise_words|triple_des|triple_des_3key|truncate|trustworthy|try|tsql|two_digit_year_cutoff|type|type_desc|type_warning|tzoffset|uid|unbounded|uncommitted|unique|uniqueidentifier|unlimited|unload|unlock|unsafe|updlock|url|use|useplan|useroptions|use_type_default|using|utcdatetime|valid_xml|validation|value|values|varbinary|varchar|vector|verbose|verifyonly|version|view_metadata|virtual_device|visiblity|wait_at_low_priority|waitfor|webmethod|week|weekday|weight|well_formed_xml|when|while|widechar|widechar_ansi|widenative|window|windows|with|within|within group|witness|without|without_array_wrapper|workload|wsdl|xact_abort|xlock|xml|xmlschema|xquery|xsinil|year|zone)\\b", "name": "keyword.other.sql" }, { diff --git a/extensions/terminal-suggest/cgmanifest.json b/extensions/terminal-suggest/cgmanifest.json index e0eaafe83ca6..f39b1fae3712 100644 --- a/extensions/terminal-suggest/cgmanifest.json +++ b/extensions/terminal-suggest/cgmanifest.json @@ -14,6 +14,75 @@ "url": "https://github.com/withfig/autocomplete/blob/main/LICENSE.md" }, "description": "IDE-style autocomplete for your existing terminal & shell from withfig/autocomplete." + }, + { + "component": { + "type": "git", + "git": { + "name": "amazon-q-developer-cli", + "repositoryUrl": "https://github.com/aws/amazon-q-developer-cli", + "commitHash": "f66e0b0e917ab185eef528dc36eca56b78ca8b5d" + } + }, + "licenseDetail": [ + "MIT License", + "", + "Copyright (c) 2024 Amazon.com, Inc. or its affiliates.", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and associated documentation files (the \"Software\"), to deal", + "in the Software without restriction, including without limitation the rights", + "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell", + "copies of the Software, and to permit persons to whom the Software is", + "furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in all", + "copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,", + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE", + "SOFTWARE." + ], + "version": "f66e0b0e917ab185eef528dc36eca56b78ca8b5d" + }, + { + "component": { + "type": "git", + "git": { + "name": "@fig/autocomplete-shared", + "repositoryUrl": "https://github.com/withfig/autocomplete-tools", + "commitHash": "104377c19a91ca8a312cb38c115a74468f6227cb" + } + }, + "licenseDetail": [ + "MIT License", + "", + "Copyright (c) 2021 Hercules Labs Inc. (Fig)", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and associated documentation files (the \"Software\"), to deal", + "in the Software without restriction, including without limitation the rights", + "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell", + "copies of the Software, and to permit persons to whom the Software is", + "furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in all", + "copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,", + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE", + "SOFTWARE." + ], + "version": "1.1.2" } - ] + ], + "version": 1 } diff --git a/extensions/terminal-suggest/fixtures/shell-parser/basic/input.sh b/extensions/terminal-suggest/fixtures/shell-parser/basic/input.sh new file mode 100644 index 000000000000..72075545c056 --- /dev/null +++ b/extensions/terminal-suggest/fixtures/shell-parser/basic/input.sh @@ -0,0 +1,29 @@ +### Case 1 +a b\\ c + +### Case 2 +a "b" + +### Case 3 +a 'b' + +### Case 4 +a $'b' + +### Case 5 +a $commit + +### Case 6 +a $$ + +### Case 7 +a $((b)) + +### Case 8 +a $(b) + +### Case 9 +a \`b\` + +### Case 10 +a $(\`b\`) diff --git a/extensions/terminal-suggest/fixtures/shell-parser/basic/output.txt b/extensions/terminal-suggest/fixtures/shell-parser/basic/output.txt new file mode 100644 index 000000000000..8e816c5fe184 --- /dev/null +++ b/extensions/terminal-suggest/fixtures/shell-parser/basic/output.txt @@ -0,0 +1,448 @@ +// Case 1 +{ + "startIndex": 0, + "type": "program", + "endIndex": 7, + "text": "a b\\\\ c", + "innerText": "a b\\\\ c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 7, + "text": "a b\\\\ c", + "innerText": "a b\\\\ c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "word", + "endIndex": 5, + "text": "b\\\\", + "innerText": "b\\", + "complete": true, + "children": [] + }, + { + "startIndex": 6, + "type": "word", + "endIndex": 7, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 2 +{ + "startIndex": 0, + "type": "program", + "endIndex": 5, + "text": "a \"b\"", + "innerText": "a \"b\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 5, + "text": "a \"b\"", + "innerText": "a \"b\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "string", + "endIndex": 5, + "text": "\"b\"", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 3 +{ + "startIndex": 0, + "type": "program", + "endIndex": 5, + "text": "a 'b'", + "innerText": "a 'b'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 5, + "text": "a 'b'", + "innerText": "a 'b'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "raw_string", + "endIndex": 5, + "text": "'b'", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 4 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "a $'b'", + "innerText": "a $'b'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 6, + "text": "a $'b'", + "innerText": "a $'b'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "ansi_c_string", + "endIndex": 6, + "text": "$'b'", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 5 +{ + "startIndex": 0, + "type": "program", + "endIndex": 9, + "text": "a $commit", + "innerText": "a $commit", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 9, + "text": "a $commit", + "innerText": "a $commit", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "simple_expansion", + "endIndex": 9, + "text": "$commit", + "innerText": "$commit", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 6 +{ + "startIndex": 0, + "type": "program", + "endIndex": 4, + "text": "a $$", + "innerText": "a $$", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 4, + "text": "a $$", + "innerText": "a $$", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "special_expansion", + "endIndex": 4, + "text": "$$", + "innerText": "$$", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 7 +{ + "startIndex": 0, + "type": "program", + "endIndex": 8, + "text": "a $((b))", + "innerText": "a $((b))", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 8, + "text": "a $((b))", + "innerText": "a $((b))", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "arithmetic_expansion", + "endIndex": 8, + "text": "$((b))", + "innerText": "$((b))", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 8 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "a $(b)", + "innerText": "a $(b)", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 6, + "text": "a $(b)", + "innerText": "a $(b)", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "command_substitution", + "endIndex": 6, + "text": "$(b)", + "innerText": "$(b)", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "command", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ] + } + ] +} + +// Case 9 +{ + "startIndex": 0, + "type": "program", + "endIndex": 7, + "text": "a \\`b\\`", + "innerText": "a \\`b\\`", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 7, + "text": "a \\`b\\`", + "innerText": "a \\`b\\`", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 3, + "type": "word", + "endIndex": 7, + "text": "`b\\`", + "innerText": "`b`", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 10 +{ + "startIndex": 0, + "type": "program", + "endIndex": 10, + "text": "a $(\\`b\\`)", + "innerText": "a $(\\`b\\`)", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 10, + "text": "a $(\\`b\\`)", + "innerText": "a $(\\`b\\`)", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "command_substitution", + "endIndex": 10, + "text": "$(\\`b\\`)", + "innerText": "$(\\`b\\`)", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "command", + "endIndex": 9, + "text": "\\`b\\`", + "innerText": "\\`b\\`", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 9, + "text": "`b\\`", + "innerText": "`b`", + "complete": true, + "children": [] + } + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/extensions/terminal-suggest/fixtures/shell-parser/multipleStatements/input.sh b/extensions/terminal-suggest/fixtures/shell-parser/multipleStatements/input.sh new file mode 100644 index 000000000000..ba6858ea1a59 --- /dev/null +++ b/extensions/terminal-suggest/fixtures/shell-parser/multipleStatements/input.sh @@ -0,0 +1,47 @@ +### Case 1 +a && b + +### Case 2 +a || b + +### Case 3 +a | b + +### Case 4 +a |& b + +### Case 5 +(a; b) + +### Case 6 +(a; b;) + +### Case 7 +{a; b} + +### Case 8 +{a; b;} + +### Case 9 +a; b + +### Case 10 +a & b + +### Case 11 +a &; b + +### Case 12 +a ; b; + +### Case 13 +a && b || c + +### Case 14 +a && b | c + +### Case 15 +a | b && c + +### Case 16 +(a) | b && c \ No newline at end of file diff --git a/extensions/terminal-suggest/fixtures/shell-parser/multipleStatements/output.txt b/extensions/terminal-suggest/fixtures/shell-parser/multipleStatements/output.txt new file mode 100644 index 000000000000..624f01663718 --- /dev/null +++ b/extensions/terminal-suggest/fixtures/shell-parser/multipleStatements/output.txt @@ -0,0 +1,1035 @@ +// Case 1 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "a && b", + "innerText": "a && b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "list", + "endIndex": 6, + "text": "a && b", + "innerText": "a && b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 2, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 5, + "type": "command", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 2 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "a || b", + "innerText": "a || b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "list", + "endIndex": 6, + "text": "a || b", + "innerText": "a || b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 2, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 5, + "type": "command", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 3 +{ + "startIndex": 0, + "type": "program", + "endIndex": 5, + "text": "a | b", + "innerText": "a | b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "pipeline", + "endIndex": 5, + "text": "a | b", + "innerText": "a | b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 2, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 4, + "type": "command", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 4 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "a |& b", + "innerText": "a |& b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "pipeline", + "endIndex": 6, + "text": "a |& b", + "innerText": "a |& b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 2, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 5, + "type": "command", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 5 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "(a; b)", + "innerText": "(a; b)", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "subshell", + "endIndex": 6, + "text": "(a; b)", + "innerText": "(a; b)", + "complete": true, + "children": [ + { + "startIndex": 1, + "type": "command", + "endIndex": 2, + "text": "a", + "innerText": "a", + "complete": true, + "children": [ + { + "startIndex": 1, + "type": "word", + "endIndex": 2, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 4, + "type": "command", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 6 +{ + "startIndex": 0, + "type": "program", + "endIndex": 7, + "text": "(a; b;)", + "innerText": "(a; b;)", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "subshell", + "endIndex": 7, + "text": "(a; b;)", + "innerText": "(a; b;)", + "complete": true, + "children": [ + { + "startIndex": 1, + "type": "command", + "endIndex": 2, + "text": "a", + "innerText": "a", + "complete": true, + "children": [ + { + "startIndex": 1, + "type": "word", + "endIndex": 2, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 4, + "type": "command", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 7 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "{a; b}", + "innerText": "{a; b}", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "compound_statement", + "endIndex": 6, + "text": "{a; b}", + "innerText": "{a; b}", + "complete": false, + "children": [ + { + "startIndex": 1, + "type": "command", + "endIndex": 2, + "text": "a", + "innerText": "a", + "complete": true, + "children": [ + { + "startIndex": 1, + "type": "word", + "endIndex": 2, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 4, + "type": "command", + "endIndex": 6, + "text": "b}", + "innerText": "b}", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 6, + "text": "b}", + "innerText": "b}", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 8 +{ + "startIndex": 0, + "type": "program", + "endIndex": 7, + "text": "{a; b;}", + "innerText": "{a; b;}", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "compound_statement", + "endIndex": 7, + "text": "{a; b;}", + "innerText": "{a; b;}", + "complete": true, + "children": [ + { + "startIndex": 1, + "type": "command", + "endIndex": 2, + "text": "a", + "innerText": "a", + "complete": true, + "children": [ + { + "startIndex": 1, + "type": "word", + "endIndex": 2, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 4, + "type": "command", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 9 +{ + "startIndex": 0, + "type": "program", + "endIndex": 4, + "text": "a; b", + "innerText": "a; b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 3, + "type": "command", + "endIndex": 4, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 3, + "type": "word", + "endIndex": 4, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 10 +{ + "startIndex": 0, + "type": "program", + "endIndex": 5, + "text": "a & b", + "innerText": "a & b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 2, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 4, + "type": "command", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 11 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "a &; b", + "innerText": "a &; b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 2, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 5, + "type": "command", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 12 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "a ; b;", + "innerText": "a ; b;", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 2, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 4, + "type": "command", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 13 +{ + "startIndex": 0, + "type": "program", + "endIndex": 11, + "text": "a && b || c", + "innerText": "a && b || c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "list", + "endIndex": 11, + "text": "a && b || c", + "innerText": "a && b || c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 2, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 5, + "type": "command", + "endIndex": 7, + "text": "b ", + "innerText": "b ", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 10, + "type": "command", + "endIndex": 11, + "text": "c", + "innerText": "c", + "complete": true, + "children": [ + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 14 +{ + "startIndex": 0, + "type": "program", + "endIndex": 10, + "text": "a && b | c", + "innerText": "a && b | c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "list", + "endIndex": 10, + "text": "a && b | c", + "innerText": "a && b | c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 2, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 5, + "type": "pipeline", + "endIndex": 10, + "text": "b | c", + "innerText": "b | c", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "command", + "endIndex": 7, + "text": "b ", + "innerText": "b ", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 9, + "type": "command", + "endIndex": 10, + "text": "c", + "innerText": "c", + "complete": true, + "children": [ + { + "startIndex": 9, + "type": "word", + "endIndex": 10, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ] + } + ] + } + ] +} + +// Case 15 +{ + "startIndex": 0, + "type": "program", + "endIndex": 10, + "text": "a | b && c", + "innerText": "a | b && c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "list", + "endIndex": 10, + "text": "a | b && c", + "innerText": "a | b && c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "pipeline", + "endIndex": 6, + "text": "a | b ", + "innerText": "a | b ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 2, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 4, + "type": "command", + "endIndex": 6, + "text": "b ", + "innerText": "b ", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + }, + { + "startIndex": 9, + "type": "command", + "endIndex": 10, + "text": "c", + "innerText": "c", + "complete": true, + "children": [ + { + "startIndex": 9, + "type": "word", + "endIndex": 10, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 16 +{ + "startIndex": 0, + "type": "program", + "endIndex": 12, + "text": "(a) | b && c", + "innerText": "(a) | b && c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "list", + "endIndex": 12, + "text": "(a) | b && c", + "innerText": "(a) | b && c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "pipeline", + "endIndex": 8, + "text": "(a) | b ", + "innerText": "(a) | b ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "subshell", + "endIndex": 3, + "text": "(a)", + "innerText": "(a)", + "complete": true, + "children": [ + { + "startIndex": 1, + "type": "command", + "endIndex": 2, + "text": "a", + "innerText": "a", + "complete": true, + "children": [ + { + "startIndex": 1, + "type": "word", + "endIndex": 2, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + } + ] + }, + { + "startIndex": 6, + "type": "command", + "endIndex": 8, + "text": "b ", + "innerText": "b ", + "complete": true, + "children": [ + { + "startIndex": 6, + "type": "word", + "endIndex": 7, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + }, + { + "startIndex": 11, + "type": "command", + "endIndex": 12, + "text": "c", + "innerText": "c", + "complete": true, + "children": [ + { + "startIndex": 11, + "type": "word", + "endIndex": 12, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/extensions/terminal-suggest/fixtures/shell-parser/primaryExpressions/input.sh b/extensions/terminal-suggest/fixtures/shell-parser/primaryExpressions/input.sh new file mode 100644 index 000000000000..d2c5977e3185 --- /dev/null +++ b/extensions/terminal-suggest/fixtures/shell-parser/primaryExpressions/input.sh @@ -0,0 +1,35 @@ +### Case 1 +a "\${b}" + +### Case 2 +a "'b'" + +### Case 3 +a "\${b:+"c"}" + +### Case 4 +a b"c" + +### Case 5 +a '\${b}' + +### Case 6 +a $'\${b}' + +### Case 7 +a $'b''c'd$$$e\${f}"g" + +### Case 8 +a $'b\\'c' + +### Case 9 +a 'b\\'c' + +### Case 10 +a "b$" + +### Case 11 +a "$b" + +### Case 12 +a "$(b "c" && d)" \ No newline at end of file diff --git a/extensions/terminal-suggest/fixtures/shell-parser/primaryExpressions/output.txt b/extensions/terminal-suggest/fixtures/shell-parser/primaryExpressions/output.txt new file mode 100644 index 000000000000..4783411a82b7 --- /dev/null +++ b/extensions/terminal-suggest/fixtures/shell-parser/primaryExpressions/output.txt @@ -0,0 +1,724 @@ +// Case 1 +{ + "startIndex": 0, + "type": "program", + "endIndex": 9, + "text": "a \"\\${b}\"", + "innerText": "a \"\\${b}\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 9, + "text": "a \"\\${b}\"", + "innerText": "a \"\\${b}\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "string", + "endIndex": 9, + "text": "\"\\${b}\"", + "innerText": "${b}", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 2 +{ + "startIndex": 0, + "type": "program", + "endIndex": 7, + "text": "a \"'b'\"", + "innerText": "a \"'b'\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 7, + "text": "a \"'b'\"", + "innerText": "a \"'b'\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "string", + "endIndex": 7, + "text": "\"'b'\"", + "innerText": "'b'", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 3 +{ + "startIndex": 0, + "type": "program", + "endIndex": 14, + "text": "a \"\\${b:+\"c\"}\"", + "innerText": "a \"\\${b:+\"c\"}\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 14, + "text": "a \"\\${b:+\"c\"}\"", + "innerText": "a \"\\${b:+\"c\"}\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "concatenation", + "endIndex": 14, + "text": "\"\\${b:+\"c\"}\"", + "innerText": "${b:+c}", + "complete": true, + "children": [ + { + "startIndex": 2, + "type": "string", + "endIndex": 10, + "text": "\"\\${b:+\"", + "innerText": "${b:+", + "complete": true, + "children": [] + }, + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + }, + { + "startIndex": 11, + "type": "string", + "endIndex": 14, + "text": "\"}\"", + "innerText": "}", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 4 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "a b\"c\"", + "innerText": "a b\"c\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 6, + "text": "a b\"c\"", + "innerText": "a b\"c\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "concatenation", + "endIndex": 6, + "text": "b\"c\"", + "innerText": "bc", + "complete": true, + "children": [ + { + "startIndex": 2, + "type": "word", + "endIndex": 3, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + }, + { + "startIndex": 3, + "type": "string", + "endIndex": 6, + "text": "\"c\"", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 5 +{ + "startIndex": 0, + "type": "program", + "endIndex": 9, + "text": "a '\\${b}'", + "innerText": "a '\\${b}'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 9, + "text": "a '\\${b}'", + "innerText": "a '\\${b}'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "raw_string", + "endIndex": 9, + "text": "'\\${b}'", + "innerText": "\\${b}", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 6 +{ + "startIndex": 0, + "type": "program", + "endIndex": 10, + "text": "a $'\\${b}'", + "innerText": "a $'\\${b}'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 10, + "text": "a $'\\${b}'", + "innerText": "a $'\\${b}'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "ansi_c_string", + "endIndex": 10, + "text": "$'\\${b}'", + "innerText": "\\${b}", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 7 +{ + "startIndex": 0, + "type": "program", + "endIndex": 22, + "text": "a $'b''c'd$$$e\\${f}\"g\"", + "innerText": "a $'b''c'd$$$e\\${f}\"g\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 22, + "text": "a $'b''c'd$$$e\\${f}\"g\"", + "innerText": "a $'b''c'd$$$e\\${f}\"g\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "concatenation", + "endIndex": 22, + "text": "$'b''c'd$$$e\\${f}\"g\"", + "innerText": "bcd$$$e${f}g", + "complete": true, + "children": [ + { + "startIndex": 2, + "type": "ansi_c_string", + "endIndex": 6, + "text": "$'b'", + "innerText": "b", + "complete": true, + "children": [] + }, + { + "startIndex": 6, + "type": "raw_string", + "endIndex": 9, + "text": "'c'", + "innerText": "c", + "complete": true, + "children": [] + }, + { + "startIndex": 9, + "type": "word", + "endIndex": 10, + "text": "d", + "innerText": "d", + "complete": true, + "children": [] + }, + { + "startIndex": 10, + "type": "special_expansion", + "endIndex": 12, + "text": "$$", + "innerText": "$$", + "complete": true, + "children": [] + }, + { + "startIndex": 12, + "type": "simple_expansion", + "endIndex": 14, + "text": "$e", + "innerText": "$e", + "complete": true, + "children": [] + }, + { + "startIndex": 15, + "type": "word", + "endIndex": 19, + "text": "${f}", + "innerText": "${f}", + "complete": true, + "children": [] + }, + { + "startIndex": 19, + "type": "string", + "endIndex": 22, + "text": "\"g\"", + "innerText": "g", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 8 +{ + "startIndex": 0, + "type": "program", + "endIndex": 10, + "text": "a $'b\\\\'c'", + "innerText": "a $'b\\\\'c'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 10, + "text": "a $'b\\\\'c'", + "innerText": "a $'b\\\\'c'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "concatenation", + "endIndex": 10, + "text": "$'b\\\\'c'", + "innerText": "b\\\\c", + "complete": false, + "children": [ + { + "startIndex": 2, + "type": "ansi_c_string", + "endIndex": 8, + "text": "$'b\\\\'", + "innerText": "b\\\\", + "complete": true, + "children": [] + }, + { + "startIndex": 8, + "type": "word", + "endIndex": 9, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + }, + { + "startIndex": 9, + "type": "raw_string", + "endIndex": 10, + "text": "'", + "innerText": "", + "complete": false, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 9 +{ + "startIndex": 0, + "type": "program", + "endIndex": 9, + "text": "a 'b\\\\'c'", + "innerText": "a 'b\\\\'c'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 9, + "text": "a 'b\\\\'c'", + "innerText": "a 'b\\\\'c'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "concatenation", + "endIndex": 9, + "text": "'b\\\\'c'", + "innerText": "b\\\\c", + "complete": false, + "children": [ + { + "startIndex": 2, + "type": "raw_string", + "endIndex": 7, + "text": "'b\\\\'", + "innerText": "b\\\\", + "complete": true, + "children": [] + }, + { + "startIndex": 7, + "type": "word", + "endIndex": 8, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + }, + { + "startIndex": 8, + "type": "raw_string", + "endIndex": 9, + "text": "'", + "innerText": "", + "complete": false, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 10 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "a \"b$\"", + "innerText": "a \"b$\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 6, + "text": "a \"b$\"", + "innerText": "a \"b$\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "string", + "endIndex": 6, + "text": "\"b$\"", + "innerText": "b$", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 11 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "a \"$b\"", + "innerText": "a \"$b\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 6, + "text": "a \"$b\"", + "innerText": "a \"$b\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "string", + "endIndex": 6, + "text": "\"$b\"", + "innerText": "$b", + "complete": true, + "children": [ + { + "startIndex": 3, + "type": "simple_expansion", + "endIndex": 5, + "text": "$b", + "innerText": "$b", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 12 +{ + "startIndex": 0, + "type": "program", + "endIndex": 17, + "text": "a \"$(b \"c\" && d)\"", + "innerText": "a \"$(b \"c\" && d)\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 17, + "text": "a \"$(b \"c\" && d)\"", + "innerText": "a \"$(b \"c\" && d)\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "string", + "endIndex": 17, + "text": "\"$(b \"c\" && d)\"", + "innerText": "$(b \"c\" && d)", + "complete": true, + "children": [ + { + "startIndex": 3, + "type": "command_substitution", + "endIndex": 16, + "text": "$(b \"c\" && d)", + "innerText": "$(b \"c\" && d)", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "list", + "endIndex": 15, + "text": "b \"c\" && d", + "innerText": "b \"c\" && d", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "command", + "endIndex": 11, + "text": "b \"c\" ", + "innerText": "b \"c\" ", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 6, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + }, + { + "startIndex": 7, + "type": "string", + "endIndex": 10, + "text": "\"c\"", + "innerText": "c", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 14, + "type": "command", + "endIndex": 15, + "text": "d", + "innerText": "d", + "complete": true, + "children": [ + { + "startIndex": 14, + "type": "word", + "endIndex": 15, + "text": "d", + "innerText": "d", + "complete": true, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/extensions/terminal-suggest/fixtures/shell-parser/variables/input.sh b/extensions/terminal-suggest/fixtures/shell-parser/variables/input.sh new file mode 100644 index 000000000000..30b8788a90f2 --- /dev/null +++ b/extensions/terminal-suggest/fixtures/shell-parser/variables/input.sh @@ -0,0 +1,77 @@ +### Case 1 +ENV=a b + +### Case 2 +ENV=a b c d --op=e + +### Case 3 +ENV=a ENV=b a + +### Case 4 +ENV=a ENV=b a && ENV=c c + +### Case 5 +ENV="a b" c + +### Case 6 +ENV='a b' c + +### Case 7 +ENV=`cmd` a + +### Case 8 +ENV+='100' b + +### Case 9 +ENV+=a ENV=b + +### Case 10 +ENV+=a ENV=b && foo + +### Case 11 +ENV="a + +### Case 12 +ENV='a + +### Case 13 +ENV=a ENV=`b + +### Case 14 +ENV=`ENV="a" b` && ENV="c" d + +### Case 15 +c $(ENV=a foo) + +### Case 16 +ENV=a; b + +### Case 17 +ENV=a ; b + +### Case 18 +ENV=a & b + +### Case 19 +ENV=a|b + +### Case 20 +ENV[0]=a b + +### Case 21 +ENV[0]=a; b + +### Case 22 +ENV[1]=`a b + +### Case 23 +ENV[2]+="a b " + +### Case 24 +MY_VAR='echo'hi$'quote'"command: $(ps | VAR=2 grep ps)" + +### Case 25 +ENV="a"'b'c d + +### Case 26 +ENV=a"b"'c' \ No newline at end of file diff --git a/extensions/terminal-suggest/fixtures/shell-parser/variables/output.txt b/extensions/terminal-suggest/fixtures/shell-parser/variables/output.txt new file mode 100644 index 000000000000..9cbf4ab2ffb0 --- /dev/null +++ b/extensions/terminal-suggest/fixtures/shell-parser/variables/output.txt @@ -0,0 +1,2439 @@ +// Case 1 +{ + "startIndex": 0, + "type": "program", + "endIndex": 7, + "text": "ENV=a b", + "innerText": "ENV=a b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 7, + "text": "ENV=a b", + "innerText": "ENV=a b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 6, + "type": "command", + "endIndex": 7, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 6, + "type": "word", + "endIndex": 7, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] +} + +// Case 2 +{ + "startIndex": 0, + "type": "program", + "endIndex": 18, + "text": "ENV=a b c d --op=e", + "innerText": "ENV=a b c d --op=e", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 18, + "text": "ENV=a b c d --op=e", + "innerText": "ENV=a b c d --op=e", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 6, + "type": "command", + "endIndex": 18, + "text": "b c d --op=e", + "innerText": "b c d --op=e", + "complete": true, + "children": [ + { + "startIndex": 6, + "type": "word", + "endIndex": 7, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + }, + { + "startIndex": 8, + "type": "word", + "endIndex": 9, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + }, + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "d", + "innerText": "d", + "complete": true, + "children": [] + }, + { + "startIndex": 12, + "type": "word", + "endIndex": 18, + "text": "--op=e", + "innerText": "--op=e", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] +} + +// Case 3 +{ + "startIndex": 0, + "type": "program", + "endIndex": 13, + "text": "ENV=a ENV=b a", + "innerText": "ENV=a ENV=b a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 13, + "text": "ENV=a ENV=b a", + "innerText": "ENV=a ENV=b a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 6, + "type": "assignment", + "endIndex": 11, + "text": "ENV=b", + "innerText": "ENV=b", + "complete": true, + "children": [ + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 6, + "type": "variable_name", + "endIndex": 9, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 12, + "type": "command", + "endIndex": 13, + "text": "a", + "innerText": "a", + "complete": true, + "children": [ + { + "startIndex": 12, + "type": "word", + "endIndex": 13, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] +} + +// Case 4 +{ + "startIndex": 0, + "type": "program", + "endIndex": 24, + "text": "ENV=a ENV=b a && ENV=c c", + "innerText": "ENV=a ENV=b a && ENV=c c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "list", + "endIndex": 24, + "text": "ENV=a ENV=b a && ENV=c c", + "innerText": "ENV=a ENV=b a && ENV=c c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 14, + "text": "ENV=a ENV=b a ", + "innerText": "ENV=a ENV=b a ", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 6, + "type": "assignment", + "endIndex": 11, + "text": "ENV=b", + "innerText": "ENV=b", + "complete": true, + "children": [ + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 6, + "type": "variable_name", + "endIndex": 9, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 12, + "type": "command", + "endIndex": 14, + "text": "a ", + "innerText": "a ", + "complete": true, + "children": [ + { + "startIndex": 12, + "type": "word", + "endIndex": 13, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + }, + { + "startIndex": 17, + "type": "assignment_list", + "endIndex": 24, + "text": "ENV=c c", + "innerText": "ENV=c c", + "complete": true, + "children": [ + { + "startIndex": 17, + "type": "assignment", + "endIndex": 22, + "text": "ENV=c", + "innerText": "ENV=c", + "complete": true, + "children": [ + { + "startIndex": 21, + "type": "word", + "endIndex": 22, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 17, + "type": "variable_name", + "endIndex": 20, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 23, + "type": "command", + "endIndex": 24, + "text": "c", + "innerText": "c", + "complete": true, + "children": [ + { + "startIndex": 23, + "type": "word", + "endIndex": 24, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] + } + ] +} + +// Case 5 +{ + "startIndex": 0, + "type": "program", + "endIndex": 11, + "text": "ENV=\"a b\" c", + "innerText": "ENV=\"a b\" c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 11, + "text": "ENV=\"a b\" c", + "innerText": "ENV=\"a b\" c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 9, + "text": "ENV=\"a b\"", + "innerText": "ENV=\"a b\"", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "string", + "endIndex": 9, + "text": "\"a b\"", + "innerText": "a b", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 10, + "type": "command", + "endIndex": 11, + "text": "c", + "innerText": "c", + "complete": true, + "children": [ + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] +} + +// Case 6 +{ + "startIndex": 0, + "type": "program", + "endIndex": 11, + "text": "ENV='a b' c", + "innerText": "ENV='a b' c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 11, + "text": "ENV='a b' c", + "innerText": "ENV='a b' c", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 9, + "text": "ENV='a b'", + "innerText": "ENV='a b'", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "raw_string", + "endIndex": 9, + "text": "'a b'", + "innerText": "a b", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 10, + "type": "command", + "endIndex": 11, + "text": "c", + "innerText": "c", + "complete": true, + "children": [ + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] +} + +// Case 7 +{ + "startIndex": 0, + "type": "program", + "endIndex": 11, + "text": "ENV=`cmd` a", + "innerText": "ENV=`cmd` a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 11, + "text": "ENV=`cmd` a", + "innerText": "ENV=`cmd` a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 9, + "text": "ENV=`cmd`", + "innerText": "ENV=`cmd`", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "command_substitution", + "endIndex": 9, + "text": "`cmd`", + "innerText": "`cmd`", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "command", + "endIndex": 8, + "text": "cmd", + "innerText": "cmd", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 8, + "text": "cmd", + "innerText": "cmd", + "complete": true, + "children": [] + } + ] + } + ] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 10, + "type": "command", + "endIndex": 11, + "text": "a", + "innerText": "a", + "complete": true, + "children": [ + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] +} + +// Case 8 +{ + "startIndex": 0, + "type": "program", + "endIndex": 12, + "text": "ENV+='100' b", + "innerText": "ENV+='100' b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 12, + "text": "ENV+='100' b", + "innerText": "ENV+='100' b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 10, + "text": "ENV+='100'", + "innerText": "ENV+='100'", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "raw_string", + "endIndex": 10, + "text": "'100'", + "innerText": "100", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "+=" + }, + { + "startIndex": 11, + "type": "command", + "endIndex": 12, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 11, + "type": "word", + "endIndex": 12, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] +} + +// Case 9 +{ + "startIndex": 0, + "type": "program", + "endIndex": 12, + "text": "ENV+=a ENV=b", + "innerText": "ENV+=a ENV=b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 12, + "text": "ENV+=a ENV=b", + "innerText": "ENV+=a ENV=b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 6, + "text": "ENV+=a", + "innerText": "ENV+=a", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 6, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "+=" + }, + { + "startIndex": 7, + "type": "assignment", + "endIndex": 12, + "text": "ENV=b", + "innerText": "ENV=b", + "complete": true, + "children": [ + { + "startIndex": 11, + "type": "word", + "endIndex": 12, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 7, + "type": "variable_name", + "endIndex": 10, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + } + ] +} + +// Case 10 +{ + "startIndex": 0, + "type": "program", + "endIndex": 19, + "text": "ENV+=a ENV=b && foo", + "innerText": "ENV+=a ENV=b && foo", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "list", + "endIndex": 19, + "text": "ENV+=a ENV=b && foo", + "innerText": "ENV+=a ENV=b && foo", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 12, + "text": "ENV+=a ENV=b", + "innerText": "ENV+=a ENV=b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 6, + "text": "ENV+=a", + "innerText": "ENV+=a", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "word", + "endIndex": 6, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "+=" + }, + { + "startIndex": 7, + "type": "assignment", + "endIndex": 12, + "text": "ENV=b", + "innerText": "ENV=b", + "complete": true, + "children": [ + { + "startIndex": 11, + "type": "word", + "endIndex": 12, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 7, + "type": "variable_name", + "endIndex": 10, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + }, + { + "startIndex": 16, + "type": "command", + "endIndex": 19, + "text": "foo", + "innerText": "foo", + "complete": true, + "children": [ + { + "startIndex": 16, + "type": "word", + "endIndex": 19, + "text": "foo", + "innerText": "foo", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 11 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "ENV=\"a", + "innerText": "ENV=\"a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 6, + "text": "ENV=\"a", + "innerText": "ENV=\"a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 6, + "text": "ENV=\"a", + "innerText": "ENV=\"a", + "complete": false, + "children": [ + { + "startIndex": 4, + "type": "string", + "endIndex": 6, + "text": "\"a", + "innerText": "a", + "complete": false, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + } + ] +} + +// Case 12 +{ + "startIndex": 0, + "type": "program", + "endIndex": 6, + "text": "ENV='a", + "innerText": "ENV='a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 6, + "text": "ENV='a", + "innerText": "ENV='a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 6, + "text": "ENV='a", + "innerText": "ENV='a", + "complete": false, + "children": [ + { + "startIndex": 4, + "type": "raw_string", + "endIndex": 6, + "text": "'a", + "innerText": "a", + "complete": false, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + } + ] +} + +// Case 13 +{ + "startIndex": 0, + "type": "program", + "endIndex": 12, + "text": "ENV=a ENV=`b", + "innerText": "ENV=a ENV=`b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 12, + "text": "ENV=a ENV=`b", + "innerText": "ENV=a ENV=`b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 6, + "type": "assignment", + "endIndex": 12, + "text": "ENV=`b", + "innerText": "ENV=`b", + "complete": false, + "children": [ + { + "startIndex": 10, + "type": "command_substitution", + "endIndex": 12, + "text": "`b", + "innerText": "`b", + "complete": false, + "children": [ + { + "startIndex": 11, + "type": "command", + "endIndex": 12, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 11, + "type": "word", + "endIndex": 12, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ], + "name": { + "startIndex": 6, + "type": "variable_name", + "endIndex": 9, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + } + ] +} + +// Case 14 +{ + "startIndex": 0, + "type": "program", + "endIndex": 28, + "text": "ENV=`ENV=\"a\" b` && ENV=\"c\" d", + "innerText": "ENV=`ENV=\"a\" b` && ENV=\"c\" d", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "list", + "endIndex": 28, + "text": "ENV=`ENV=\"a\" b` && ENV=\"c\" d", + "innerText": "ENV=`ENV=\"a\" b` && ENV=\"c\" d", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 15, + "text": "ENV=`ENV=\"a\" b`", + "innerText": "ENV=`ENV=\"a\" b`", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 15, + "text": "ENV=`ENV=\"a\" b`", + "innerText": "ENV=`ENV=\"a\" b`", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "command_substitution", + "endIndex": 15, + "text": "`ENV=\"a\" b`", + "innerText": "`ENV=\"a\" b`", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "assignment_list", + "endIndex": 14, + "text": "ENV=\"a\" b", + "innerText": "ENV=\"a\" b", + "complete": true, + "children": [ + { + "startIndex": 5, + "type": "assignment", + "endIndex": 12, + "text": "ENV=\"a\"", + "innerText": "ENV=\"a\"", + "complete": true, + "children": [ + { + "startIndex": 9, + "type": "string", + "endIndex": 12, + "text": "\"a\"", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 5, + "type": "variable_name", + "endIndex": 8, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 13, + "type": "command", + "endIndex": 14, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 13, + "type": "word", + "endIndex": 14, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + }, + { + "startIndex": 19, + "type": "assignment_list", + "endIndex": 28, + "text": "ENV=\"c\" d", + "innerText": "ENV=\"c\" d", + "complete": true, + "children": [ + { + "startIndex": 19, + "type": "assignment", + "endIndex": 26, + "text": "ENV=\"c\"", + "innerText": "ENV=\"c\"", + "complete": true, + "children": [ + { + "startIndex": 23, + "type": "string", + "endIndex": 26, + "text": "\"c\"", + "innerText": "c", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 19, + "type": "variable_name", + "endIndex": 22, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 27, + "type": "command", + "endIndex": 28, + "text": "d", + "innerText": "d", + "complete": true, + "children": [ + { + "startIndex": 27, + "type": "word", + "endIndex": 28, + "text": "d", + "innerText": "d", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] + } + ] +} + +// Case 15 +{ + "startIndex": 0, + "type": "program", + "endIndex": 14, + "text": "c $(ENV=a foo)", + "innerText": "c $(ENV=a foo)", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "command", + "endIndex": 14, + "text": "c $(ENV=a foo)", + "innerText": "c $(ENV=a foo)", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "word", + "endIndex": 1, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + }, + { + "startIndex": 2, + "type": "command_substitution", + "endIndex": 14, + "text": "$(ENV=a foo)", + "innerText": "$(ENV=a foo)", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "assignment_list", + "endIndex": 13, + "text": "ENV=a foo", + "innerText": "ENV=a foo", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "assignment", + "endIndex": 9, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 8, + "type": "word", + "endIndex": 9, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 4, + "type": "variable_name", + "endIndex": 7, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 10, + "type": "command", + "endIndex": 13, + "text": "foo", + "innerText": "foo", + "complete": true, + "children": [ + { + "startIndex": 10, + "type": "word", + "endIndex": 13, + "text": "foo", + "innerText": "foo", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] + } + ] + } + ] +} + +// Case 16 +{ + "startIndex": 0, + "type": "program", + "endIndex": 8, + "text": "ENV=a; b", + "innerText": "ENV=a; b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + }, + { + "startIndex": 7, + "type": "command", + "endIndex": 8, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 7, + "type": "word", + "endIndex": 8, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 17 +{ + "startIndex": 0, + "type": "program", + "endIndex": 9, + "text": "ENV=a ; b", + "innerText": "ENV=a ; b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + }, + { + "startIndex": 8, + "type": "command", + "endIndex": 9, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 8, + "type": "word", + "endIndex": 9, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 18 +{ + "startIndex": 0, + "type": "program", + "endIndex": 9, + "text": "ENV=a & b", + "innerText": "ENV=a & b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + }, + { + "startIndex": 8, + "type": "command", + "endIndex": 9, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 8, + "type": "word", + "endIndex": 9, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 19 +{ + "startIndex": 0, + "type": "program", + "endIndex": 7, + "text": "ENV=a|b", + "innerText": "ENV=a|b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "pipeline", + "endIndex": 7, + "text": "ENV=a|b", + "innerText": "ENV=a|b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 5, + "text": "ENV=a", + "innerText": "ENV=a", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + }, + { + "startIndex": 6, + "type": "command", + "endIndex": 7, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 6, + "type": "word", + "endIndex": 7, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ] +} + +// Case 20 +{ + "startIndex": 0, + "type": "program", + "endIndex": 10, + "text": "ENV[0]=a b", + "innerText": "ENV[0]=a b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 10, + "text": "ENV[0]=a b", + "innerText": "ENV[0]=a b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 8, + "text": "ENV[0]=a", + "innerText": "ENV[0]=a", + "complete": true, + "children": [ + { + "startIndex": 7, + "type": "word", + "endIndex": 8, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "subscript", + "endIndex": 6, + "text": "ENV[0]", + "innerText": "ENV[0]", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "0", + "innerText": "0", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + } + }, + "operator": "=" + }, + { + "startIndex": 9, + "type": "command", + "endIndex": 10, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 9, + "type": "word", + "endIndex": 10, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] +} + +// Case 21 +{ + "startIndex": 0, + "type": "program", + "endIndex": 11, + "text": "ENV[0]=a; b", + "innerText": "ENV[0]=a; b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 8, + "text": "ENV[0]=a", + "innerText": "ENV[0]=a", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 8, + "text": "ENV[0]=a", + "innerText": "ENV[0]=a", + "complete": true, + "children": [ + { + "startIndex": 7, + "type": "word", + "endIndex": 8, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "subscript", + "endIndex": 6, + "text": "ENV[0]", + "innerText": "ENV[0]", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "0", + "innerText": "0", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + } + }, + "operator": "=" + } + ], + "hasCommand": false + }, + { + "startIndex": 10, + "type": "command", + "endIndex": 11, + "text": "b", + "innerText": "b", + "complete": true, + "children": [ + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] +} + +// Case 22 +{ + "startIndex": 0, + "type": "program", + "endIndex": 11, + "text": "ENV[1]=`a b", + "innerText": "ENV[1]=`a b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 11, + "text": "ENV[1]=`a b", + "innerText": "ENV[1]=`a b", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 11, + "text": "ENV[1]=`a b", + "innerText": "ENV[1]=`a b", + "complete": false, + "children": [ + { + "startIndex": 7, + "type": "command_substitution", + "endIndex": 11, + "text": "`a b", + "innerText": "`a b", + "complete": false, + "children": [ + { + "startIndex": 8, + "type": "command", + "endIndex": 11, + "text": "a b", + "innerText": "a b", + "complete": true, + "children": [ + { + "startIndex": 8, + "type": "word", + "endIndex": 9, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "b", + "innerText": "b", + "complete": true, + "children": [] + } + ] + } + ] + } + ], + "name": { + "startIndex": 0, + "type": "subscript", + "endIndex": 6, + "text": "ENV[1]", + "innerText": "ENV[1]", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "1", + "innerText": "1", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + } + }, + "operator": "=" + } + ], + "hasCommand": false + } + ] +} + +// Case 23 +{ + "startIndex": 0, + "type": "program", + "endIndex": 14, + "text": "ENV[2]+=\"a b \"", + "innerText": "ENV[2]+=\"a b \"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 14, + "text": "ENV[2]+=\"a b \"", + "innerText": "ENV[2]+=\"a b \"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 14, + "text": "ENV[2]+=\"a b \"", + "innerText": "ENV[2]+=\"a b \"", + "complete": true, + "children": [ + { + "startIndex": 8, + "type": "string", + "endIndex": 14, + "text": "\"a b \"", + "innerText": "a b ", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "subscript", + "endIndex": 6, + "text": "ENV[2]", + "innerText": "ENV[2]", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "2", + "innerText": "2", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + } + }, + "operator": "+=" + } + ], + "hasCommand": false + } + ] +} + +// Case 24 +{ + "startIndex": 0, + "type": "program", + "endIndex": 55, + "text": "MY_VAR='echo'hi$'quote'\"command: $(ps | VAR=2 grep ps)\"", + "innerText": "MY_VAR='echo'hi$'quote'\"command: $(ps | VAR=2 grep ps)\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 55, + "text": "MY_VAR='echo'hi$'quote'\"command: $(ps | VAR=2 grep ps)\"", + "innerText": "MY_VAR='echo'hi$'quote'\"command: $(ps | VAR=2 grep ps)\"", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 55, + "text": "MY_VAR='echo'hi$'quote'\"command: $(ps | VAR=2 grep ps)\"", + "innerText": "MY_VAR='echo'hi$'quote'\"command: $(ps | VAR=2 grep ps)\"", + "complete": true, + "children": [ + { + "startIndex": 7, + "type": "concatenation", + "endIndex": 55, + "text": "'echo'hi$'quote'\"command: $(ps | VAR=2 grep ps)\"", + "innerText": "echohiquotecommand: $(ps | VAR=2 grep ps)", + "complete": true, + "children": [ + { + "startIndex": 7, + "type": "raw_string", + "endIndex": 13, + "text": "'echo'", + "innerText": "echo", + "complete": true, + "children": [] + }, + { + "startIndex": 13, + "type": "word", + "endIndex": 15, + "text": "hi", + "innerText": "hi", + "complete": true, + "children": [] + }, + { + "startIndex": 15, + "type": "ansi_c_string", + "endIndex": 23, + "text": "$'quote'", + "innerText": "quote", + "complete": true, + "children": [] + }, + { + "startIndex": 23, + "type": "string", + "endIndex": 55, + "text": "\"command: $(ps | VAR=2 grep ps)\"", + "innerText": "command: $(ps | VAR=2 grep ps)", + "complete": true, + "children": [ + { + "startIndex": 33, + "type": "command_substitution", + "endIndex": 54, + "text": "$(ps | VAR=2 grep ps)", + "innerText": "$(ps | VAR=2 grep ps)", + "complete": true, + "children": [ + { + "startIndex": 35, + "type": "pipeline", + "endIndex": 53, + "text": "ps | VAR=2 grep ps", + "innerText": "ps | VAR=2 grep ps", + "complete": true, + "children": [ + { + "startIndex": 35, + "type": "command", + "endIndex": 38, + "text": "ps ", + "innerText": "ps ", + "complete": true, + "children": [ + { + "startIndex": 35, + "type": "word", + "endIndex": 37, + "text": "ps", + "innerText": "ps", + "complete": true, + "children": [] + } + ] + }, + { + "startIndex": 40, + "type": "assignment_list", + "endIndex": 53, + "text": "VAR=2 grep ps", + "innerText": "VAR=2 grep ps", + "complete": true, + "children": [ + { + "startIndex": 40, + "type": "assignment", + "endIndex": 45, + "text": "VAR=2", + "innerText": "VAR=2", + "complete": true, + "children": [ + { + "startIndex": 44, + "type": "word", + "endIndex": 45, + "text": "2", + "innerText": "2", + "complete": true, + "children": [] + } + ], + "name": { + "startIndex": 40, + "type": "variable_name", + "endIndex": 43, + "text": "VAR", + "innerText": "VAR", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 46, + "type": "command", + "endIndex": 53, + "text": "grep ps", + "innerText": "grep ps", + "complete": true, + "children": [ + { + "startIndex": 46, + "type": "word", + "endIndex": 50, + "text": "grep", + "innerText": "grep", + "complete": true, + "children": [] + }, + { + "startIndex": 51, + "type": "word", + "endIndex": 53, + "text": "ps", + "innerText": "ps", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] + } + ] + } + ] + } + ] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 6, + "text": "MY_VAR", + "innerText": "MY_VAR", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + } + ] +} + +// Case 25 +{ + "startIndex": 0, + "type": "program", + "endIndex": 13, + "text": "ENV=\"a\"'b'c d", + "innerText": "ENV=\"a\"'b'c d", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 13, + "text": "ENV=\"a\"'b'c d", + "innerText": "ENV=\"a\"'b'c d", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 11, + "text": "ENV=\"a\"'b'c", + "innerText": "ENV=\"a\"'b'c", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "concatenation", + "endIndex": 11, + "text": "\"a\"'b'c", + "innerText": "abc", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "string", + "endIndex": 7, + "text": "\"a\"", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 7, + "type": "raw_string", + "endIndex": 10, + "text": "'b'", + "innerText": "b", + "complete": true, + "children": [] + }, + { + "startIndex": 10, + "type": "word", + "endIndex": 11, + "text": "c", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + }, + { + "startIndex": 12, + "type": "command", + "endIndex": 13, + "text": "d", + "innerText": "d", + "complete": true, + "children": [ + { + "startIndex": 12, + "type": "word", + "endIndex": 13, + "text": "d", + "innerText": "d", + "complete": true, + "children": [] + } + ] + } + ], + "hasCommand": true + } + ] +} + +// Case 26 +{ + "startIndex": 0, + "type": "program", + "endIndex": 11, + "text": "ENV=a\"b\"'c'", + "innerText": "ENV=a\"b\"'c'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment_list", + "endIndex": 11, + "text": "ENV=a\"b\"'c'", + "innerText": "ENV=a\"b\"'c'", + "complete": true, + "children": [ + { + "startIndex": 0, + "type": "assignment", + "endIndex": 11, + "text": "ENV=a\"b\"'c'", + "innerText": "ENV=a\"b\"'c'", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "concatenation", + "endIndex": 11, + "text": "a\"b\"'c'", + "innerText": "abc", + "complete": true, + "children": [ + { + "startIndex": 4, + "type": "word", + "endIndex": 5, + "text": "a", + "innerText": "a", + "complete": true, + "children": [] + }, + { + "startIndex": 5, + "type": "string", + "endIndex": 8, + "text": "\"b\"", + "innerText": "b", + "complete": true, + "children": [] + }, + { + "startIndex": 8, + "type": "raw_string", + "endIndex": 11, + "text": "'c'", + "innerText": "c", + "complete": true, + "children": [] + } + ] + } + ], + "name": { + "startIndex": 0, + "type": "variable_name", + "endIndex": 3, + "text": "ENV", + "innerText": "ENV", + "complete": true, + "children": [] + }, + "operator": "=" + } + ], + "hasCommand": false + } + ] +} \ No newline at end of file diff --git a/extensions/terminal-suggest/package.json b/extensions/terminal-suggest/package.json index 82e488dd9f52..dcc02bff6a24 100644 --- a/extensions/terminal-suggest/package.json +++ b/extensions/terminal-suggest/package.json @@ -20,9 +20,9 @@ ], "scripts": { "compile": "npx gulp compile-extension:terminal-suggest", - "watch": "npx gulp watch-extension:terminal-suggest" + "watch": "npx gulp watch-extension:terminal-suggest", + "pull-zshbuiltins": "ts-node ./scripts/pullZshBuiltins.ts" }, - "main": "./out/terminalSuggestMain", "activationEvents": [ "onTerminalCompletionsRequested" diff --git a/extensions/terminal-suggest/scripts/clone-fig.sh b/extensions/terminal-suggest/scripts/clone-fig.sh old mode 100644 new mode 100755 diff --git a/extensions/terminal-suggest/scripts/pullZshBuiltins.ts b/extensions/terminal-suggest/scripts/pullZshBuiltins.ts new file mode 100644 index 000000000000..cedfc85cd138 --- /dev/null +++ b/extensions/terminal-suggest/scripts/pullZshBuiltins.ts @@ -0,0 +1,268 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { exec } from 'child_process'; +import { promisify } from 'util'; +import * as fs from 'fs/promises'; +import * as path from 'path'; +import { platform } from 'os'; + +if (platform() === 'win32') { + console.error('\x1b[31mThis command is not supported on Windows\x1b[0m'); + process.exit(1); +} + +const latestZshVersion = 5.9; + +const shortDescriptions: Map = new Map([ + ['.', 'Source a file'], + [':', 'No effect'], + ['alias', 'Define or view aliases'], + ['autoload', 'Autoload a function'], + ['bg', 'Put a job in the background'], + ['bindkey', 'Manipulate keymap names'], + ['break', 'Exit from a loop'], + ['builtin', 'Executes a builtin'], + ['bye', 'Exit the shell'], + ['cap', 'Manipulating POSIX capability sets'], + ['cd', 'Change the current directory'], + ['chdir', 'Change the current directory'], + ['clone', 'Clone shell onto another terminal'], + ['command', 'Execute a command'], + ['comparguments', 'Complete arguments'], + ['compcall', 'Complete call'], + ['compctl', 'Complete control'], + ['compdescribe', 'Complete describe'], + ['compfiles', 'Complete files'], + ['compgroups', 'Complete groups'], + ['compquote', 'Complete quote'], + ['comptags', 'Complete tags'], + ['comptry', 'Complete try'], + ['compvalues', 'Complete values'], + ['continue', 'Resume the next loop iteration'], + ['declare', 'Set or display parameter attributes/values'], + ['dirs', 'Interact with directory stack'], + ['disable', 'Disable shell features'], + ['disown', 'Remove job from job table'], + ['echo', 'Write on standard output'], + ['echotc', 'Echo terminal capabilities'], + ['echoti', 'Echo terminal info'], + ['emulate', 'Emulate a shell'], + ['enable', 'Enable shell features'], + ['eval', 'Execute arguments in shell'], + ['exec', 'Replace shell with command'], + ['exit', 'Exit the shell'], + ['export', 'Export to environment'], + ['false', 'Return exit status of 1'], + ['fc', 'Fix command'], + ['fg', 'Put a job in the foreground'], + ['float', 'Floating point arithmetic'], + ['functions', 'List functions'], + ['getcap', 'Get capabilities'], + ['getln', 'Get line from buffer'], + ['getopts', 'Parse positional parameters'], + ['hash', 'Remember command locations'], + ['history', 'Command history'], + ['integer', 'Integer arithmetic'], + ['jobs', 'List active jobs'], + ['kill', 'Send a signal to a process'], + ['let', 'Evaluate arithmetic expression'], + ['limit', 'Set or display resource limits'], + ['local', 'Create a local variable'], + ['logout', 'Exit the shell'], + ['noglob', 'Disable filename expansion'], + ['popd', 'Remove directory from stack'], + ['print', 'Print arguments'], + ['printf', 'Format and print data'], + ['pushd', 'Add directory to stack'], + ['pushln', 'Push arguments onto the buffer'], + ['pwd', 'Print working directory'], + ['r', 'Re-execute command'], + ['read', 'Read a line from input'], + ['readonly', 'Mark variables as read-only'], + ['rehash', 'Recompute command hash table'], + ['return', 'Return from a function'], + ['sched', 'Schedule commands'], + ['set', 'Set shell options'], + ['setcap', 'Set capabilities'], + ['setopt', 'Set shell options'], + ['shift', 'Shift positional parameters'], + ['source', 'Source a file'], + ['stat', 'Display file status'], + ['suspend', 'Suspend the shell'], + ['test', 'Evaluate a conditional expression'], + ['times', 'Display shell times'], + ['trap', 'Set signal handlers'], + ['true', 'Return exit status of 0'], + ['ttyctl', 'Control terminal attributes'], + ['type', 'Describe a command'], + ['typeset', 'Set or display parameter attributes/values'], + ['ulimit', 'Set or display resource limits'], + ['umask', 'Set file creation mask'], + ['unalias', 'Removes aliases'], + ['unfunction', 'Remove function definition'], + ['unhash', 'Remove command from hash table'], + ['unlimit', 'Remove resource limits'], + ['unset', 'Unset values and attributes of variables'], + ['unsetopt', 'Unset shell options'], + ['vared', 'Edit shell variables'], + ['wait', 'Wait for a process'], + ['whence', 'Locate a command'], + ['where', 'Locate a command'], + ['which', 'Locate a command'], + ['zcompile', 'Compile functions'], + ['zformat', 'Format strings'], + ['zftp', 'Zsh FTP client'], + ['zle', 'Zsh line editor'], + ['zmodload', 'Load a module'], + ['zparseopts', 'Parse options'], + ['zprof', 'Zsh profiler'], + ['zpty', 'Zsh pseudo terminal'], + ['zregexparse', 'Parse regex'], + ['zsocket', 'Zsh socket interface'], + ['zstyle', 'Define styles'], + ['ztcp', 'Manipulate TCP sockets'], +]); + +const execAsync = promisify(exec); + +interface ICommandDetails { + description: string; + args: string | undefined; + shortDescription?: string; +} +let zshBuiltinsCommandDescriptionsCache = new Map(); +async function createCommandDescriptionsCache(): Promise { + const cachedCommandDescriptions: Map = new Map(); + let output = ''; + const zshVersionOutput = await execAsync('zsh --version').then(r => r.stdout); + const zshVersionMatch = zshVersionOutput.match(/zsh (\d+\.\d+)/); + if (!zshVersionMatch) { + console.error('\x1b[31mFailed to determine zsh version\x1b[0m'); + process.exit(1); + } + const zshVersion = parseFloat(zshVersionMatch[1]); + if (zshVersion < latestZshVersion) { + console.error(`\x1b[31mZsh version must be ${latestZshVersion} or higher\x1b[0m`); + process.exit(1); + } + try { + output = await execAsync('pandoc --from man --to markdown --wrap=none < $(man -w zshbuiltins)').then(r => r.stdout); + } catch { + } + + const commands: Map = new Map(); + const commandRegex = /^\*\*(?[a-z\.:]+)\*\*(?:\s\*.+\*)?(?:\s\\\[.+\\\])?$/; + if (output) { + const lines = output.split('\n'); + let currentCommand: string | undefined; + let currentCommandStart = 0; + let seenOutput = false; + let i = 0; + for (; i < lines.length; i++) { + if (!currentCommand || seenOutput) { + const match = lines[i].match(commandRegex); + if (match?.groups?.command) { + if (currentCommand) { + commands.set(currentCommand, lines.slice(currentCommandStart, i)); + } + currentCommand = match.groups.command; + currentCommandStart = i; + seenOutput = false; + } + } + if (!currentCommand) { + continue; + } + // There may be several examples of usage + if (!seenOutput) { + seenOutput = lines[i].length > 0 && !lines[i].match(commandRegex); + } + } + if (currentCommand) { + commands.set(currentCommand, lines.slice(currentCommandStart, i - 1)); + } + } + + if (commands.size === 0) { + console.error('\x1b[31mFailed to parse command descriptions\x1b[30m'); + process.exit(1); + } + + for (const [command, lines] of commands) { + const shortDescription = shortDescriptions.get(command); + let argsEnd = 0; + try { + while (true) { + const line = lines[++argsEnd]; + if (line.trim().length > 0 && !line.match(commandRegex)) { + break; + } + } + } catch (e) { + console.log(e); + } + const formattedArgs = lines.slice(0, argsEnd - 1).join('\n'); + const args = (await execAsync(`pandoc --from markdown --to plain <<< "${formattedArgs}"`)).stdout.trim(); + const description = lines.slice(argsEnd).map(e => formatLineAsMarkdown(e)).join('\n').trim(); + if (shortDescription) { + cachedCommandDescriptions.set(command, { + shortDescription, + description, + args + }); + } else { + cachedCommandDescriptions.set(command, { + description, + args + }); + } + } + + zshBuiltinsCommandDescriptionsCache = cachedCommandDescriptions; +} + +function formatLineAsMarkdown(text: string): string { + // Detect any inline code blocks which use the form `code' (backtick, single quote) and convert + // them to standard markdown `code` (backtick, backtick). This doesn't attempt to remove + // formatting inside the code blocks. We probably need to use the original .troff format to do + // this + const formattedText = text.replace(/\\`([^']+)\\'/g, '`$1`'); + return formattedText; +} + +const main = async () => { + try { + await createCommandDescriptionsCache(); + console.log('created command descriptions cache with ', zshBuiltinsCommandDescriptionsCache.size, 'entries'); + + const missingShortDescription: string[] = []; + for (const [command, entry] of zshBuiltinsCommandDescriptionsCache.entries()) { + if (entry.shortDescription === undefined) { + missingShortDescription.push(command); + } + } + if (missingShortDescription.length > 0) { + console.log('\x1b[31mmissing short description for commands:\n' + missingShortDescription.join('\n') + '\x1b[0m'); + } + + // Save the cache to a TypeScript file + const cacheFilePath = path.join(__dirname, '../src/shell/zshBuiltinsCache.ts'); + const cacheObject = Object.fromEntries(zshBuiltinsCommandDescriptionsCache); + const tsContent = `${copyright}\n\nexport const zshBuiltinsCommandDescriptionsCache = ${JSON.stringify(cacheObject, null, 2)} as const;`; + await fs.writeFile(cacheFilePath, tsContent, 'utf8'); + console.log('saved command descriptions cache to zshBuiltinsCache.ts with ', Object.keys(cacheObject).length, 'entries'); + } catch (error) { + console.error('Error:', error); + } +}; + +const copyright = ` +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/`; + +main(); diff --git a/extensions/terminal-suggest/scripts/update-specs.js b/extensions/terminal-suggest/scripts/update-specs.js index 3573c6664d6d..775c5dd32648 100644 --- a/extensions/terminal-suggest/scripts/update-specs.js +++ b/extensions/terminal-suggest/scripts/update-specs.js @@ -3,14 +3,55 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +// @ts-check + const fs = require('fs'); const path = require('path'); const upstreamSpecs = require('../out/constants.js').upstreamSpecs; - const extRoot = path.resolve(path.join(__dirname, '..')); +const replaceStrings = [ + [ + 'import { filepaths } from "@fig/autocomplete-generators";', + 'import { filepaths } from \'../../helpers/filepaths\';' + ], +]; +const indentSearch = [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1].map(e => new RegExp('^' + ' '.repeat(e * 2), 'gm')); +const indentReplaceValue = [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1].map(e => '\t'.repeat(e)); + +const specSpecificReplaceStrings = new Map([ + ['git', [ + [ + 'import { ai } from "@fig/autocomplete-generators";', + 'function ai(...args: any[]): undefined { return undefined; }' + ], [ + 'prompt: async ({ executeCommand }) => {', + 'prompt: async ({ executeCommand }: any) => {' + ], [ + 'message: async ({ executeCommand }) =>', + 'message: async ({ executeCommand }: any) =>' + ] + ]], +]); + for (const spec of upstreamSpecs) { const source = path.join(extRoot, `third_party/autocomplete/src/${spec}.ts`); const destination = path.join(extRoot, `src/completions/upstream/${spec}.ts`); fs.copyFileSync(source, destination); + + let content = fs.readFileSync(destination).toString(); + for (const replaceString of replaceStrings) { + content = content.replaceAll(replaceString[0], replaceString[1]); + } + for (let i = 0; i < indentSearch.length; i++) { + content = content.replaceAll(indentSearch[i], indentReplaceValue[i]); + } + const thisSpecReplaceStrings = specSpecificReplaceStrings.get(spec); + if (thisSpecReplaceStrings) { + for (const replaceString of thisSpecReplaceStrings) { + content = content.replaceAll(replaceString[0], replaceString[1]); + } + } + + fs.writeFileSync(destination, content); } diff --git a/extensions/terminal-suggest/scripts/update-specs.sh b/extensions/terminal-suggest/scripts/update-specs.sh old mode 100644 new mode 100755 diff --git a/extensions/terminal-suggest/src/completions/cd.ts b/extensions/terminal-suggest/src/completions/cd.ts index 0eb7aaba25b1..ee38ca1a526a 100644 --- a/extensions/terminal-suggest/src/completions/cd.ts +++ b/extensions/terminal-suggest/src/completions/cd.ts @@ -16,11 +16,6 @@ const cdSpec: Fig.Spec = { description: 'Switch to the last used folder', hidden: true, }, - { - name: '~', - description: 'Switch to the home directory', - hidden: true, - }, ], } }; diff --git a/extensions/terminal-suggest/src/completions/code-insiders.ts b/extensions/terminal-suggest/src/completions/code-insiders.ts index 89d01dc536ff..1eb4f04acb17 100644 --- a/extensions/terminal-suggest/src/completions/code-insiders.ts +++ b/extensions/terminal-suggest/src/completions/code-insiders.ts @@ -2,12 +2,17 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import code from './code'; +import code, { commonOptions, extensionManagementOptions, troubleshootingOptions } from './code'; const codeInsidersCompletionSpec: Fig.Spec = { ...code, name: 'code-insiders', description: 'Visual Studio Code Insiders', + options: [ + ...commonOptions, + ...extensionManagementOptions('code-insiders'), + ...troubleshootingOptions('code-insiders'), + ], }; export default codeInsidersCompletionSpec; diff --git a/extensions/terminal-suggest/src/completions/code.ts b/extensions/terminal-suggest/src/completions/code.ts index c514a32e2e19..919253c387f6 100644 --- a/extensions/terminal-suggest/src/completions/code.ts +++ b/extensions/terminal-suggest/src/completions/code.ts @@ -3,7 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -const commonOptions: Fig.Option[] = [ +import { filepaths } from '../helpers/filepaths'; + +export const commonOptions: Fig.Option[] = [ { name: '-', description: `Read from stdin (e.g. 'ps aux | grep code | code -')`, @@ -60,7 +62,6 @@ const commonOptions: Fig.Option[] = [ 'Open a file at the path on the specified line and character position', args: { name: 'file:line[:character]', - // TODO: Support :line[:character] completion? template: 'filepaths', }, }, @@ -135,9 +136,25 @@ const commonOptions: Fig.Option[] = [ name: ['-h', '--help'], description: 'Print usage', }, + { + name: '--locate-shell-integration-path', + description: + 'Print the path to the shell integration script for the provided shell', + args: { + isOptional: false, + name: 'shell', + description: 'The shell to locate the integration script for', + suggestions: [ + 'bash', + 'fish', + 'pwsh', + 'zsh', + ] + } + } ]; -const extensionManagementOptions: Fig.Option[] = [ +export const extensionManagementOptions = (cliName: string): Fig.Option[] => [ { name: '--extensions-dir', description: 'Set the root path for extensions', @@ -188,8 +205,13 @@ const extensionManagementOptions: Fig.Option[] = [ description: `Installs or updates an extension. The argument is either an extension id or a path to a VSIX. The identifier of an extension is '\${ publisher }.\${ name }'. Use '--force' argument to update to latest version. To install a specific version provide '@\${version}'. For example: 'vscode.csharp@1.2.3'`, args: { - // TODO: Create extension ID generator name: 'extension-id[@version] | path-to-vsix', + generators: [ + createCodeGenerators(cliName), + filepaths({ + extensions: ['vsix'], + }), + ], }, }, { @@ -201,8 +223,8 @@ const extensionManagementOptions: Fig.Option[] = [ name: '--uninstall-extension', description: 'Uninstalls an extension', args: { - // TODO: Create extension ID generator name: 'extension-id', + generators: createCodeGenerators(cliName) }, }, { @@ -212,7 +234,7 @@ const extensionManagementOptions: Fig.Option[] = [ }, ]; -const troubleshootingOptions: Fig.Option[] = [ +export const troubleshootingOptions = (cliName: string): Fig.Option[] => [ { name: ['-v', '--version'], description: 'Print version', @@ -254,8 +276,8 @@ const troubleshootingOptions: Fig.Option[] = [ name: '--disable-extension', description: 'Disable an extension', args: { - // TODO: Create extension ID generator name: 'extension-id', + generators: createCodeGenerators(cliName) }, }, { @@ -301,6 +323,26 @@ const troubleshootingOptions: Fig.Option[] = [ }, ]; +export function createCodeGenerators(cliName: string): Fig.Generator { + return { + script: [cliName, '--list-extensions', '--show-versions'], + postProcess: parseInstalledExtensions + }; +} + +export function parseInstalledExtensions(out: string): Fig.Suggestion[] | undefined { + const extensions = out.split('\n').filter(Boolean).map((line) => { + const [id, version] = line.split('@'); + return { + name: id, + type: 'option' as Fig.SuggestionType, + description: `Version: ${version}` + }; + }); + return extensions; +} + + const codeCompletionSpec: Fig.Spec = { name: 'code', description: 'Visual Studio Code', @@ -310,9 +352,10 @@ const codeCompletionSpec: Fig.Spec = { }, options: [ ...commonOptions, - ...extensionManagementOptions, - ...troubleshootingOptions, + ...extensionManagementOptions('code'), + ...troubleshootingOptions('code'), ], }; export default codeCompletionSpec; + diff --git a/extensions/terminal-suggest/src/completions/index.d.ts b/extensions/terminal-suggest/src/completions/index.d.ts index de76233ecb47..44dcb9814456 100644 --- a/extensions/terminal-suggest/src/completions/index.d.ts +++ b/extensions/terminal-suggest/src/completions/index.d.ts @@ -1,1300 +1,1300 @@ /* eslint-disable @typescript-eslint/ban-types */ declare namespace Fig { - /** - * Templates are generators prebuilt by Fig. - * @remarks - * Here are the three templates: - * - filepaths: show folders and filepaths. Allow autoexecute on filepaths - * - folders: show folders only. Allow autoexecute on folders - * - history: show suggestions for all items in history matching this pattern - * - help: show subcommands. Only includes the 'siblings' of the nearest 'parent' subcommand - */ - type TemplateStrings = "filepaths" | "folders" | "history" | "help"; + /** + * Templates are generators prebuilt by Fig. + * @remarks + * Here are the three templates: + * - filepaths: show folders and filepaths. Allow autoexecute on filepaths + * - folders: show folders only. Allow autoexecute on folders + * - history: show suggestions for all items in history matching this pattern + * - help: show subcommands. Only includes the 'siblings' of the nearest 'parent' subcommand + */ + type TemplateStrings = "filepaths" | "folders" | "history" | "help"; - /** - * A template which is a single TemplateString or an array of TemplateStrings - * - * @remarks - * Templates are generators prebuilt by Fig. Here are the three templates: - * - filepaths: show folders and filepaths. Allow autoexecute on filepaths - * - folders: show folders only. Allow autoexecute on folders - * - history: show suggestions for all items in history matching this pattern - * - help: show subcommands. Only includes the 'siblings' of the nearest 'parent' subcommand - * - * @example - * `cd` uses the "folders" template - * `ls` used ["filepaths", "folders"]. Why both? Because if I `ls` a directory, we want to enable a user to autoexecute on this directory. If we just did "filepaths" they couldn't autoexecute. - * - */ - type Template = TemplateStrings | TemplateStrings[]; + /** + * A template which is a single TemplateString or an array of TemplateStrings + * + * @remarks + * Templates are generators prebuilt by Fig. Here are the three templates: + * - filepaths: show folders and filepaths. Allow autoexecute on filepaths + * - folders: show folders only. Allow autoexecute on folders + * - history: show suggestions for all items in history matching this pattern + * - help: show subcommands. Only includes the 'siblings' of the nearest 'parent' subcommand + * + * @example + * `cd` uses the "folders" template + * `ls` used ["filepaths", "folders"]. Why both? Because if I `ls` a directory, we want to enable a user to autoexecute on this directory. If we just did "filepaths" they couldn't autoexecute. + * + */ + type Template = TemplateStrings | TemplateStrings[]; - type HistoryContext = { - currentWorkingDirectory: string; - time: number; - exitCode: number; - shell: string; - }; + type HistoryContext = { + currentWorkingDirectory: string; + time: number; + exitCode: number; + shell: string; + }; - type TemplateSuggestionContext = - | { templateType: "filepaths" } - | { templateType: "folders" } - | { templateType: "help" } - | ({ templateType: "history" } & Partial); + type TemplateSuggestionContext = + | { templateType: "filepaths" } + | { templateType: "folders" } + | { templateType: "help" } + | ({ templateType: "history" } & Partial); - type TemplateSuggestion = Modify< - Suggestion, - { name?: string; context: TemplateSuggestionContext } - >; + type TemplateSuggestion = Modify< + Suggestion, + { name?: string; context: TemplateSuggestionContext } + >; - /** - * - * The SpecLocation object defines well... the location of the completion spec we want to load. - * Specs can be "global" (ie hosted by Fig's cloud) or "local" (ie stored on your local machine) - * - * @remarks - * **The `SpecLocation` Object** - * - * The SpecLocation object defines well... the location of the completion spec we want to load. - * Specs can be "global" (ie hosted by Fig's cloud) or "local" (ie stored on your local machine). - * - * - Global `SpecLocation`: - * Load specs hosted in Fig's Cloud. Assume the current working directory is here: https://github.com/withfig/autocomplete/tree/master/src. Now set the value for the "name" prop to the relative location of your spec (without the .js file extension) - * ```js - * // e.g. - * { type: "global", name: "aws/s3" } // Loads up the aws s3 completion spec - * { type: "global", name: "python/http.server" } // Loads up the http.server completion spec - * ``` - * - * - Local `SpecLocation`: - * Load specs saved on your local system / machine. Assume the current working directory is the user's current working directory. - * The `name` prop should take the name of the spec (without the .js file extension) e.g. my_cli_tool - * The `path` prop should take an absolute path OR a relative path (relative to the user's current working directory). The path should be to the directory that contains the `.fig` folder. Fig will then assume your spec is located in `.fig/autocomplete/build/` - * ```js - * // e.g. - * { type: "global", path: "node_modules/cowsay", name: "cowsay_cli" } // will look for `cwd/node_modules/cowsay/.fig/autocomplete/build/cowsay_cli.js` - * { type: "global", path: "~", name: "my_cli" } // will look for `~/.fig/autocomplete/build/my_cli.js` - * ``` - * @irreplaceable - */ - type SpecLocation = - | { type: "local"; path?: string; name: string } - | { type: "global"; name: string }; + /** + * + * The SpecLocation object defines well... the location of the completion spec we want to load. + * Specs can be "global" (ie hosted by Fig's cloud) or "local" (ie stored on your local machine) + * + * @remarks + * **The `SpecLocation` Object** + * + * The SpecLocation object defines well... the location of the completion spec we want to load. + * Specs can be "global" (ie hosted by Fig's cloud) or "local" (ie stored on your local machine). + * + * - Global `SpecLocation`: + * Load specs hosted in Fig's Cloud. Assume the current working directory is here: https://github.com/withfig/autocomplete/tree/master/src. Now set the value for the "name" prop to the relative location of your spec (without the .js file extension) + * ```js + * // e.g. + * { type: "global", name: "aws/s3" } // Loads up the aws s3 completion spec + * { type: "global", name: "python/http.server" } // Loads up the http.server completion spec + * ``` + * + * - Local `SpecLocation`: + * Load specs saved on your local system / machine. Assume the current working directory is the user's current working directory. + * The `name` prop should take the name of the spec (without the .js file extension) e.g. my_cli_tool + * The `path` prop should take an absolute path OR a relative path (relative to the user's current working directory). The path should be to the directory that contains the `.fig` folder. Fig will then assume your spec is located in `.fig/autocomplete/build/` + * ```js + * // e.g. + * { type: "global", path: "node_modules/cowsay", name: "cowsay_cli" } // will look for `cwd/node_modules/cowsay/.fig/autocomplete/build/cowsay_cli.js` + * { type: "global", path: "~", name: "my_cli" } // will look for `~/.fig/autocomplete/build/my_cli.js` + * ``` + * @irreplaceable + */ + type SpecLocation = + | { type: "local"; path?: string; name: string } + | { type: "global"; name: string }; - /** - * Dynamically load up another completion spec at runtime. - * - * See [`loadSpec` property in Subcommand Object](https://fig.io/docs/reference/subcommand#loadspec). - */ - type LoadSpec = - | string - | Subcommand - | (( - token: string, - executeCommand: ExecuteCommandFunction - ) => Promise); + /** + * Dynamically load up another completion spec at runtime. + * + * See [`loadSpec` property in Subcommand Object](https://fig.io/docs/reference/subcommand#loadspec). + */ + type LoadSpec = + | string + | Subcommand + | (( + token: string, + executeCommand: ExecuteCommandFunction + ) => Promise); - /** - * The type of a suggestion object. - * @remarks - * The type determines: - * - the default icon Fig uses (e.g. a file or folder searches for the system icon, a subcommand has a specific icon etc) - * - whether we allow users to auto-execute a command - */ - type SuggestionType = - | "folder" - | "file" - | "arg" - | "subcommand" - | "option" - | "special" - | "mixin" - | "shortcut"; + /** + * The type of a suggestion object. + * @remarks + * The type determines: + * - the default icon Fig uses (e.g. a file or folder searches for the system icon, a subcommand has a specific icon etc) + * - whether we allow users to auto-execute a command + */ + type SuggestionType = + | "folder" + | "file" + | "arg" + | "subcommand" + | "option" + | "special" + | "mixin" + | "shortcut"; - /** - * A single object of type `T` or an array of objects of type `T`. - */ - type SingleOrArray = T | T[]; + /** + * A single object of type `T` or an array of objects of type `T`. + */ + type SingleOrArray = T | T[]; - /** - * An async function that returns the version of a given CLI tool. - * @remarks - * This is used in completion specs that want to version themselves the same way CLI tools are versioned. See fig.io/docs - * - * @param executeCommand -an async function that allows you to execute a shell command on the user's system and get the output as a string. - * @returns The version of a CLI tool - * - * @example - * `1.0.22` - * - * @example - * `v26` - * - */ - type GetVersionCommand = (executeCommand: ExecuteCommandFunction) => Promise; + /** + * An async function that returns the version of a given CLI tool. + * @remarks + * This is used in completion specs that want to version themselves the same way CLI tools are versioned. See fig.io/docs + * + * @param executeCommand -an async function that allows you to execute a shell command on the user's system and get the output as a string. + * @returns The version of a CLI tool + * + * @example + * `1.0.22` + * + * @example + * `v26` + * + */ + type GetVersionCommand = (executeCommand: ExecuteCommandFunction) => Promise; - /** - * Context about a current shell session. - */ - type ShellContext = { - /** - * The current directory the shell is in - */ - currentWorkingDirectory: string; - /** - * Exported environment variables from the shell - */ - environmentVariables: Record; - /** - * The name of the current process - */ - currentProcess: string; - /** - * @hidden - * @deprecated - */ - sshPrefix: string; - }; + /** + * Context about a current shell session. + */ + type ShellContext = { + /** + * The current directory the shell is in + */ + currentWorkingDirectory: string; + /** + * Exported environment variables from the shell + */ + environmentVariables: Record; + /** + * The name of the current process + */ + currentProcess: string; + /** + * @hidden + * @deprecated + */ + sshPrefix: string; + }; - type GeneratorContext = ShellContext & { - isDangerous?: boolean; - searchTerm: string; - }; + type GeneratorContext = ShellContext & { + isDangerous?: boolean; + searchTerm: string; + }; - /** - * A function which can have a `T` argument and a `R` result. - * @param param - A param of type `R` - * @returns Something of type `R` - */ - type Function = (param: T) => R; + /** + * A function which can have a `T` argument and a `R` result. + * @param param - A param of type `R` + * @returns Something of type `R` + */ + type Function = (param: T) => R; - /** - * A utility type to modify a property type - * @irreplaceable - */ - type Modify = Omit & R; + /** + * A utility type to modify a property type + * @irreplaceable + */ + type Modify = Omit & R; - /** - * A `string` OR a `function` which can have a `T` argument and a `R` result. - * @param param - A param of type `R` - * @returns Something of type `R` - */ - type StringOrFunction = string | Function; + /** + * A `string` OR a `function` which can have a `T` argument and a `R` result. + * @param param - A param of type `R` + * @returns Something of type `R` + */ + type StringOrFunction = string | Function; - /** - * @excluded - * @irreplaceable - */ - type ArgDiff = Modify; + /** + * @excluded + * @irreplaceable + */ + type ArgDiff = Modify; - /** - * @excluded - * @irreplaceable - */ - type OptionDiff = Modify< - Fig.Option, - { - args?: ArgDiff | ArgDiff[]; - remove?: true; - } - >; + /** + * @excluded + * @irreplaceable + */ + type OptionDiff = Modify< + Fig.Option, + { + args?: ArgDiff | ArgDiff[]; + remove?: true; + } + >; - /** - * @excluded - * @irreplaceable - */ - type SubcommandDiff = Modify< - Fig.Subcommand, - { - subcommands?: SubcommandDiff[]; - options?: OptionDiff[]; - args?: ArgDiff | ArgDiff[]; - remove?: true; - } - >; + /** + * @excluded + * @irreplaceable + */ + type SubcommandDiff = Modify< + Fig.Subcommand, + { + subcommands?: SubcommandDiff[]; + options?: OptionDiff[]; + args?: ArgDiff | ArgDiff[]; + remove?: true; + } + >; - /** - * @excluded - * @irreplaceable - */ - type SpecDiff = Omit; + /** + * @excluded + * @irreplaceable + */ + type SpecDiff = Omit; - /** - * @excluded - * @irreplaceable - */ - type VersionDiffMap = Record; + /** + * @excluded + * @irreplaceable + */ + type VersionDiffMap = Record; - /** - * A spec object. - * Can be one of - * 1. A subcommand - * 2. A function that dynamically computes a subcommand - * 3. A function that returns the path to a versioned spec files (that exports a base subcommand and { versions: VersionDiffMap } - */ - type Spec = - | Subcommand - | ((version?: string) => Subcommand) - | ((version?: string) => { - versionedSpecPath: string; - version?: string; - }); + /** + * A spec object. + * Can be one of + * 1. A subcommand + * 2. A function that dynamically computes a subcommand + * 3. A function that returns the path to a versioned spec files (that exports a base subcommand and { versions: VersionDiffMap } + */ + type Spec = + | Subcommand + | ((version?: string) => Subcommand) + | ((version?: string) => { + versionedSpecPath: string; + version?: string; + }); - type ExecuteCommandInput = { - /** - * The command to execute - */ - command: string; - /** - * The arguments to the command to be run - */ - args: string[]; - /** - * The directory to run the command in - */ - cwd?: string; - /** - * The environment variables to set when executing the command, `undefined` will unset the variable if it set - */ - env?: Record; - /** - * Duration of timeout in milliseconds, if the command takes longer than the timeout a error will be thrown. - * @defaultValue 5000 - */ - timeout?: number; - }; + type ExecuteCommandInput = { + /** + * The command to execute + */ + command: string; + /** + * The arguments to the command to be run + */ + args: string[]; + /** + * The directory to run the command in + */ + cwd?: string; + /** + * The environment variables to set when executing the command, `undefined` will unset the variable if it set + */ + env?: Record; + /** + * Duration of timeout in milliseconds, if the command takes longer than the timeout a error will be thrown. + * @defaultValue 5000 + */ + timeout?: number; + }; - /** - * The output of running a command - */ - type ExecuteCommandOutput = { - /** - * The stdout (1) of running a command - */ - stdout: string; - /** - * The stderr (2) of running a command - */ - stderr: string; - /** - * The exit status of running a command - */ - status: number; - }; + /** + * The output of running a command + */ + type ExecuteCommandOutput = { + /** + * The stdout (1) of running a command + */ + stdout: string; + /** + * The stderr (2) of running a command + */ + stderr: string; + /** + * The exit status of running a command + */ + status: number; + }; - /** - * An async function to execute a command - * @returns The output of the command - */ - type ExecuteCommandFunction = (args: ExecuteCommandInput) => Promise; + /** + * An async function to execute a command + * @returns The output of the command + */ + type ExecuteCommandFunction = (args: ExecuteCommandInput) => Promise; - type CacheMaxAge = { - strategy: "max-age"; - /** - * The time to live for the cache in milliseconds. - * @example - * 3600 - */ - ttl: number; - }; + type CacheMaxAge = { + strategy: "max-age"; + /** + * The time to live for the cache in milliseconds. + * @example + * 3600 + */ + ttl: number; + }; - type CacheStaleWhileRevalidate = { - strategy?: "stale-while-revalidate"; - /** - * The time to live for the cache in milliseconds. - * @example - * 3600 - */ - ttl?: number; - }; + type CacheStaleWhileRevalidate = { + strategy?: "stale-while-revalidate"; + /** + * The time to live for the cache in milliseconds. + * @example + * 3600 + */ + ttl?: number; + }; - type Cache = (CacheMaxAge | CacheStaleWhileRevalidate) & { - /** - * Whether the cache should be based on the directory the user was currently in or not. - * @defaultValue false - */ - cacheByDirectory?: boolean; + type Cache = (CacheMaxAge | CacheStaleWhileRevalidate) & { + /** + * Whether the cache should be based on the directory the user was currently in or not. + * @defaultValue false + */ + cacheByDirectory?: boolean; - /** - * Hardcoded cache key that can be used to cache a single generator across - * multiple argument locations in a spec. - */ - cacheKey?: string; - }; + /** + * Hardcoded cache key that can be used to cache a single generator across + * multiple argument locations in a spec. + */ + cacheKey?: string; + }; - type TriggerOnChange = { - /** Trigger on any change to the token */ - on: "change"; - }; + type TriggerOnChange = { + /** Trigger on any change to the token */ + on: "change"; + }; - type TriggerOnThreshold = { - /** Trigger when the length of the token changes past a threshold */ - on: "threshold"; - length: number; - }; + type TriggerOnThreshold = { + /** Trigger when the length of the token changes past a threshold */ + on: "threshold"; + length: number; + }; - type TriggerOnMatch = { - /** Trigger when the index of a string changes */ - on: "match"; - string: string | string[]; - }; + type TriggerOnMatch = { + /** Trigger when the index of a string changes */ + on: "match"; + string: string | string[]; + }; - type Trigger = - | string - | ((newToken: string, oldToken: string) => boolean) - | TriggerOnChange - | TriggerOnThreshold - | TriggerOnMatch; + type Trigger = + | string + | ((newToken: string, oldToken: string) => boolean) + | TriggerOnChange + | TriggerOnThreshold + | TriggerOnMatch; - /** - * The BaseSuggestion object is the root of the Suggestion, Subcommand, and Option objects. - * It is where key properties like description, icon, and displayName are found - * @excluded - */ - interface BaseSuggestion { - /** - * The string that is displayed in the UI for a given suggestion. - * @defaultValue the name prop - * - * @example - * The npm CLI has a subcommand called `install`. If we wanted - * to display some custom text like `Install an NPM package 📦` we would set - * `name: "install"` and `displayName: "Install an NPM package 📦"` - */ - displayName?: string; - /** - * The value that's inserted into the terminal when a user presses enter/tab or clicks on a menu item. - * - * @remarks - * You can use `\n` to insert a newline or `\b` to insert a backspace. - * You can also optionally specify {cursor} in the string and Fig will automatically place the cursor there after insert. - * - * @defaultValue The value of the name prop. - * - * @example - * For the `git commit` subcommand, the `-m` option has an insert value of `-m '{cursor}'` - */ - insertValue?: string; - /** - * When the suggestion is inserted, replace the command with this string - * - * @remarks - * You can use `\n` to insert a newline or `\b` to insert a backspace. - * You can also optionally specify {cursor} in the string and Fig will automatically place the cursor there after insert. - * Note that currently the entire edit buffer will be replaced. Eventually, only the root command will be replaced, preserving pipes and continuations. - */ - replaceValue?: string; - /** - * The text that gets rendered at the bottom of the autocomplete box (or the side if you hit ⌘i) - * - * @example - * "Your commit message" - */ - description?: string; - /** - * The icon that is rendered is based on the type. - * - * @remarks - * Icons can be a 1 character string, a URL, or Fig's [icon protocol](https://fig.io/docs/reference/suggestion/icon-api) (fig://) which lets you generate - * colorful and fun systems icons. - * - * @defaultValue related to the type of the object (e.g. `Suggestion`, `Subcommand`, `Option`, `Arg`) - * - * @example - * `A` - * @example - * `😊` - * @example - * `https://www.herokucdn.com/favicon.ico` - * @example - * `fig://icon?type=file` - * - */ - icon?: string; - /** - * Specifies whether the suggestion is "dangerous". - * - * @remarks - * If true, Fig will not enable its autoexecute functionality. Autoexecute means if a user selects a suggestion it will insert the text and run the command. We signal this by changing the icon to red. - * Setting `isDangerous` to `true` will make it harder for a user to accidentally run a dangerous command. - * - * @defaultValue false - * - * @example - * This is used in the `rm` spec. Why? Because we don't want users to accidentally delete their files so we make it just a little bit harder... - */ - isDangerous?: boolean; - /** - * The number used to rank suggestions in autocomplete. Number must be from 0-100. Higher priorities rank higher. - * - * @defaultValue 50 - * @remarks - * Fig ranks suggestions by recency. To do this, we check if a suggestion has been selected before. If yes and the suggestions has: - * - a priority between 50-75, the priority will be replaced with 75, then we will add the timestamp of when that suggestion was selected as a decimal. - * - a priority outside of 50-75, the priority will be increased by the timestamp of when that suggestion was selected as a decimal. - * If it has not been selected before, Fig will keep the same priority as was set in the completion spec - * If it was not set in the spec, it will default to 50. - * - * @example - * Let's say a user has previously selected a suggestion at unix timestamp 1634087677: - * - If completion spec did not set a priority (Fig treats this as priority 50), its priority would change to 75 + 0.1634087677 = 75.1634087677; - * - If completion spec set a priority of 49 or less, its priority would change to 49 + 0.1634087677 = 49.1634087677; - * - If completion spec set a priority of 76 or more, its priority would change to 76 + 0.1634087677 = 76.1634087677; - * - If a user had never selected a suggestion, then its priority would just stay as is (or if not set, default to 50). - * - * @example - * If you want your suggestions to always be: - * - at the top order, rank them 76 or above. - * - at the bottom, rank them 49 or below - */ - priority?: number; - /** - * Specifies whether a suggestion should be hidden from results. - * @remarks - * Fig will only show it if the user exactly types the name. - * @defaultValue false - * @example - * The "-" suggestion is hidden in the `cd` spec. You will only see it if you type exactly `cd -` - */ - hidden?: boolean; - /** - * - * Specifies whether a suggestion is deprecated. - * @remarks - * It is possible to specify a suggestion to replace the deprecated one. - * - The `description` of the deprecated object (e.g `deprecated: { description: 'The --no-ansi option has been deprecated in v2' }`) is used to provide infos about the deprecation. - * - `deprecated: true` and `deprecated: { }` behave the same and will just display the suggestion as deprecated. - * @example - * ```js - * deprecated: { insertValue: '--ansi never', description: 'The --no-ansi option has been deprecated in v2' } - * ``` - */ - deprecated?: boolean | Omit; + /** + * The BaseSuggestion object is the root of the Suggestion, Subcommand, and Option objects. + * It is where key properties like description, icon, and displayName are found + * @excluded + */ + interface BaseSuggestion { + /** + * The string that is displayed in the UI for a given suggestion. + * @defaultValue the name prop + * + * @example + * The npm CLI has a subcommand called `install`. If we wanted + * to display some custom text like `Install an NPM package 📦` we would set + * `name: "install"` and `displayName: "Install an NPM package 📦"` + */ + displayName?: string; + /** + * The value that's inserted into the terminal when a user presses enter/tab or clicks on a menu item. + * + * @remarks + * You can use `\n` to insert a newline or `\b` to insert a backspace. + * You can also optionally specify {cursor} in the string and Fig will automatically place the cursor there after insert. + * + * @defaultValue The value of the name prop. + * + * @example + * For the `git commit` subcommand, the `-m` option has an insert value of `-m '{cursor}'` + */ + insertValue?: string; + /** + * When the suggestion is inserted, replace the command with this string + * + * @remarks + * You can use `\n` to insert a newline or `\b` to insert a backspace. + * You can also optionally specify {cursor} in the string and Fig will automatically place the cursor there after insert. + * Note that currently the entire edit buffer will be replaced. Eventually, only the root command will be replaced, preserving pipes and continuations. + */ + replaceValue?: string; + /** + * The text that gets rendered at the bottom of the autocomplete box (or the side if you hit ⌘i) + * + * @example + * "Your commit message" + */ + description?: string; + /** + * The icon that is rendered is based on the type. + * + * @remarks + * Icons can be a 1 character string, a URL, or Fig's [icon protocol](https://fig.io/docs/reference/suggestion/icon-api) (fig://) which lets you generate + * colorful and fun systems icons. + * + * @defaultValue related to the type of the object (e.g. `Suggestion`, `Subcommand`, `Option`, `Arg`) + * + * @example + * `A` + * @example + * `😊` + * @example + * `https://www.herokucdn.com/favicon.ico` + * @example + * `fig://icon?type=file` + * + */ + icon?: string; + /** + * Specifies whether the suggestion is "dangerous". + * + * @remarks + * If true, Fig will not enable its autoexecute functionality. Autoexecute means if a user selects a suggestion it will insert the text and run the command. We signal this by changing the icon to red. + * Setting `isDangerous` to `true` will make it harder for a user to accidentally run a dangerous command. + * + * @defaultValue false + * + * @example + * This is used in the `rm` spec. Why? Because we don't want users to accidentally delete their files so we make it just a little bit harder... + */ + isDangerous?: boolean; + /** + * The number used to rank suggestions in autocomplete. Number must be from 0-100. Higher priorities rank higher. + * + * @defaultValue 50 + * @remarks + * Fig ranks suggestions by recency. To do this, we check if a suggestion has been selected before. If yes and the suggestions has: + * - a priority between 50-75, the priority will be replaced with 75, then we will add the timestamp of when that suggestion was selected as a decimal. + * - a priority outside of 50-75, the priority will be increased by the timestamp of when that suggestion was selected as a decimal. + * If it has not been selected before, Fig will keep the same priority as was set in the completion spec + * If it was not set in the spec, it will default to 50. + * + * @example + * Let's say a user has previously selected a suggestion at unix timestamp 1634087677: + * - If completion spec did not set a priority (Fig treats this as priority 50), its priority would change to 75 + 0.1634087677 = 75.1634087677; + * - If completion spec set a priority of 49 or less, its priority would change to 49 + 0.1634087677 = 49.1634087677; + * - If completion spec set a priority of 76 or more, its priority would change to 76 + 0.1634087677 = 76.1634087677; + * - If a user had never selected a suggestion, then its priority would just stay as is (or if not set, default to 50). + * + * @example + * If you want your suggestions to always be: + * - at the top order, rank them 76 or above. + * - at the bottom, rank them 49 or below + */ + priority?: number; + /** + * Specifies whether a suggestion should be hidden from results. + * @remarks + * Fig will only show it if the user exactly types the name. + * @defaultValue false + * @example + * The "-" suggestion is hidden in the `cd` spec. You will only see it if you type exactly `cd -` + */ + hidden?: boolean; + /** + * + * Specifies whether a suggestion is deprecated. + * @remarks + * It is possible to specify a suggestion to replace the deprecated one. + * - The `description` of the deprecated object (e.g `deprecated: { description: 'The --no-ansi option has been deprecated in v2' }`) is used to provide infos about the deprecation. + * - `deprecated: true` and `deprecated: { }` behave the same and will just display the suggestion as deprecated. + * @example + * ```js + * deprecated: { insertValue: '--ansi never', description: 'The --no-ansi option has been deprecated in v2' } + * ``` + */ + deprecated?: boolean | Omit; - /** - * Specifies which component to use to render the preview window. - * - * @remarks This should be the path within the `src` directory to the component without the extension. - * - * @example 'ls/filepathPreview' - */ - previewComponent?: string; + /** + * Specifies which component to use to render the preview window. + * + * @remarks This should be the path within the `src` directory to the component without the extension. + * + * @example 'ls/filepathPreview' + */ + previewComponent?: string; - /** - * This is a way to pass data to the Autocomplete Engine that is not formalized in the spec, do not use this in specs as it may change at any time - * - * @ignore - */ - _internal?: Record; - } + /** + * This is a way to pass data to the Autocomplete Engine that is not formalized in the spec, do not use this in specs as it may change at any time + * + * @ignore + */ + _internal?: Record; + } - /** - * Each item in Fig's autocomplete popup window is a Suggestion object. It is probably the most important object in Fig. - * Subcommand and Option objects compile down to Suggestion objects. Generators return Suggestion objects. - * The main things you can customize in your suggestion object is the text that's displayed, the icon, and what's inserted after being selected. In saying that, most of these have very sane defaults. - */ - interface Suggestion extends BaseSuggestion { - /** - * The string Fig uses when filtering over a list of suggestions to check for a match. - * @remarks - * When a a user is typing in the terminal, the query term (the token they are currently typing) filters over all suggestions in a list by checking if the queryTerm matches the prefix of the name. - * The `displayName` prop also defaults to the value of name. - * - * The `name` props of suggestion, subcommand, option, and arg objects are all different. It's important to read them all carefully. - * - * @example - * If a user types git `c`, any Suggestion objects with a name prop that has a value starting with "c" will match. - * - */ - name?: SingleOrArray; - /** - * The type of a suggestion object. - * @remarks - * The type determines - * - the default icon Fig uses (e.g. a file or folder searches for the system icon, a subcommand has a specific icon etc) - * - whether we allow users to auto-execute a command - */ - type?: SuggestionType; - } + /** + * Each item in Fig's autocomplete popup window is a Suggestion object. It is probably the most important object in Fig. + * Subcommand and Option objects compile down to Suggestion objects. Generators return Suggestion objects. + * The main things you can customize in your suggestion object is the text that's displayed, the icon, and what's inserted after being selected. In saying that, most of these have very sane defaults. + */ + interface Suggestion extends BaseSuggestion { + /** + * The string Fig uses when filtering over a list of suggestions to check for a match. + * @remarks + * When a a user is typing in the terminal, the query term (the token they are currently typing) filters over all suggestions in a list by checking if the queryTerm matches the prefix of the name. + * The `displayName` prop also defaults to the value of name. + * + * The `name` props of suggestion, subcommand, option, and arg objects are all different. It's important to read them all carefully. + * + * @example + * If a user types git `c`, any Suggestion objects with a name prop that has a value starting with "c" will match. + * + */ + name?: SingleOrArray; + /** + * The type of a suggestion object. + * @remarks + * The type determines + * - the default icon Fig uses (e.g. a file or folder searches for the system icon, a subcommand has a specific icon etc) + * - whether we allow users to auto-execute a command + */ + type?: SuggestionType; + } - /** - * The subcommand object represent the tree structure of a completion spec. We sometimes also call it the skeleton. - * - * A subcommand can nest options, arguments, and more subcommands (it's recursive) - */ - interface Subcommand extends BaseSuggestion { - /** - * The name of the subcommand. Should exactly match the name defined by the CLI tool. - * - * @remarks - * If a subcommand has multiple aliases, they should be included as an array. - * - * Note that Fig's autocomplete engine requires this `name` to match the text typed by the user in the shell. - * - * To customize the title that is displayed to the user, use `displayName`. - * - * - * @example - * For `git checkout`, the subcommand `checkout` would have `name: "checkout"` - * @example - * For `npm install`, the subcommand `install` would have `name: ["install", "i"]` as these two values both represent the same subcommand. - */ - name: SingleOrArray; + /** + * The subcommand object represent the tree structure of a completion spec. We sometimes also call it the skeleton. + * + * A subcommand can nest options, arguments, and more subcommands (it's recursive) + */ + interface Subcommand extends BaseSuggestion { + /** + * The name of the subcommand. Should exactly match the name defined by the CLI tool. + * + * @remarks + * If a subcommand has multiple aliases, they should be included as an array. + * + * Note that Fig's autocomplete engine requires this `name` to match the text typed by the user in the shell. + * + * To customize the title that is displayed to the user, use `displayName`. + * + * + * @example + * For `git checkout`, the subcommand `checkout` would have `name: "checkout"` + * @example + * For `npm install`, the subcommand `install` would have `name: ["install", "i"]` as these two values both represent the same subcommand. + */ + name: SingleOrArray; - /** - * An array of `Subcommand` objects representing all the subcommands that exist beneath the current command. - * * - * To support large CLI tools, `Subcommands` can be nested recursively. - * - * @example - * A CLI tool like `aws` is composed of many top-level subcommands (`s3`, `ec2`, `eks`...), each of which include child subcommands of their own. - */ - subcommands?: Subcommand[]; + /** + * An array of `Subcommand` objects representing all the subcommands that exist beneath the current command. + * * + * To support large CLI tools, `Subcommands` can be nested recursively. + * + * @example + * A CLI tool like `aws` is composed of many top-level subcommands (`s3`, `ec2`, `eks`...), each of which include child subcommands of their own. + */ + subcommands?: Subcommand[]; - /** - * Specifies whether the command requires a subcommand. This is false by default. - * - * A space will always be inserted after this command if `requiresSubcommand` is true. - * If the property is omitted, a space will be inserted if there is at least one required argument. - */ - requiresSubcommand?: boolean; + /** + * Specifies whether the command requires a subcommand. This is false by default. + * + * A space will always be inserted after this command if `requiresSubcommand` is true. + * If the property is omitted, a space will be inserted if there is at least one required argument. + */ + requiresSubcommand?: boolean; - /** - * An array of `Option` objects representing the options that are available on this subcommand. - * - * @example - * A command like `git commit` accepts various flags and options, such as `--message` and `--all`. These `Option` objects would be included in the `options` field. - */ - options?: Option[]; + /** + * An array of `Option` objects representing the options that are available on this subcommand. + * + * @example + * A command like `git commit` accepts various flags and options, such as `--message` and `--all`. These `Option` objects would be included in the `options` field. + */ + options?: Option[]; - /** - * An array of `Arg` objects representing the various parameters or "arguments" that can be passed to this subcommand. - * - */ - args?: SingleOrArray; - /** - * This option allows to enforce the suggestion filtering strategy for a specific subcommand. - * @remarks - * Users always want to have the most accurate results at the top of the suggestions list. - * For example we can enable fuzzy search on a subcommand that always requires fuzzy search to show the best suggestions. - * This property is also useful when subcommands or options have a prefix (e.g. the npm package scope) because enabling fuzzy search users can omit that part (see the second example below) - * @example - * yarn workspace [name] with fuzzy search is way more useful since we can omit the npm package scope - * @example - * fig settings uses fuzzy search to prevent having to add the `autocomplete.` prefix to each searched setting - * ```typescript - * const figSpec: Fig.Spec { - * name: "fig", - * subcommands: [ - * { - * name: "settings", - * filterStrategy: "fuzzy", - * subcommands: [ - * { - * name: "autocomplete.theme", // if a user writes `fig settings theme` it gets the correct suggestions - * }, - * // ... other settings - * ] - * }, - * // ... other fig subcommands - * ] - * } - * ``` - */ - filterStrategy?: "fuzzy" | "prefix" | "default"; - /** - * A list of Suggestion objects that are appended to the suggestions shown beneath a subcommand. - * - * @remarks - * You can use this field to suggest common workflows. - * - */ - additionalSuggestions?: (string | Suggestion)[]; - /** - * Dynamically load another completion spec at runtime. - * - * @param tokens - a tokenized array of the text the user has typed in the shell. - * @param executeCommand - an async function that can execute a shell command on behalf of the user. The output is a string. - * @returns A `SpecLocation` object or an array of `SpecLocation` objects. - * - * @remarks - * `loadSpec` can be invoked as string (recommended) or a function (advanced). - * - * The API tells the autocomplete engine where to look for a completion spec. If you pass a string, the engine will attempt to locate a matching spec that is hosted by Fig. - * - * @example - * Suppose you have an internal CLI tool that wraps `kubectl`. Instead of copying the `kubectl` completion spec, you can include the spec at runtime. - * ```typescript - * { - * name: "kube", - * description: "a wrapper around kubectl" - * loadSpec: "kubectl" - * } - * ``` - * @example - * In the `aws` completion spec, `loadSpec` is used to optimize performance. The completion spec is split into multiple files, each of which can be loaded separately. - * ```typescript - * { - * name: "s3", - * loadSpec: "aws/s3" - * } - * ``` - */ - loadSpec?: LoadSpec; - /** - * Dynamically *generate* a `Subcommand` object a runtime. The generated `Subcommand` is merged with the current subcommand. - * - * @remarks - * This API is often used by CLI tools where the structure of the CLI tool is not *static*. For instance, if the tool can be extended by plugins or otherwise shows different subcommands or options depending on the environment. - * - * @param tokens - a tokenized array of the text the user has typed in the shell. - * @param executeCommand - an async function that can execute a shell command on behalf of the user. The output is a string. - * @returns a `Fig.Spec` object - * - * @example - * The `python` spec uses `generateSpec` to include the`django-admin` spec if `django manage.py` exists. - * ```typescript - * generateSpec: async (tokens, executeCommand) => { - * // Load the contents of manage.py - * const managePyContents = await executeCommand("cat manage.py"); - * // Heuristic to determine if project uses django - * if (managePyContents.contains("django")) { - * return { - * name: "python", - * subcommands: [{ name: "manage.py", loadSpec: "django-admin" }], - * }; - * } - * }, - * ``` - */ - generateSpec?: (tokens: string[], executeCommand: ExecuteCommandFunction) => Promise; + /** + * An array of `Arg` objects representing the various parameters or "arguments" that can be passed to this subcommand. + * + */ + args?: SingleOrArray; + /** + * This option allows to enforce the suggestion filtering strategy for a specific subcommand. + * @remarks + * Users always want to have the most accurate results at the top of the suggestions list. + * For example we can enable fuzzy search on a subcommand that always requires fuzzy search to show the best suggestions. + * This property is also useful when subcommands or options have a prefix (e.g. the npm package scope) because enabling fuzzy search users can omit that part (see the second example below) + * @example + * yarn workspace [name] with fuzzy search is way more useful since we can omit the npm package scope + * @example + * fig settings uses fuzzy search to prevent having to add the `autocomplete.` prefix to each searched setting + * ```typescript + * const figSpec: Fig.Spec { + * name: "fig", + * subcommands: [ + * { + * name: "settings", + * filterStrategy: "fuzzy", + * subcommands: [ + * { + * name: "autocomplete.theme", // if a user writes `fig settings theme` it gets the correct suggestions + * }, + * // ... other settings + * ] + * }, + * // ... other fig subcommands + * ] + * } + * ``` + */ + filterStrategy?: "fuzzy" | "prefix" | "default"; + /** + * A list of Suggestion objects that are appended to the suggestions shown beneath a subcommand. + * + * @remarks + * You can use this field to suggest common workflows. + * + */ + additionalSuggestions?: (string | Suggestion)[]; + /** + * Dynamically load another completion spec at runtime. + * + * @param tokens - a tokenized array of the text the user has typed in the shell. + * @param executeCommand - an async function that can execute a shell command on behalf of the user. The output is a string. + * @returns A `SpecLocation` object or an array of `SpecLocation` objects. + * + * @remarks + * `loadSpec` can be invoked as string (recommended) or a function (advanced). + * + * The API tells the autocomplete engine where to look for a completion spec. If you pass a string, the engine will attempt to locate a matching spec that is hosted by Fig. + * + * @example + * Suppose you have an internal CLI tool that wraps `kubectl`. Instead of copying the `kubectl` completion spec, you can include the spec at runtime. + * ```typescript + * { + * name: "kube", + * description: "a wrapper around kubectl" + * loadSpec: "kubectl" + * } + * ``` + * @example + * In the `aws` completion spec, `loadSpec` is used to optimize performance. The completion spec is split into multiple files, each of which can be loaded separately. + * ```typescript + * { + * name: "s3", + * loadSpec: "aws/s3" + * } + * ``` + */ + loadSpec?: LoadSpec; + /** + * Dynamically *generate* a `Subcommand` object a runtime. The generated `Subcommand` is merged with the current subcommand. + * + * @remarks + * This API is often used by CLI tools where the structure of the CLI tool is not *static*. For instance, if the tool can be extended by plugins or otherwise shows different subcommands or options depending on the environment. + * + * @param tokens - a tokenized array of the text the user has typed in the shell. + * @param executeCommand - an async function that can execute a shell command on behalf of the user. The output is a string. + * @returns a `Fig.Spec` object + * + * @example + * The `python` spec uses `generateSpec` to include the`django-admin` spec if `django manage.py` exists. + * ```typescript + * generateSpec: async (tokens, executeCommand) => { + * // Load the contents of manage.py + * const managePyContents = await executeCommand("cat manage.py"); + * // Heuristic to determine if project uses django + * if (managePyContents.contains("django")) { + * return { + * name: "python", + * subcommands: [{ name: "manage.py", loadSpec: "django-admin" }], + * }; + * } + * }, + * ``` + */ + generateSpec?: (tokens: string[], executeCommand: ExecuteCommandFunction) => Promise; - /** - * Generating a spec can be expensive, but due to current guarantees they are not cached. - * This function generates a cache key which is used to cache the result of generateSpec. - * If `undefined` is returned, the cache will not be used. - */ - generateSpecCacheKey?: Function<{ tokens: string[] }, string | undefined> | string; + /** + * Generating a spec can be expensive, but due to current guarantees they are not cached. + * This function generates a cache key which is used to cache the result of generateSpec. + * If `undefined` is returned, the cache will not be used. + */ + generateSpecCacheKey?: Function<{ tokens: string[] }, string | undefined> | string; - /** - * Configure how the autocomplete engine will map the raw tokens to a given completion spec. - * - * @param flagsArePosixNoncompliant - Indicates that flags with one hyphen may have *more* than one character. Enabling this directive, turns off support for option chaining. - * @param optionsMustPrecedeArguments - Options will not be suggested after any argument of the Subcommand has been typed. - * @param optionArgSeparators - Indicate that options which take arguments will require one of the specified separators between the 'verbose' option name and the argument. - * - * @example - * The `-work` option from the `go` spec is parsed as a single flag when `parserDirectives.flagsArePosixNoncompliant` is set to true. Normally, this would be chained and parsed as `-w -o -r -k` if `flagsArePosixNoncompliant` is not set to true. - */ - parserDirectives?: { - flagsArePosixNoncompliant?: boolean; - optionsMustPrecedeArguments?: boolean; - optionArgSeparators?: SingleOrArray; - }; + /** + * Configure how the autocomplete engine will map the raw tokens to a given completion spec. + * + * @param flagsArePosixNoncompliant - Indicates that flags with one hyphen may have *more* than one character. Enabling this directive, turns off support for option chaining. + * @param optionsMustPrecedeArguments - Options will not be suggested after any argument of the Subcommand has been typed. + * @param optionArgSeparators - Indicate that options which take arguments will require one of the specified separators between the 'verbose' option name and the argument. + * + * @example + * The `-work` option from the `go` spec is parsed as a single flag when `parserDirectives.flagsArePosixNoncompliant` is set to true. Normally, this would be chained and parsed as `-w -o -r -k` if `flagsArePosixNoncompliant` is not set to true. + */ + parserDirectives?: { + flagsArePosixNoncompliant?: boolean; + optionsMustPrecedeArguments?: boolean; + optionArgSeparators?: SingleOrArray; + }; - /** - * Specifies whether or not to cache the result of loadSpec and generateSpec - * - * @remarks - * Caching is good because it reduces the time to completion on subsequent calls to a dynamic subcommand, but when the data does not outlive the cache this allows a mechanism for opting out of it. - */ - cache?: boolean; - } + /** + * Specifies whether or not to cache the result of loadSpec and generateSpec + * + * @remarks + * Caching is good because it reduces the time to completion on subsequent calls to a dynamic subcommand, but when the data does not outlive the cache this allows a mechanism for opting out of it. + */ + cache?: boolean; + } - /** - * The option object represent CLI options (sometimes called flags). - * - * A option can have an argument. An option can NOT have subcommands or other option - */ - interface Option extends BaseSuggestion { - /** - * The exact name of the subcommand as defined in the CLI tool. - * - * @remarks - * Fig's parser relies on your option name being exactly what the user would type. (e.g. if the user types `git "-m"`, you must have `name: "-m"` and not something like `name: "your message"` or even with an `=` sign like`name: "-m="`) - * - * If you want to customize what the text the popup says, use `displayName`. - * - * The name prop in an Option object compiles down to the name prop in a Suggestion object - * - * Final note: the name prop can be a string (most common) or an array of strings - * - * - * @example - * For `git commit -m` in the, message option nested beneath `commit` would have `name: ["-m", "--message"]` - * @example - * For `ls -l` the `-l` option would have `name: "-l"` - */ - name: SingleOrArray; + /** + * The option object represent CLI options (sometimes called flags). + * + * A option can have an argument. An option can NOT have subcommands or other option + */ + interface Option extends BaseSuggestion { + /** + * The exact name of the subcommand as defined in the CLI tool. + * + * @remarks + * Fig's parser relies on your option name being exactly what the user would type. (e.g. if the user types `git "-m"`, you must have `name: "-m"` and not something like `name: "your message"` or even with an `=` sign like`name: "-m="`) + * + * If you want to customize what the text the popup says, use `displayName`. + * + * The name prop in an Option object compiles down to the name prop in a Suggestion object + * + * Final note: the name prop can be a string (most common) or an array of strings + * + * + * @example + * For `git commit -m` in the, message option nested beneath `commit` would have `name: ["-m", "--message"]` + * @example + * For `ls -l` the `-l` option would have `name: "-l"` + */ + name: SingleOrArray; - /** - * An array of arg objects or a single arg object - * - * @remarks - * If a subcommand takes an argument, please at least include an empty Arg Object. (e.g. `{ }`). Why? If you don't, Fig will assume the subcommand does not take an argument. When the user types their argument - * If the argument is optional, signal this by saying `isOptional: true`. - * - * @example - * `npm run` takes one mandatory argument. This can be represented by `args: { }` - * @example - * `git push` takes two optional arguments. This can be represented by: `args: [{ isOptional: true }, { isOptional: true }]` - * @example - * `git clone` takes one mandatory argument and one optional argument. This can be represented by: `args: [{ }, { isOptional: true }]` - */ - args?: SingleOrArray; - /** - * - * Signals whether an option is persistent, meaning that it will still be available - * as an option for all child subcommands. - * - * @remarks - * As of now there is no way to disable this - * persistence for certain children. Also see - * https://github.com/spf13/cobra/blob/master/user_guide.md#persistent-flags. - * - * @defaultValue false - * - * @example - * Say the `git` spec had an option at the top level with `{ name: "--help", isPersistent: true }`. - * Then the spec would recognize both `git --help` and `git commit --help` - * as a valid as we are passing the `--help` option to all `git` subcommands. - * - */ - isPersistent?: boolean; - /** - * Signals whether an option is required. - * - * @defaultValue false (option is NOT required) - * @example - * The `-m` option of `git commit` is required - * - */ - isRequired?: boolean; - /** - * - * Signals whether an equals sign is required to pass an argument to an option (e.g. `git commit --message="msg"`) - * @defaultValue false (does NOT require an equal) - * - * @example - * When `requiresEqual: true` the user MUST do `--opt=value` and cannot do `--opt value` - * - * @deprecated use `requiresSeparator` instead - * - */ - requiresEquals?: boolean; - /** - * - * Signals whether one of the separators specified in parserDirectives is required to pass an argument to an option (e.g. `git commit --message[separator]"msg"`) - * If set to true this will automatically insert an equal after the option name. - * If set to a separator (string) this will automatically insert the separator specified after the option name. - * @defaultValue false (does NOT require a separator) - * - * @example - * When `requiresSeparator: true` the user MUST do `--opt=value` and cannot do `--opt value` - * @example - * When `requiresSeparator: ':'` the user MUST do `--opt:value` and cannot do `--opt value` - */ - requiresSeparator?: boolean | string; - /** - * - * Signals whether an option can be passed multiple times. - * - * @defaultValue false (option is NOT repeatable) - * - * @remarks - * Passing `isRepeatable: true` will allow an option to be passed any number - * of times, while passing `isRepeatable: 2` will allow it to be passed - * twice, etc. Passing `isRepeatable: false` is the same as passing - * `isRepeatable: 1`. - * - * If you explicitly specify the isRepeatable option in a spec, this - * constraint will be enforced at the parser level, meaning after the option - * (say `-o`) has been passed the maximum number of times, Fig's parser will - * not recognize `-o` as an option if the user types it again. - * - * @example - * In `npm install` doesn't specify `isRepeatable` for `{ name: ["-D", "--save-dev"] }`. - * When the user types `npm install -D`, Fig will no longer suggest `-D`. - * If the user types `npm install -D -D`. Fig will still parse the second - * `-D` as an option. - * - * Suppose `npm install` explicitly specified `{ name: ["-D", "--save-dev"], isRepeatable: false }`. - * Now if the user types `npm install -D -D`, Fig will instead parse the second - * `-D` as the argument to the `install` subcommand instead of as an option. - * - * @example - * SSH has `{ name: "-v", isRepeatable: 3 }`. When the user types `ssh -vv`, Fig - * will still suggest `-v`, when the user types `ssh -vvv` Fig will stop - * suggesting `-v` as an option. Finally if the user types `ssh -vvvv` Fig's - * parser will recognize that this is not a valid string of chained options - * and will treat this as an argument to `ssh`. - * - */ - isRepeatable?: boolean | number; - /** - * - * Signals whether an option is mutually exclusive with other options (ie if the user has this option, Fig should not show the options specified). - * @defaultValue false - * - * @remarks - * Options that are mutually exclusive with flags the user has already passed will not be shown in the suggestions list. - * - * @example - * You might see `[-a | --interactive | --patch]` in a man page. This means each of these options are mutually exclusive on each other. - * If we were defining the exclusive prop of the "-a" option, then we would have `exclusive: ["--interactive", "--patch"]` - * - */ - exclusiveOn?: string[]; - /** - * - * - * Signals whether an option depends on other options (ie if the user has this option, Fig should only show these options until they are all inserted). - * - * @defaultValue false - * - * @remarks - * If the user has an unmet dependency for a flag they've already typed, this dependency will have boosted priority in the suggestion list. - * - * @example - * In a tool like firebase, we may want to delete a specific extension. The command might be `firebase delete --project ABC --extension 123` This would mean we delete the 123 extension from the ABC project. - * In this case, `--extension` dependsOn `--project` - * - */ - dependsOn?: string[]; - } + /** + * An array of arg objects or a single arg object + * + * @remarks + * If a subcommand takes an argument, please at least include an empty Arg Object. (e.g. `{ }`). Why? If you don't, Fig will assume the subcommand does not take an argument. When the user types their argument + * If the argument is optional, signal this by saying `isOptional: true`. + * + * @example + * `npm run` takes one mandatory argument. This can be represented by `args: { }` + * @example + * `git push` takes two optional arguments. This can be represented by: `args: [{ isOptional: true }, { isOptional: true }]` + * @example + * `git clone` takes one mandatory argument and one optional argument. This can be represented by: `args: [{ }, { isOptional: true }]` + */ + args?: SingleOrArray; + /** + * + * Signals whether an option is persistent, meaning that it will still be available + * as an option for all child subcommands. + * + * @remarks + * As of now there is no way to disable this + * persistence for certain children. Also see + * https://github.com/spf13/cobra/blob/master/user_guide.md#persistent-flags. + * + * @defaultValue false + * + * @example + * Say the `git` spec had an option at the top level with `{ name: "--help", isPersistent: true }`. + * Then the spec would recognize both `git --help` and `git commit --help` + * as a valid as we are passing the `--help` option to all `git` subcommands. + * + */ + isPersistent?: boolean; + /** + * Signals whether an option is required. + * + * @defaultValue false (option is NOT required) + * @example + * The `-m` option of `git commit` is required + * + */ + isRequired?: boolean; + /** + * + * Signals whether an equals sign is required to pass an argument to an option (e.g. `git commit --message="msg"`) + * @defaultValue false (does NOT require an equal) + * + * @example + * When `requiresEqual: true` the user MUST do `--opt=value` and cannot do `--opt value` + * + * @deprecated use `requiresSeparator` instead + * + */ + requiresEquals?: boolean; + /** + * + * Signals whether one of the separators specified in parserDirectives is required to pass an argument to an option (e.g. `git commit --message[separator]"msg"`) + * If set to true this will automatically insert an equal after the option name. + * If set to a separator (string) this will automatically insert the separator specified after the option name. + * @defaultValue false (does NOT require a separator) + * + * @example + * When `requiresSeparator: true` the user MUST do `--opt=value` and cannot do `--opt value` + * @example + * When `requiresSeparator: ':'` the user MUST do `--opt:value` and cannot do `--opt value` + */ + requiresSeparator?: boolean | string; + /** + * + * Signals whether an option can be passed multiple times. + * + * @defaultValue false (option is NOT repeatable) + * + * @remarks + * Passing `isRepeatable: true` will allow an option to be passed any number + * of times, while passing `isRepeatable: 2` will allow it to be passed + * twice, etc. Passing `isRepeatable: false` is the same as passing + * `isRepeatable: 1`. + * + * If you explicitly specify the isRepeatable option in a spec, this + * constraint will be enforced at the parser level, meaning after the option + * (say `-o`) has been passed the maximum number of times, Fig's parser will + * not recognize `-o` as an option if the user types it again. + * + * @example + * In `npm install` doesn't specify `isRepeatable` for `{ name: ["-D", "--save-dev"] }`. + * When the user types `npm install -D`, Fig will no longer suggest `-D`. + * If the user types `npm install -D -D`. Fig will still parse the second + * `-D` as an option. + * + * Suppose `npm install` explicitly specified `{ name: ["-D", "--save-dev"], isRepeatable: false }`. + * Now if the user types `npm install -D -D`, Fig will instead parse the second + * `-D` as the argument to the `install` subcommand instead of as an option. + * + * @example + * SSH has `{ name: "-v", isRepeatable: 3 }`. When the user types `ssh -vv`, Fig + * will still suggest `-v`, when the user types `ssh -vvv` Fig will stop + * suggesting `-v` as an option. Finally if the user types `ssh -vvvv` Fig's + * parser will recognize that this is not a valid string of chained options + * and will treat this as an argument to `ssh`. + * + */ + isRepeatable?: boolean | number; + /** + * + * Signals whether an option is mutually exclusive with other options (ie if the user has this option, Fig should not show the options specified). + * @defaultValue false + * + * @remarks + * Options that are mutually exclusive with flags the user has already passed will not be shown in the suggestions list. + * + * @example + * You might see `[-a | --interactive | --patch]` in a man page. This means each of these options are mutually exclusive on each other. + * If we were defining the exclusive prop of the "-a" option, then we would have `exclusive: ["--interactive", "--patch"]` + * + */ + exclusiveOn?: string[]; + /** + * + * + * Signals whether an option depends on other options (ie if the user has this option, Fig should only show these options until they are all inserted). + * + * @defaultValue false + * + * @remarks + * If the user has an unmet dependency for a flag they've already typed, this dependency will have boosted priority in the suggestion list. + * + * @example + * In a tool like firebase, we may want to delete a specific extension. The command might be `firebase delete --project ABC --extension 123` This would mean we delete the 123 extension from the ABC project. + * In this case, `--extension` dependsOn `--project` + * + */ + dependsOn?: string[]; + } - /** - * The arg object represent CLI arguments (sometimes called positional arguments). - * - * An argument is different to a subcommand object and option object. It does not compile down to a suggestion object. Rather, it represents custom user input. If you want to generate suggestions for this custom user input, you should use the generator prop nested beneath an Arg object - */ - interface Arg { - /** - * The name of an argument. This is different to the `name` prop for subcommands, options, and suggestion objects so please read carefully. - * This `name` prop signals a normal, human readable string. It usually signals to the user the type of argument they are inserting if there are no available suggestions. - * Unlike subcommands and options, Fig does NOT use this value for parsing. Therefore, it can be whatever you want. - * - * @example - * The name prop for the `git commit -m ` arg object is "msg". But you could also make it "message" or "your message". It is only used for description purposes (you see it when you type the message), not for parsing! - */ - name?: string; + /** + * The arg object represent CLI arguments (sometimes called positional arguments). + * + * An argument is different to a subcommand object and option object. It does not compile down to a suggestion object. Rather, it represents custom user input. If you want to generate suggestions for this custom user input, you should use the generator prop nested beneath an Arg object + */ + interface Arg { + /** + * The name of an argument. This is different to the `name` prop for subcommands, options, and suggestion objects so please read carefully. + * This `name` prop signals a normal, human readable string. It usually signals to the user the type of argument they are inserting if there are no available suggestions. + * Unlike subcommands and options, Fig does NOT use this value for parsing. Therefore, it can be whatever you want. + * + * @example + * The name prop for the `git commit -m ` arg object is "msg". But you could also make it "message" or "your message". It is only used for description purposes (you see it when you type the message), not for parsing! + */ + name?: string; - /** - * The text that gets rendered at the bottom of the autocomplete box a) when the user is inputting an argument and there are no suggestions and b) for all generated suggestions for an argument - * Keep it short and direct! - * - * @example - * "Your commit message" - */ - description?: string; + /** + * The text that gets rendered at the bottom of the autocomplete box a) when the user is inputting an argument and there are no suggestions and b) for all generated suggestions for an argument + * Keep it short and direct! + * + * @example + * "Your commit message" + */ + description?: string; - /** - * Specifies whether the suggestions generated for this argument are "dangerous". - * - * @remarks - * If true, Fig will not enable its autoexecute functionality. Autoexecute means if a user selects a suggestion it will insert the text and run the command. We signal this by changing the icon to red. - * Turning on isDangerous will make it harder for a user to accidentally run a dangerous command. - * - * @defaultValue false - * - * @example - * This is used for all arguments in the `rm` spec. - */ - isDangerous?: boolean; + /** + * Specifies whether the suggestions generated for this argument are "dangerous". + * + * @remarks + * If true, Fig will not enable its autoexecute functionality. Autoexecute means if a user selects a suggestion it will insert the text and run the command. We signal this by changing the icon to red. + * Turning on isDangerous will make it harder for a user to accidentally run a dangerous command. + * + * @defaultValue false + * + * @example + * This is used for all arguments in the `rm` spec. + */ + isDangerous?: boolean; - /** - * A list of Suggestion objects that are shown when a user is typing an argument. - * - * @remarks - * These suggestions are static meaning you know them beforehand and they are not generated at runtime. If you want to generate suggestions at runtime, use a generator - * - * @example - * For `git reset `, a two common arguments to pass are "head" and "head^". Therefore, the spec suggests both of these by using the suggestion prop - */ - suggestions?: (string | Suggestion)[]; - /** - * A template which is a single TemplateString or an array of TemplateStrings - * - * @remarks - * Templates are generators prebuilt by Fig. Here are the three templates: - * - filepaths: show folders and filepaths. Allow autoexecute on filepaths - * - folders: show folders only. Allow autoexecute on folders - * - history: show suggestions for all items in history matching this pattern - * - help: show subcommands. Only includes the 'siblings' of the nearest 'parent' subcommand - * - * @example - * `cd` uses the "folders" template - * @example - * `ls` used ["filepaths", "folders"]. Why both? Because if I `ls` a directory, we want to enable a user to autoexecute on this directory. If we just did "filepaths" they couldn't autoexecute. - * - */ - template?: Template; - /** - * - * Generators let you dynamically generate suggestions for arguments by running shell commands on a user's device. - * - * This takes a single generator or an array of generators - */ - generators?: SingleOrArray; - /** - * This option allows to enforce the suggestion filtering strategy for a specific argument suggestions. - * @remarks - * Users always want to have the most accurate results at the top of the suggestions list. - * For example we can enable fuzzy search on an argument that always requires fuzzy search to show the best suggestions. - * This property is also useful when argument suggestions have a prefix (e.g. the npm package scope) because enabling fuzzy search users can omit that part (see the second example below) - * @example - * npm uninstall [packages...] uses fuzzy search to allow searching for installed packages ignoring the package scope - * ```typescript - * const figSpec: Fig.Spec { - * name: "npm", - * subcommands: [ - * { - * args: { - * name: "packages", - * filterStrategy: "fuzzy", // search in suggestions provided by the generator (in this case) using fuzzy search - * generators: generateNpmDeps, - * isVariadic: true, - * }, - * }, - * // ... other npm commands - * ], - * } - * ``` - */ - filterStrategy?: "fuzzy" | "prefix" | "default"; - /** - * Provide a suggestion at the top of the list with the current token that is being typed by the user. - */ - suggestCurrentToken?: boolean; - /** - * Specifies that the argument is variadic and therefore repeats infinitely. - * - * @remarks - * Man pages represent variadic arguments with an ellipsis e.g. `git add ` - * - * @example - * `echo` takes a variadic argument (`echo hello world ...`) - * @example - * `git add` also takes a variadic argument - */ - isVariadic?: boolean; + /** + * A list of Suggestion objects that are shown when a user is typing an argument. + * + * @remarks + * These suggestions are static meaning you know them beforehand and they are not generated at runtime. If you want to generate suggestions at runtime, use a generator + * + * @example + * For `git reset `, a two common arguments to pass are "head" and "head^". Therefore, the spec suggests both of these by using the suggestion prop + */ + suggestions?: (string | Suggestion)[]; + /** + * A template which is a single TemplateString or an array of TemplateStrings + * + * @remarks + * Templates are generators prebuilt by Fig. Here are the three templates: + * - filepaths: show folders and filepaths. Allow autoexecute on filepaths + * - folders: show folders only. Allow autoexecute on folders + * - history: show suggestions for all items in history matching this pattern + * - help: show subcommands. Only includes the 'siblings' of the nearest 'parent' subcommand + * + * @example + * `cd` uses the "folders" template + * @example + * `ls` used ["filepaths", "folders"]. Why both? Because if I `ls` a directory, we want to enable a user to autoexecute on this directory. If we just did "filepaths" they couldn't autoexecute. + * + */ + template?: Template; + /** + * + * Generators let you dynamically generate suggestions for arguments by running shell commands on a user's device. + * + * This takes a single generator or an array of generators + */ + generators?: SingleOrArray; + /** + * This option allows to enforce the suggestion filtering strategy for a specific argument suggestions. + * @remarks + * Users always want to have the most accurate results at the top of the suggestions list. + * For example we can enable fuzzy search on an argument that always requires fuzzy search to show the best suggestions. + * This property is also useful when argument suggestions have a prefix (e.g. the npm package scope) because enabling fuzzy search users can omit that part (see the second example below) + * @example + * npm uninstall [packages...] uses fuzzy search to allow searching for installed packages ignoring the package scope + * ```typescript + * const figSpec: Fig.Spec { + * name: "npm", + * subcommands: [ + * { + * args: { + * name: "packages", + * filterStrategy: "fuzzy", // search in suggestions provided by the generator (in this case) using fuzzy search + * generators: generateNpmDeps, + * isVariadic: true, + * }, + * }, + * // ... other npm commands + * ], + * } + * ``` + */ + filterStrategy?: "fuzzy" | "prefix" | "default"; + /** + * Provide a suggestion at the top of the list with the current token that is being typed by the user. + */ + suggestCurrentToken?: boolean; + /** + * Specifies that the argument is variadic and therefore repeats infinitely. + * + * @remarks + * Man pages represent variadic arguments with an ellipsis e.g. `git add ` + * + * @example + * `echo` takes a variadic argument (`echo hello world ...`) + * @example + * `git add` also takes a variadic argument + */ + isVariadic?: boolean; - /** - * Specifies whether options can interrupt variadic arguments. There is - * slightly different behavior when this is used on an option argument and - * on a subcommand argument: - * - * - When an option breaks a *variadic subcommand argument*, after the option - * and any arguments are parsed, the parser will continue parsing variadic - * arguments to the subcommand - * - When an option breaks a *variadic option argument*, after the breaking - * option and any arguments are parsed, the original variadic options - * arguments will be terminated. See the second examples below for details. - * - * - * @defaultValue true - * - * @example - * When true for git add's argument: - * `git add file1 -v file2` will interpret `-v` as an option NOT an - * argument, and will continue interpreting file2 as a variadic argument to - * add after - * - * @example - * When true for -T's argument, where -T is a variadic list of tags: - * `cmd -T tag1 tag2 -p project tag3` will interpret `-p` as an option, but - * will then terminate the list of tags. So tag3 is not parsed as an - * argument to `-T`, but rather as a subcommand argument to `cmd` if `cmd` - * takes any arguments. - * - * @example - * When false: - * `echo hello -n world` will treat -n as an argument NOT an option. - * However, in `echo -n hello world` it will treat -n as an option as - * variadic arguments haven't started yet - * - */ - optionsCanBreakVariadicArg?: boolean; + /** + * Specifies whether options can interrupt variadic arguments. There is + * slightly different behavior when this is used on an option argument and + * on a subcommand argument: + * + * - When an option breaks a *variadic subcommand argument*, after the option + * and any arguments are parsed, the parser will continue parsing variadic + * arguments to the subcommand + * - When an option breaks a *variadic option argument*, after the breaking + * option and any arguments are parsed, the original variadic options + * arguments will be terminated. See the second examples below for details. + * + * + * @defaultValue true + * + * @example + * When true for git add's argument: + * `git add file1 -v file2` will interpret `-v` as an option NOT an + * argument, and will continue interpreting file2 as a variadic argument to + * add after + * + * @example + * When true for -T's argument, where -T is a variadic list of tags: + * `cmd -T tag1 tag2 -p project tag3` will interpret `-p` as an option, but + * will then terminate the list of tags. So tag3 is not parsed as an + * argument to `-T`, but rather as a subcommand argument to `cmd` if `cmd` + * takes any arguments. + * + * @example + * When false: + * `echo hello -n world` will treat -n as an argument NOT an option. + * However, in `echo -n hello world` it will treat -n as an option as + * variadic arguments haven't started yet + * + */ + optionsCanBreakVariadicArg?: boolean; - /** - * `true` if an argument is optional (ie the CLI spec says it is not mandatory to include an argument, but you can if you want to). - * - * @remarks - * NOTE: It is important you include this for our parsing. If you don't, Fig will assume the argument is mandatory. When we assume an argument is mandatory, we force the user to input the argument and hide all other suggestions. - * - * @example - * `git push [remote] [branch]` takes two optional args. - */ - isOptional?: boolean; - /** - * Syntactic sugar over the `loadSpec` prop. - * - * @remarks - * Specifies that the argument is an entirely new command which Fig should start completing on from scratch. - * - * @example - * `time` and `builtin` have only one argument and this argument has the `isCommand` property. If I type `time git`, Fig will load up the git completion spec because the isCommand property is set. - */ - isCommand?: boolean; - /** - * The same as the `isCommand` prop, except Fig will look for a completion spec in the `.fig/autocomplete/build` folder in the user's current working directory. - * - * @remarks - * See our docs for more on building completion specs for local scripts [Fig for Teams](https://fig.io/docs/) - * @example - * `python` take one argument which is a `.py` file. If I have a `main.py` file on my desktop and my current working directory is my desktop, if I type `python main.py[space]` Fig will look for a completion spec in `~/Desktop/.fig/autocomplete/build/main.py.js` - */ - isScript?: boolean; - /** - * The same as the `isCommand` prop, except you specify a string to prepend to what the user inputs and fig will load the completion spec accordingly. - * @remarks - * If isModule: "python/", Fig would load up the `python/USER_INPUT.js` completion spec from the `~/.fig/autocomplete` folder. - * @example - * For `python -m`, the user can input a specific module such as http.server. Each module is effectively a mini CLI tool that should have its own completions. Therefore the argument object for -m has `isModule: "python/"`. Whatever the modules user inputs, Fig will look under the `~/.fig/autocomplete/python/` directory for completion spec. - * - * @deprecated use `loadSpec` instead - */ - isModule?: string; + /** + * `true` if an argument is optional (ie the CLI spec says it is not mandatory to include an argument, but you can if you want to). + * + * @remarks + * NOTE: It is important you include this for our parsing. If you don't, Fig will assume the argument is mandatory. When we assume an argument is mandatory, we force the user to input the argument and hide all other suggestions. + * + * @example + * `git push [remote] [branch]` takes two optional args. + */ + isOptional?: boolean; + /** + * Syntactic sugar over the `loadSpec` prop. + * + * @remarks + * Specifies that the argument is an entirely new command which Fig should start completing on from scratch. + * + * @example + * `time` and `builtin` have only one argument and this argument has the `isCommand` property. If I type `time git`, Fig will load up the git completion spec because the isCommand property is set. + */ + isCommand?: boolean; + /** + * The same as the `isCommand` prop, except Fig will look for a completion spec in the `.fig/autocomplete/build` folder in the user's current working directory. + * + * @remarks + * See our docs for more on building completion specs for local scripts [Fig for Teams](https://fig.io/docs/) + * @example + * `python` take one argument which is a `.py` file. If I have a `main.py` file on my desktop and my current working directory is my desktop, if I type `python main.py[space]` Fig will look for a completion spec in `~/Desktop/.fig/autocomplete/build/main.py.js` + */ + isScript?: boolean; + /** + * The same as the `isCommand` prop, except you specify a string to prepend to what the user inputs and fig will load the completion spec accordingly. + * @remarks + * If isModule: "python/", Fig would load up the `python/USER_INPUT.js` completion spec from the `~/.fig/autocomplete` folder. + * @example + * For `python -m`, the user can input a specific module such as http.server. Each module is effectively a mini CLI tool that should have its own completions. Therefore the argument object for -m has `isModule: "python/"`. Whatever the modules user inputs, Fig will look under the `~/.fig/autocomplete/python/` directory for completion spec. + * + * @deprecated use `loadSpec` instead + */ + isModule?: string; - /** - * This will debounce every keystroke event for this particular arg. - * @remarks - * If there are no keystroke events after 100ms, Fig will execute all the generators in this arg and return the suggestions. - * - * @example - * `npm install` and `pip install` send debounced network requests after inactive typing from users. - */ - debounce?: boolean; - /** - * The default value for an optional argument. - * - * @remarks - * Note: This is currently not used anywhere in Fig's autocomplete popup, but will be soon. - * - */ - default?: string; - /** - * See [`loadSpec` in Subcommand Object](https://fig.io/docs/reference/subcommand#loadspec). - * - * @remarks - * There is a very high chance you want to use one of the following: - * 1. `isCommand` (See [Arg Object](https://fig.io/docs/reference/arg#iscommand)) - * 2. `isScript` (See [Arg Object](https://fig.io/docs/reference/arg#isscript)) - * - */ - loadSpec?: LoadSpec; + /** + * This will debounce every keystroke event for this particular arg. + * @remarks + * If there are no keystroke events after 100ms, Fig will execute all the generators in this arg and return the suggestions. + * + * @example + * `npm install` and `pip install` send debounced network requests after inactive typing from users. + */ + debounce?: boolean; + /** + * The default value for an optional argument. + * + * @remarks + * Note: This is currently not used anywhere in Fig's autocomplete popup, but will be soon. + * + */ + default?: string; + /** + * See [`loadSpec` in Subcommand Object](https://fig.io/docs/reference/subcommand#loadspec). + * + * @remarks + * There is a very high chance you want to use one of the following: + * 1. `isCommand` (See [Arg Object](https://fig.io/docs/reference/arg#iscommand)) + * 2. `isScript` (See [Arg Object](https://fig.io/docs/reference/arg#isscript)) + * + */ + loadSpec?: LoadSpec; - /** - * The `arg.parserDirective.alias` prop defines whether Fig's tokenizer should expand out an alias into separate tokens then offer completions accordingly. - * - * @remarks - * This is similar to how Fig is able to offer autocomplete for user defined shell aliases, but occurs at the completion spec level. - * - * @param token - The token that the user has just typed that is an alias for something else - * @param executeCommand -an async function that allows you to execute a shell command on the user's system and get the output as a string. - * @returns The expansion of the alias that Fig's bash parser will reparse as if it were typed out in full, rather than the alias. - * - * If for some reason you know exactly what it will be, you may also just pass in the expanded alias, not a function that returns the expanded alias. - * - * @example - * git takes git aliases. These aliases are defined in a user's gitconfig file. Let's say a user has an alias for `p=push`, then if a user typed `git p[space]`, this function would take the `p` token, return `push` and then offer suggestions as if the user had typed `git push[space]` - * - * @example - * `npm run