diff --git a/.eslintrc.json b/.eslintrc.json index 8382822ac14..4d5b300eafb 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -151,21 +151,13 @@ { // Files should (only) be removed from the list they adopt the leak detector "exclude": [ - "src/vs/base/test/browser/browser.test.ts", - "src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts", - "src/vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts", "src/vs/editor/contrib/codeAction/test/browser/codeActionModel.test.ts", - "src/vs/editor/test/common/services/languageService.test.ts", - "src/vs/editor/test/node/classification/typescript.test.ts", "src/vs/platform/configuration/test/common/configuration.test.ts", - "src/vs/platform/extensions/test/common/extensionValidator.test.ts", "src/vs/platform/opener/test/common/opener.test.ts", "src/vs/platform/registry/test/common/platform.test.ts", - "src/vs/platform/remote/test/common/remoteHosts.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/common/extHostExtensionActivator.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", @@ -176,7 +168,6 @@ "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/extensions/test/common/extensionDescriptionRegistry.test.ts", "src/vs/workbench/services/userActivity/test/browser/domActivityTracker.test.ts", "src/vs/workbench/test/browser/quickAccess.test.ts" ] @@ -317,6 +308,10 @@ "selector": "BinaryExpression[operator='instanceof'][right.name='MouseEvent']", "message": "Use DOM.isMouseEvent() to support multi-window scenarios." }, + { + "selector": "BinaryExpression[operator='instanceof'][right.name=/^HTML\\w+/]", + "message": "Use DOM.isHTMLElement() and related methods to support multi-window scenarios." + }, { "selector": "BinaryExpression[operator='instanceof'][right.name='KeyboardEvent']", "message": "Use DOM.isKeyboardEvent() to support multi-window scenarios." diff --git a/.vscode/extensions/vscode-selfhost-test-provider/src/vscodeTestRunner.ts b/.vscode/extensions/vscode-selfhost-test-provider/src/vscodeTestRunner.ts index 5d73928aed5..8a76cefe36a 100644 --- a/.vscode/extensions/vscode-selfhost-test-provider/src/vscodeTestRunner.ts +++ b/.vscode/extensions/vscode-selfhost-test-provider/src/vscodeTestRunner.ts @@ -24,7 +24,7 @@ const ATTACH_CONFIG_NAME = 'Attach to VS Code'; const DEBUG_TYPE = 'pwa-chrome'; export abstract class VSCodeTestRunner { - constructor(protected readonly repoLocation: vscode.WorkspaceFolder) {} + constructor(protected readonly repoLocation: vscode.WorkspaceFolder) { } public async run(baseArgs: ReadonlyArray, filter?: ReadonlyArray) { const args = this.prepareArguments(baseArgs, filter); @@ -163,18 +163,40 @@ export abstract class VSCodeTestRunner { path.relative(data.workspaceFolder.uri.fsPath, data.uri.fsPath).replace(/\\/g, '/') ); + const itemDatas = filter.map(f => itemData.get(f)); + /** If true, we have to be careful with greps, as a grep for one test file affects the run of the other test file. */ + const hasBothTestCaseOrTestSuiteAndTestFileFilters = + itemDatas.some(d => (d instanceof TestCase) || (d instanceof TestSuite)) && + itemDatas.some(d => d instanceof TestFile); + + function addTestCaseOrSuite(data: TestCase | TestSuite, test: vscode.TestItem): void { + grepRe.push(escapeRe(data.fullName) + (data instanceof TestCase ? '$' : ' ')); + for (let p = test.parent; p; p = p.parent) { + const parentData = itemData.get(p); + if (parentData instanceof TestFile) { + addTestFileRunPath(parentData); + } + } + } + for (const test of filter) { const data = itemData.get(test); if (data instanceof TestCase || data instanceof TestSuite) { - grepRe.push(escapeRe(data.fullName) + (data instanceof TestCase ? '$' : ' ')); - for (let p = test.parent; p; p = p.parent) { - const parentData = itemData.get(p); - if (parentData instanceof TestFile) { - addTestFileRunPath(parentData); + addTestCaseOrSuite(data, test); + } else if (data instanceof TestFile) { + if (!hasBothTestCaseOrTestSuiteAndTestFileFilters) { + addTestFileRunPath(data); + } else { + // We add all the items individually so they get their own grep expressions. + for (const [_id, nestedTest] of test.children) { + const childData = itemData.get(nestedTest); + if (childData instanceof TestCase || childData instanceof TestSuite) { + addTestCaseOrSuite(childData, nestedTest); + } else { + console.error('Unexpected test item in test file', nestedTest.id, nestedTest.label); + } } } - } else if (data instanceof TestFile) { - addTestFileRunPath(data); } } @@ -303,5 +325,5 @@ export const PlatformTestRunner = process.platform === 'win32' ? WindowsTestRunner : process.platform === 'darwin' - ? DarwinTestRunner - : PosixTestRunner; + ? DarwinTestRunner + : PosixTestRunner; diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 60c0c7e445e..2e3f2610f46 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -517,7 +517,7 @@ to the base-name name of the original file, and an extension of txt, html, or si --------------------------------------------------------- -go-syntax 0.6.5 - MIT +go-syntax 0.6.6 - MIT https://github.com/worlpaker/go-syntax MIT License @@ -777,7 +777,7 @@ SOFTWARE. --------------------------------------------------------- -jeff-hykin/better-shell-syntax 1.8.3 - MIT +jeff-hykin/better-shell-syntax 1.8.7 - MIT https://github.com/jeff-hykin/better-shell-syntax MIT License diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 0027a774b35..0508059fcd7 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -164,7 +164,7 @@ resources: - repository: 1ESPipelines type: git name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/heads/joao/disable-tsa-linux-arm64 + ref: refs/tags/release extends: template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines diff --git a/build/lib/stylelint/vscode-known-variables.json b/build/lib/stylelint/vscode-known-variables.json index e6291132d56..d8b28e0dd24 100644 --- a/build/lib/stylelint/vscode-known-variables.json +++ b/build/lib/stylelint/vscode-known-variables.json @@ -128,8 +128,10 @@ "--vscode-dropdown-listBackground", "--vscode-editor-background", "--vscode-editor-findMatchBackground", + "--vscode-editor-findMatchForeground", "--vscode-editor-findMatchBorder", "--vscode-editor-findMatchHighlightBackground", + "--vscode-editor-findMatchHighlightForeground", "--vscode-editor-findMatchHighlightBorder", "--vscode-editor-findRangeHighlightBackground", "--vscode-editor-findRangeHighlightBorder", diff --git a/cglicenses.json b/cglicenses.json index 7643d1e4194..d90d55d7315 100644 --- a/cglicenses.json +++ b/cglicenses.json @@ -130,6 +130,21 @@ "SOFTWARE" ] }, + { + // Reason: NPM package does not include repository URL https://github.com/microsoft/vscode-deviceid/issues/12 + "name": "@vscode/deviceid", + "fullLicenseText": [ + "Copyright (c) Microsoft Corporation.", + "", + "MIT License", + "", + "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." + ] + }, { // Reason: Missing license file "name": "@tokenizer/token", @@ -317,13 +332,21 @@ "fullLicenseTextUri": "https://raw.githubusercontent.com/rodrimati1992/const_format_crates/b2207af46bfbd9f1a6bd12dbffd10feeea3d9fd7/LICENSE-ZLIB.md" }, { // License is MIT/Apache and tool doesn't look in subfolders - "name": "toml", - "fullLicenseTextUri": "https://raw.githubusercontent.com/toml-rs/toml/main/crates/toml/LICENSE-MIT" + "name": "toml_edit", + "fullLicenseTextUri": "https://raw.githubusercontent.com/toml-rs/toml/main/crates/toml_edit/LICENSE-MIT" + }, + { // License is MIT/Apache and tool doesn't look in subfolders + "name": "toml_datetime", + "fullLicenseTextUri": "https://raw.githubusercontent.com/toml-rs/toml/main/crates/toml_datetime/LICENSE-MIT" }, { // License is MIT/Apache and tool doesn't look in subfolders "name": "dirs-sys-next", "fullLicenseTextUri": "https://raw.githubusercontent.com/xdg-rs/dirs/master/dirs-sys/LICENSE-MIT" }, + { // License is MIT/Apache and gitlab API doesn't find the project + "name": "libredox", + "fullLicenseTextUri": "https://gitlab.redox-os.org/redox-os/libredox/-/raw/master/LICENSE" + }, { "name": "https-proxy-agent", "fullLicenseText": [ diff --git a/cli/ThirdPartyNotices.txt b/cli/ThirdPartyNotices.txt index 1b98ce5b18c..7a74fb503c5 100644 --- a/cli/ThirdPartyNotices.txt +++ b/cli/ThirdPartyNotices.txt @@ -17,6 +17,38 @@ required to debug changes to any libraries licensed under the GNU Lesser General +--------------------------------------------------------- + +addr2line 0.21.0 - Apache-2.0 OR MIT +https://github.com/gimli-rs/addr2line + +Copyright (c) 2016-2018 The gimli 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 +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. +--------------------------------------------------------- + --------------------------------------------------------- adler 1.0.2 - 0BSD OR MIT OR Apache-2.0 @@ -49,7 +81,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -aho-corasick 1.0.1 - Unlicense OR MIT +aho-corasick 1.1.3 - Unlicense OR MIT https://github.com/BurntSushi/aho-corasick The MIT License (MIT) @@ -132,7 +164,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -anstream 0.3.2 - MIT OR Apache-2.0 +anstream 0.6.14 - MIT OR Apache-2.0 https://github.com/rust-cli/anstyle This software is released under the MIT license: @@ -157,7 +189,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -anstyle 1.0.0 - MIT OR Apache-2.0 +anstyle 1.0.7 - MIT OR Apache-2.0 https://github.com/rust-cli/anstyle This software is released under the MIT license: @@ -182,7 +214,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -anstyle-parse 0.2.0 - MIT OR Apache-2.0 +anstyle-parse 0.2.4 - MIT OR Apache-2.0 https://github.com/rust-cli/anstyle This software is released under the MIT license: @@ -207,7 +239,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -anstyle-query 1.0.0 - MIT OR Apache-2.0 +anstyle-query 1.0.3 - MIT OR Apache-2.0 https://github.com/rust-cli/anstyle This software is released under the MIT license: @@ -232,7 +264,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -anstyle-wincon 1.0.1 - MIT OR Apache-2.0 +anstyle-wincon 3.0.3 - MIT OR Apache-2.0 https://github.com/rust-cli/anstyle This software is released under the MIT license: @@ -285,7 +317,7 @@ SOFTWARE. --------------------------------------------------------- -async-channel 1.8.0 - Apache-2.0 OR MIT +async-channel 2.3.1 - Apache-2.0 OR MIT https://github.com/smol-rs/async-channel Permission is hereby granted, free of charge, to any @@ -315,7 +347,8 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -async-io 1.9.0 - Apache-2.0 OR MIT +async-io 1.13.0 - Apache-2.0 OR MIT +async-io 2.3.2 - Apache-2.0 OR MIT https://github.com/smol-rs/async-io Permission is hereby granted, free of charge, to any @@ -345,7 +378,8 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -async-lock 2.7.0 - Apache-2.0 OR MIT +async-lock 2.8.0 - Apache-2.0 OR MIT +async-lock 3.3.0 - Apache-2.0 OR MIT https://github.com/smol-rs/async-lock Permission is hereby granted, free of charge, to any @@ -375,7 +409,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -async-process 1.7.0 - Apache-2.0 OR MIT +async-process 1.8.1 - Apache-2.0 OR MIT https://github.com/smol-rs/async-process Permission is hereby granted, free of charge, to any @@ -405,7 +439,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -async-recursion 1.0.0 - MIT OR Apache-2.0 +async-recursion 1.1.1 - MIT OR Apache-2.0 https://github.com/dcchut/async-recursion Permission is hereby granted, free of charge, to any @@ -435,7 +469,37 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -async-task 4.4.0 - Apache-2.0 OR MIT +async-signal 0.2.6 - Apache-2.0 OR MIT +https://github.com/smol-rs/async-signal + +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. +--------------------------------------------------------- + +--------------------------------------------------------- + +async-task 4.7.1 - Apache-2.0 OR MIT https://github.com/smol-rs/async-task Permission is hereby granted, free of charge, to any @@ -465,7 +529,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -async-trait 0.1.68 - MIT OR Apache-2.0 +async-trait 0.1.80 - MIT OR Apache-2.0 https://github.com/dtolnay/async-trait Permission is hereby granted, free of charge, to any @@ -495,7 +559,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -atomic-waker 1.1.1 - Apache-2.0 OR MIT +atomic-waker 1.1.2 - Apache-2.0 OR MIT https://github.com/smol-rs/atomic-waker Permission is hereby granted, free of charge, to any @@ -525,7 +589,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -autocfg 1.1.0 - Apache-2.0 OR MIT +autocfg 1.3.0 - Apache-2.0 OR MIT https://github.com/cuviper/autocfg Copyright (c) 2018 Josh Stone @@ -557,7 +621,39 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -base64 0.21.2 - MIT OR Apache-2.0 +backtrace 0.3.71 - MIT OR Apache-2.0 +https://github.com/rust-lang/backtrace-rs + +Copyright (c) 2014 Alex Crichton + +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. +--------------------------------------------------------- + +--------------------------------------------------------- + +base64 0.21.7 - MIT OR Apache-2.0 https://github.com/marshallpierce/rust-base64 The MIT License (MIT) @@ -618,7 +714,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- bitflags 1.3.2 - MIT/Apache-2.0 -bitflags 2.4.1 - MIT OR Apache-2.0 +bitflags 2.5.0 - MIT OR Apache-2.0 https://github.com/bitflags/bitflags Copyright (c) 2014 The Rust Project Developers @@ -650,7 +746,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -block-buffer 0.10.3 - MIT OR Apache-2.0 +block-buffer 0.10.4 - MIT OR Apache-2.0 https://github.com/RustCrypto/utils All crates licensed under either of @@ -704,7 +800,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted --------------------------------------------------------- -block-padding 0.3.2 - MIT OR Apache-2.0 +block-padding 0.3.3 - MIT OR Apache-2.0 https://github.com/RustCrypto/utils All crates licensed under either of @@ -758,7 +854,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted --------------------------------------------------------- -blocking 1.3.1 - Apache-2.0 OR MIT +blocking 1.6.0 - Apache-2.0 OR MIT https://github.com/smol-rs/blocking Permission is hereby granted, free of charge, to any @@ -788,7 +884,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -bumpalo 3.12.0 - MIT/Apache-2.0 +bumpalo 3.16.0 - MIT OR Apache-2.0 https://github.com/fitzgen/bumpalo Copyright (c) 2019 Nick Fitzgerald @@ -820,7 +916,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -byteorder 1.4.3 - Unlicense OR MIT +byteorder 1.5.0 - Unlicense OR MIT https://github.com/BurntSushi/byteorder The MIT License (MIT) @@ -848,7 +944,7 @@ THE SOFTWARE. --------------------------------------------------------- -bytes 1.4.0 - MIT +bytes 1.6.0 - MIT https://github.com/tokio-rs/bytes The MIT License (MIT) @@ -882,37 +978,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -cache-padded 1.2.0 - Apache-2.0 OR MIT -https://github.com/smol-rs/cache-padded - -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. ---------------------------------------------------------- - ---------------------------------------------------------- - -cc 1.0.73 - MIT/Apache-2.0 +cc 1.0.98 - MIT OR Apache-2.0 https://github.com/rust-lang/cc-rs Copyright (c) 2014 Alex Crichton @@ -976,7 +1042,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -chrono 0.4.26 - MIT/Apache-2.0 +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 @@ -1222,7 +1288,7 @@ limitations under the License. --------------------------------------------------------- -clap 4.3.0 - MIT OR Apache-2.0 +clap 4.5.4 - MIT OR Apache-2.0 https://github.com/clap-rs/clap Copyright (c) Individual contributors @@ -1248,7 +1314,7 @@ SOFTWARE. --------------------------------------------------------- -clap_builder 4.3.0 - MIT OR Apache-2.0 +clap_builder 4.5.2 - MIT OR Apache-2.0 https://github.com/clap-rs/clap Copyright (c) Individual contributors @@ -1274,7 +1340,7 @@ SOFTWARE. --------------------------------------------------------- -clap_derive 4.3.0 - MIT OR Apache-2.0 +clap_derive 4.5.4 - MIT OR Apache-2.0 https://github.com/clap-rs/clap/tree/master/clap_derive Copyright (c) Individual contributors @@ -1300,7 +1366,7 @@ SOFTWARE. --------------------------------------------------------- -clap_lex 0.5.0 - MIT OR Apache-2.0 +clap_lex 0.7.0 - MIT OR Apache-2.0 https://github.com/clap-rs/clap/tree/master/clap_lex Copyright (c) Individual contributors @@ -1326,299 +1392,90 @@ SOFTWARE. --------------------------------------------------------- -codespan-reporting 0.11.1 - Apache-2.0 -https://github.com/brendanzab/codespan +colorchoice 1.0.1 - MIT OR Apache-2.0 +https://github.com/rust-cli/anstyle -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +This software is released under the MIT license: - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +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: - 1. Definitions. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. +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. +--------------------------------------------------------- - "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. +concurrent-queue 2.5.0 - Apache-2.0 OR MIT +https://github.com/smol-rs/concurrent-queue - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. +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: - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. - "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. +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. +--------------------------------------------------------- - "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. +console 0.15.8 - MIT +https://github.com/console-rs/console - "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." +The MIT License (MIT) - "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. +Copyright (c) 2017 Armin Ronacher - 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. +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: - 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. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - 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: +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. +--------------------------------------------------------- - (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. ---------------------------------------------------------- - ---------------------------------------------------------- - -colorchoice 1.0.0 - MIT OR Apache-2.0 -https://github.com/rust-cli/anstyle - -This software is released under the MIT license: - -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. ---------------------------------------------------------- - ---------------------------------------------------------- - -concurrent-queue 1.2.4 - Apache-2.0 OR MIT -concurrent-queue 2.2.0 - Apache-2.0 OR MIT -https://github.com/smol-rs/concurrent-queue - -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. ---------------------------------------------------------- - ---------------------------------------------------------- - -console 0.15.7 - MIT -https://github.com/console-rs/console - -The MIT License (MIT) - -Copyright (c) 2017 Armin Ronacher - -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. ---------------------------------------------------------- - ---------------------------------------------------------- - -const_format 0.2.31 - Zlib +const_format 0.2.32 - Zlib https://github.com/rodrimati1992/const_format_crates/ Copyright (c) 2020 Matias Rodriguez. @@ -1642,7 +1499,7 @@ freely, subject to the following restrictions: --------------------------------------------------------- -const_format_proc_macros 0.2.31 - Zlib +const_format_proc_macros 0.2.32 - Zlib https://github.com/rodrimati1992/const_format_crates/ Copyright (c) 2020 Matias Rodriguez. @@ -1666,7 +1523,7 @@ freely, subject to the following restrictions: --------------------------------------------------------- -core-foundation 0.9.3 - MIT / Apache-2.0 +core-foundation 0.9.4 - MIT OR Apache-2.0 https://github.com/servo/core-foundation-rs Copyright (c) 2012-2013 Mozilla Foundation @@ -1698,7 +1555,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -core-foundation-sys 0.8.3 - MIT / Apache-2.0 +core-foundation-sys 0.8.6 - MIT OR Apache-2.0 https://github.com/servo/core-foundation-rs Copyright (c) 2012-2013 Mozilla Foundation @@ -1730,7 +1587,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -cpufeatures 0.2.8 - MIT OR Apache-2.0 +cpufeatures 0.2.12 - MIT OR Apache-2.0 https://github.com/RustCrypto/utils All crates licensed under either of @@ -1784,7 +1641,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted --------------------------------------------------------- -crc32fast 1.3.2 - MIT OR Apache-2.0 +crc32fast 1.4.1 - MIT OR Apache-2.0 https://github.com/srijs/rust-crc32fast MIT License @@ -1812,7 +1669,7 @@ SOFTWARE. --------------------------------------------------------- -crossbeam-channel 0.5.12 - MIT OR Apache-2.0 +crossbeam-channel 0.5.13 - MIT OR Apache-2.0 https://github.com/crossbeam-rs/crossbeam The MIT License (MIT) @@ -1846,7 +1703,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -crossbeam-utils 0.8.19 - MIT OR Apache-2.0 +crossbeam-utils 0.8.20 - MIT OR Apache-2.0 https://github.com/crossbeam-rs/crossbeam The MIT License (MIT) @@ -1936,133 +1793,39 @@ Unless you explicitly state otherwise, any contribution intentionally submitted --------------------------------------------------------- -cxx 1.0.97 - MIT OR Apache-2.0 -https://github.com/dtolnay/cxx - -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. ---------------------------------------------------------- - ---------------------------------------------------------- - -cxx-build 1.0.97 - MIT OR Apache-2.0 -https://github.com/dtolnay/cxx - -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. ---------------------------------------------------------- - ---------------------------------------------------------- - -cxxbridge-flags 1.0.97 - MIT OR Apache-2.0 -https://github.com/dtolnay/cxx - -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. ---------------------------------------------------------- +data-encoding 2.6.0 - MIT +https://github.com/ia0/data-encoding ---------------------------------------------------------- +The MIT License (MIT) -cxxbridge-macro 1.0.97 - MIT OR Apache-2.0 -https://github.com/dtolnay/cxx +Copyright (c) 2015-2020 Julien Cretin +Copyright (c) 2017-2020 Google Inc. -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: +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 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. +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. --------------------------------------------------------- --------------------------------------------------------- -data-encoding 2.3.2 - MIT -https://github.com/ia0/data-encoding +deranged 0.3.11 - MIT OR Apache-2.0 +https://github.com/jhpratt/deranged -The MIT License (MIT) - -Copyright (c) 2015-2020 Julien Cretin -Copyright (c) 2017-2020 Google Inc. +Copyright (c) 2022 Jacob Pratt et al. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -2139,7 +1902,7 @@ SOFTWARE. --------------------------------------------------------- -digest 0.10.5 - MIT OR Apache-2.0 +digest 0.10.7 - MIT OR Apache-2.0 https://github.com/RustCrypto/traits All crates licensed under either of @@ -2273,7 +2036,7 @@ SOFTWARE --------------------------------------------------------- -encoding_rs 0.8.31 - (Apache-2.0 OR MIT) AND BSD-3-Clause +encoding_rs 0.8.34 - (Apache-2.0 OR MIT) AND BSD-3-Clause https://github.com/hsivonen/encoding_rs Copyright Mozilla Foundation @@ -2305,7 +2068,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -enumflags2 0.7.7 - MIT OR Apache-2.0 +enumflags2 0.7.9 - MIT OR Apache-2.0 https://github.com/meithecatte/enumflags2 Copyright (c) 2017-2023 Maik Klein, Maja Kądziołka @@ -2337,7 +2100,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -enumflags2_derive 0.7.7 - MIT OR Apache-2.0 +enumflags2_derive 0.7.9 - MIT OR Apache-2.0 https://github.com/meithecatte/enumflags2 Copyright (c) 2017-2023 Maik Klein, Maja Kądziołka @@ -2401,7 +2164,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -errno 0.3.1 - MIT OR Apache-2.0 +errno 0.3.9 - MIT OR Apache-2.0 https://github.com/lambda-fairy/rust-errno Copyright (c) 2014 Chris Wong @@ -2433,36 +2196,42 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -errno-dragonfly 0.1.2 - MIT -https://github.com/mneumann/errno-dragonfly-rs - -MIT License - -Copyright (c) 2017 Michael Neumann +event-listener 2.5.3 - Apache-2.0 OR MIT +event-listener 3.1.0 - Apache-2.0 OR MIT +event-listener 4.0.3 - Apache-2.0 OR MIT +event-listener 5.3.0 - Apache-2.0 OR MIT +https://github.com/smol-rs/event-listener -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: +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 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. +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. --------------------------------------------------------- --------------------------------------------------------- -event-listener 2.5.3 - Apache-2.0 OR MIT -https://github.com/smol-rs/event-listener +event-listener-strategy 0.4.0 - Apache-2.0 OR MIT +event-listener-strategy 0.5.2 - Apache-2.0 OR MIT +https://github.com/smol-rs/event-listener-strategy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -2491,7 +2260,8 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -fastrand 1.8.0 - Apache-2.0 OR MIT +fastrand 1.9.0 - Apache-2.0 OR MIT +fastrand 2.1.0 - Apache-2.0 OR MIT https://github.com/smol-rs/fastrand Permission is hereby granted, free of charge, to any @@ -2521,7 +2291,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -filetime 0.2.17 - MIT/Apache-2.0 +filetime 0.2.23 - MIT/Apache-2.0 https://github.com/alexcrichton/filetime Copyright (c) 2014 Alex Crichton @@ -2553,7 +2323,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -flate2 1.0.26 - MIT OR Apache-2.0 +flate2 1.0.30 - MIT OR Apache-2.0 https://github.com/rust-lang/flate2-rs Copyright (c) 2014 Alex Crichton @@ -2669,7 +2439,7 @@ SOFTWARE. --------------------------------------------------------- -form_urlencoded 1.1.0 - MIT OR Apache-2.0 +form_urlencoded 1.2.1 - MIT OR Apache-2.0 https://github.com/servo/rust-url Copyright (c) 2013-2022 The rust-url developers @@ -2701,7 +2471,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -futures 0.3.28 - MIT OR Apache-2.0 +futures 0.3.30 - MIT OR Apache-2.0 https://github.com/rust-lang/futures-rs Copyright (c) 2016 Alex Crichton @@ -2734,7 +2504,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -futures-channel 0.3.28 - MIT OR Apache-2.0 +futures-channel 0.3.30 - MIT OR Apache-2.0 https://github.com/rust-lang/futures-rs Copyright (c) 2016 Alex Crichton @@ -2767,7 +2537,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -futures-core 0.3.28 - MIT OR Apache-2.0 +futures-core 0.3.30 - MIT OR Apache-2.0 https://github.com/rust-lang/futures-rs Copyright (c) 2016 Alex Crichton @@ -2800,7 +2570,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -futures-executor 0.3.28 - MIT OR Apache-2.0 +futures-executor 0.3.30 - MIT OR Apache-2.0 https://github.com/rust-lang/futures-rs Copyright (c) 2016 Alex Crichton @@ -2833,7 +2603,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -futures-io 0.3.28 - MIT OR Apache-2.0 +futures-io 0.3.30 - MIT OR Apache-2.0 https://github.com/rust-lang/futures-rs Copyright (c) 2016 Alex Crichton @@ -2866,7 +2636,8 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -futures-lite 1.12.0 - Apache-2.0 OR MIT +futures-lite 1.13.0 - Apache-2.0 OR MIT +futures-lite 2.3.0 - Apache-2.0 OR MIT https://github.com/smol-rs/futures-lite Permission is hereby granted, free of charge, to any @@ -2896,7 +2667,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -futures-macro 0.3.28 - MIT OR Apache-2.0 +futures-macro 0.3.30 - MIT OR Apache-2.0 https://github.com/rust-lang/futures-rs Copyright (c) 2016 Alex Crichton @@ -2929,7 +2700,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -futures-sink 0.3.28 - MIT OR Apache-2.0 +futures-sink 0.3.30 - MIT OR Apache-2.0 https://github.com/rust-lang/futures-rs Copyright (c) 2016 Alex Crichton @@ -2962,7 +2733,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -futures-task 0.3.28 - MIT OR Apache-2.0 +futures-task 0.3.30 - MIT OR Apache-2.0 https://github.com/rust-lang/futures-rs Copyright (c) 2016 Alex Crichton @@ -2995,7 +2766,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -futures-util 0.3.28 - MIT OR Apache-2.0 +futures-util 0.3.30 - MIT OR Apache-2.0 https://github.com/rust-lang/futures-rs Copyright (c) 2016 Alex Crichton @@ -3028,7 +2799,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -generic-array 0.14.6 - MIT +generic-array 0.14.7 - MIT https://github.com/fizyk20/generic-array The MIT License (MIT) @@ -3265,7 +3036,7 @@ limitations under the License. --------------------------------------------------------- getrandom 0.1.16 - MIT OR Apache-2.0 -getrandom 0.2.7 - MIT OR Apache-2.0 +getrandom 0.2.15 - MIT OR Apache-2.0 https://github.com/rust-random/getrandom Copyright (c) 2018-2024 The rust-random Project Developers @@ -3298,6 +3069,38 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- +gimli 0.28.1 - MIT OR Apache-2.0 +https://github.com/gimli-rs/gimli + +Copyright (c) 2015 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 +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. +--------------------------------------------------------- + +--------------------------------------------------------- + h2 0.3.26 - MIT https://github.com/hyperium/h2 @@ -3333,7 +3136,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- hashbrown 0.12.3 - MIT OR Apache-2.0 -hashbrown 0.14.3 - MIT OR Apache-2.0 +hashbrown 0.14.5 - MIT OR Apache-2.0 https://github.com/rust-lang/hashbrown Copyright (c) 2016 Amanieu d'Antras @@ -3365,7 +3168,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -heck 0.4.0 - MIT OR Apache-2.0 +heck 0.5.0 - MIT OR Apache-2.0 https://github.com/withoutboats/heck Copyright (c) 2015 The Rust Project Developers @@ -3397,8 +3200,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -hermit-abi 0.1.19 - MIT/Apache-2.0 -hermit-abi 0.3.1 - MIT OR Apache-2.0 +hermit-abi 0.3.9 - MIT OR Apache-2.0 https://github.com/hermit-os/hermit-rs Permission is hereby granted, free of charge, to any @@ -3557,7 +3359,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted --------------------------------------------------------- -http 0.2.9 - MIT OR Apache-2.0 +http 0.2.12 - MIT OR Apache-2.0 https://github.com/hyperium/http Copyright (c) 2017 http-rs authors @@ -3589,7 +3391,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -http-body 0.4.5 - MIT +http-body 0.4.6 - MIT https://github.com/hyperium/http-body The MIT License (MIT) @@ -3649,7 +3451,7 @@ THE SOFTWARE. --------------------------------------------------------- -httpdate 1.0.2 - MIT/Apache-2.0 +httpdate 1.0.3 - MIT OR Apache-2.0 https://github.com/pyfisch/httpdate Copyright (c) 2016 Pyfisch @@ -3675,7 +3477,7 @@ THE SOFTWARE. --------------------------------------------------------- -hyper 0.14.26 - MIT +hyper 0.14.28 - MIT https://github.com/hyperium/hyper The MIT License (MIT) @@ -3729,7 +3531,7 @@ THE SOFTWARE. --------------------------------------------------------- -iana-time-zone 0.1.57 - MIT OR Apache-2.0 +iana-time-zone 0.1.60 - MIT OR Apache-2.0 https://github.com/strawlab/iana-time-zone Copyright (c) 2020 Andrew D. Straw @@ -3761,7 +3563,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -iana-time-zone-haiku 0.1.1 - MIT OR Apache-2.0 +iana-time-zone-haiku 0.1.2 - MIT OR Apache-2.0 https://github.com/strawlab/iana-time-zone Copyright (c) 2020 Andrew D. Straw @@ -3793,7 +3595,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -idna 0.3.0 - MIT OR Apache-2.0 +idna 0.5.0 - MIT OR Apache-2.0 https://github.com/servo/rust-url/ Copyright (c) 2013-2022 The rust-url developers @@ -3826,7 +3628,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- indexmap 1.9.3 - Apache-2.0 OR MIT -indexmap 2.1.0 - Apache-2.0 OR MIT +indexmap 2.2.6 - Apache-2.0 OR MIT https://github.com/indexmap-rs/indexmap Copyright (c) 2016--2017 @@ -3858,7 +3660,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -indicatif 0.17.4 - MIT +indicatif 0.17.8 - MIT https://github.com/console-rs/indicatif The MIT License (MIT) @@ -3940,7 +3742,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted --------------------------------------------------------- -instant 0.1.12 - BSD-3-Clause +instant 0.1.13 - BSD-3-Clause https://github.com/sebcrozet/instant Copyright (c) 2019, Sébastien Crozet @@ -4004,7 +3806,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -ipnet 2.5.0 - MIT OR Apache-2.0 +ipnet 2.9.0 - MIT OR Apache-2.0 https://github.com/krisprice/ipnet Copyright 2017 Juniper Networks, Inc. @@ -4046,44 +3848,38 @@ SOFTWARE. --------------------------------------------------------- -is-terminal 0.4.7 - MIT -https://github.com/sunfishcode/is-terminal +is-wsl 0.4.0 - MIT +https://github.com/TheLarkInn/is-wsl -The MIT License (MIT) +MIT License -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: +Copyright (c) 2023 Sean Larkin -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. +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 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. ---------------------------------------------------------- +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. --------------------------------------------------------- -is-wsl 0.4.0 - MIT -https://github.com/TheLarkInn/is-wsl +--------------------------------------------------------- -MIT License +is_terminal_polyfill 1.70.0 - MIT OR Apache-2.0 +https://github.com/polyfill-rs/is_terminal_polyfill -Copyright (c) 2023 Sean Larkin +Copyright (c) Individual contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -4106,7 +3902,7 @@ SOFTWARE. --------------------------------------------------------- -itoa 1.0.4 - MIT OR Apache-2.0 +itoa 1.0.11 - MIT OR Apache-2.0 https://github.com/dtolnay/itoa Permission is hereby granted, free of charge, to any @@ -4136,7 +3932,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -js-sys 0.3.60 - MIT/Apache-2.0 +js-sys 0.3.69 - MIT OR Apache-2.0 https://github.com/rustwasm/wasm-bindgen/tree/master/crates/js-sys Copyright (c) 2014 Alex Crichton @@ -4168,7 +3964,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -keyring 2.0.3 - MIT OR Apache-2.0 +keyring 2.3.3 - MIT OR Apache-2.0 https://github.com/hwchen/keyring-rs Copyright (c) 2016 keyring Developers @@ -4232,7 +4028,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -libc 0.2.153 - MIT OR Apache-2.0 +libc 0.2.155 - MIT OR Apache-2.0 https://github.com/rust-lang/libc Copyright (c) 2014-2020 The Rust Project Developers @@ -4264,41 +4060,39 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -libz-sys 1.1.12 - MIT OR Apache-2.0 -https://github.com/rust-lang/libz-sys +libredox 0.1.3 - MIT +https://gitlab.redox-os.org/redox-os/libredox.git -Copyright (c) 2014 Alex Crichton -Copyright (c) 2020 Josh Triplett +MIT License -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: +Copyright (c) 2023 4lDO2 -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. +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 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. +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. --------------------------------------------------------- --------------------------------------------------------- -link-cplusplus 1.0.9 - MIT OR Apache-2.0 -https://github.com/dtolnay/link-cplusplus +libz-sys 1.1.16 - MIT OR Apache-2.0 +https://github.com/rust-lang/libz-sys + +Copyright (c) 2014 Alex Crichton +Copyright (c) 2020 Josh Triplett Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -4327,7 +4121,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -linux-keyutils 0.2.3 - Apache-2.0 OR MIT +linux-keyutils 0.2.4 - Apache-2.0 OR MIT https://github.com/landhb/linux-keyutils Licensed under either of the following at your discretion: @@ -4359,6 +4153,7 @@ additional terms or conditions. --------------------------------------------------------- linux-raw-sys 0.3.8 - Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT +linux-raw-sys 0.4.14 - Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT https://github.com/sunfishcode/linux-raw-sys Permission is hereby granted, free of charge, to any @@ -4388,7 +4183,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -lock_api 0.4.9 - MIT OR Apache-2.0 +lock_api 0.4.12 - MIT OR Apache-2.0 https://github.com/Amanieu/parking_lot Copyright (c) 2016 The Rust Project Developers @@ -4420,7 +4215,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -log 0.4.18 - MIT OR Apache-2.0 +log 0.4.21 - MIT OR Apache-2.0 https://github.com/rust-lang/log Copyright (c) 2014 The Rust Project Developers @@ -4506,7 +4301,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -memchr 2.5.0 - Unlicense/MIT +memchr 2.7.2 - Unlicense OR MIT https://github.com/BurntSushi/memchr The MIT License (MIT) @@ -4535,6 +4330,7 @@ THE SOFTWARE. --------------------------------------------------------- memoffset 0.7.1 - MIT +memoffset 0.9.1 - MIT https://github.com/Gilnaa/memoffset The MIT License (MIT) @@ -4562,7 +4358,7 @@ SOFTWARE. --------------------------------------------------------- -mime 0.3.16 - MIT/Apache-2.0 +mime 0.3.17 - MIT OR Apache-2.0 https://github.com/hyperium/mime Copyright (c) 2014-2019 Sean McArthur @@ -4588,7 +4384,7 @@ THE SOFTWARE. --------------------------------------------------------- -miniz_oxide 0.7.1 - MIT OR Zlib OR Apache-2.0 +miniz_oxide 0.7.3 - MIT OR Zlib OR Apache-2.0 https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide This library (excluding the miniz C code used for tests) is licensed under the MIT license. The library is based on the miniz C library, of which the parts used are dual-licensed under the [MIT license](https://github.com/Frommi/miniz_oxide/blob/master/miniz/miniz.c#L1) and also the [unlicense](https://github.com/Frommi/miniz_oxide/blob/master/miniz/miniz.c#L577). @@ -4651,7 +4447,7 @@ SOFTWARE. --------------------------------------------------------- -nix 0.26.2 - MIT +nix 0.26.4 - MIT https://github.com/nix-rust/nix The MIT License (MIT) @@ -4679,7 +4475,7 @@ THE SOFTWARE. --------------------------------------------------------- -ntapi 0.4.0 - Apache-2.0 OR MIT +ntapi 0.4.1 - Apache-2.0 OR MIT https://github.com/MSxDOS/ntapi Permission is hereby granted, free of charge, to any person obtaining a copy @@ -4703,7 +4499,7 @@ SOFTWARE. --------------------------------------------------------- -num 0.4.0 - MIT OR Apache-2.0 +num 0.4.3 - MIT OR Apache-2.0 https://github.com/rust-num/num Copyright (c) 2014 The Rust Project Developers @@ -4735,7 +4531,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -num-bigint 0.4.3 - MIT OR Apache-2.0 +num-bigint 0.4.5 - MIT OR Apache-2.0 https://github.com/rust-num/num-bigint Copyright (c) 2014 The Rust Project Developers @@ -4767,7 +4563,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -num-complex 0.4.2 - MIT OR Apache-2.0 +num-complex 0.4.6 - MIT OR Apache-2.0 https://github.com/rust-num/num-complex Copyright (c) 2014 The Rust Project Developers @@ -4799,7 +4595,33 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -num-integer 0.1.45 - MIT OR Apache-2.0 +num-conv 0.1.0 - MIT OR Apache-2.0 +https://github.com/jhpratt/num-conv + +Copyright (c) 2023 Jacob Pratt + +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. +--------------------------------------------------------- + +--------------------------------------------------------- + +num-integer 0.1.46 - MIT OR Apache-2.0 https://github.com/rust-num/num-integer Copyright (c) 2014 The Rust Project Developers @@ -4831,7 +4653,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -num-iter 0.1.43 - MIT OR Apache-2.0 +num-iter 0.1.45 - MIT OR Apache-2.0 https://github.com/rust-num/num-iter Copyright (c) 2014 The Rust Project Developers @@ -4863,7 +4685,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -num-rational 0.4.1 - MIT OR Apache-2.0 +num-rational 0.4.2 - MIT OR Apache-2.0 https://github.com/rust-num/num-rational Copyright (c) 2014 The Rust Project Developers @@ -4895,7 +4717,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -num-traits 0.2.15 - MIT OR Apache-2.0 +num-traits 0.2.19 - MIT OR Apache-2.0 https://github.com/rust-num/num-traits Copyright (c) 2014 The Rust Project Developers @@ -4927,7 +4749,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -num_cpus 1.13.1 - MIT OR Apache-2.0 +num_cpus 1.16.0 - MIT OR Apache-2.0 https://github.com/seanmonstar/num_cpus Copyright (c) 2015 @@ -4981,7 +4803,39 @@ SOFTWARE. --------------------------------------------------------- -once_cell 1.17.2 - MIT OR Apache-2.0 +object 0.32.2 - Apache-2.0 OR MIT +https://github.com/gimli-rs/object + +Copyright (c) 2015 The Gimli 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 +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. +--------------------------------------------------------- + +--------------------------------------------------------- + +once_cell 1.19.0 - MIT OR Apache-2.0 https://github.com/matklad/once_cell Permission is hereby granted, free of charge, to any @@ -5011,7 +4865,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -open 4.1.0 - MIT +open 4.2.0 - MIT https://github.com/Byron/open-rs The MIT License (MIT) @@ -5042,7 +4896,7 @@ OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -openssl 0.10.60 - Apache-2.0 +openssl 0.10.64 - Apache-2.0 https://github.com/sfackler/rust-openssl Copyright 2011-2017 Google Inc. @@ -5064,7 +4918,7 @@ limitations under the License. --------------------------------------------------------- -openssl-macros 0.1.0 - MIT/Apache-2.0 +openssl-macros 0.1.1 - MIT/Apache-2.0 This software is released under the MIT license: @@ -5121,7 +4975,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -openssl-sys 0.9.96 - MIT +openssl-sys 0.9.102 - MIT https://github.com/sfackler/rust-openssl The MIT License (MIT) @@ -6189,7 +6043,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -os_info 3.7.0 - MIT +os_info 3.8.2 - MIT https://github.com/stanislav-tkach/os_info The MIT License (MIT) @@ -6217,7 +6071,7 @@ SOFTWARE. --------------------------------------------------------- -parking 2.0.0 - Apache-2.0 OR MIT +parking 2.2.0 - Apache-2.0 OR MIT https://github.com/smol-rs/parking Permission is hereby granted, free of charge, to any @@ -6247,7 +6101,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -parking_lot 0.12.1 - MIT OR Apache-2.0 +parking_lot 0.12.2 - MIT OR Apache-2.0 https://github.com/Amanieu/parking_lot Copyright (c) 2016 The Rust Project Developers @@ -6279,7 +6133,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -parking_lot_core 0.9.3 - MIT OR Apache-2.0 +parking_lot_core 0.9.10 - MIT OR Apache-2.0 https://github.com/Amanieu/parking_lot Copyright (c) 2016 The Rust Project Developers @@ -6311,7 +6165,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -paste 1.0.9 - MIT OR Apache-2.0 +paste 1.0.15 - MIT OR Apache-2.0 https://github.com/dtolnay/paste Permission is hereby granted, free of charge, to any @@ -6371,7 +6225,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -percent-encoding 2.2.0 - MIT OR Apache-2.0 +percent-encoding 2.3.1 - MIT OR Apache-2.0 https://github.com/servo/rust-url/ Copyright (c) 2013-2022 The rust-url developers @@ -6403,7 +6257,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -pin-project 1.1.0 - Apache-2.0 OR MIT +pin-project 1.1.5 - Apache-2.0 OR MIT https://github.com/taiki-e/pin-project Permission is hereby granted, free of charge, to any @@ -6433,7 +6287,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -pin-project-internal 1.1.0 - Apache-2.0 OR MIT +pin-project-internal 1.1.5 - Apache-2.0 OR MIT https://github.com/taiki-e/pin-project Permission is hereby granted, free of charge, to any @@ -6463,7 +6317,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -pin-project-lite 0.2.9 - Apache-2.0 OR MIT +pin-project-lite 0.2.14 - Apache-2.0 OR MIT https://github.com/taiki-e/pin-project-lite Permission is hereby granted, free of charge, to any @@ -6525,7 +6379,37 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -pkg-config 0.3.25 - MIT OR Apache-2.0 +piper 0.2.2 - MIT OR Apache-2.0 +https://github.com/smol-rs/piper + +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. +--------------------------------------------------------- + +--------------------------------------------------------- + +pkg-config 0.3.30 - MIT OR Apache-2.0 https://github.com/rust-lang/pkg-config-rs Copyright (c) 2014 Alex Crichton @@ -6557,7 +6441,8 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -polling 2.3.0 - Apache-2.0 OR MIT +polling 2.8.0 - Apache-2.0 OR MIT +polling 3.7.0 - Apache-2.0 OR MIT https://github.com/smol-rs/polling Permission is hereby granted, free of charge, to any @@ -6587,7 +6472,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -portable-atomic 1.3.3 - Apache-2.0 OR MIT +portable-atomic 1.6.0 - Apache-2.0 OR MIT https://github.com/taiki-e/portable-atomic Permission is hereby granted, free of charge, to any @@ -6617,7 +6502,33 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -ppv-lite86 0.2.16 - MIT/Apache-2.0 +powerfmt 0.2.0 - MIT OR Apache-2.0 +https://github.com/jhpratt/powerfmt + +Copyright (c) 2023 Jacob Pratt et al. + +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. +--------------------------------------------------------- + +--------------------------------------------------------- + +ppv-lite86 0.2.17 - MIT/Apache-2.0 https://github.com/cryptocorrosion/cryptocorrosion Copyright (c) 2019 The CryptoCorrosion Contributors @@ -6649,7 +6560,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -proc-macro-crate 1.2.1 - Apache-2.0/MIT +proc-macro-crate 1.3.1 - MIT OR Apache-2.0 https://github.com/bkchr/proc-macro-crate Permission is hereby granted, free of charge, to any @@ -6679,7 +6590,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -proc-macro2 1.0.80 - MIT OR Apache-2.0 +proc-macro2 1.0.83 - MIT OR Apache-2.0 https://github.com/dtolnay/proc-macro2 Permission is hereby granted, free of charge, to any @@ -6709,7 +6620,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -quote 1.0.28 - MIT OR Apache-2.0 +quote 1.0.36 - MIT OR Apache-2.0 https://github.com/dtolnay/quote Permission is hereby granted, free of charge, to any @@ -6874,8 +6785,8 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -redox_syscall 0.2.16 - MIT -redox_syscall 0.3.5 - MIT +redox_syscall 0.4.1 - MIT +redox_syscall 0.5.1 - MIT https://github.com/redox-os/syscall Copyright (c) 2017 Redox OS Developers @@ -6904,7 +6815,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -redox_users 0.4.3 - MIT +redox_users 0.4.5 - MIT https://gitlab.redox-os.org/redox-os/users The MIT License (MIT) @@ -6932,7 +6843,7 @@ SOFTWARE. --------------------------------------------------------- -regex 1.8.3 - MIT OR Apache-2.0 +regex 1.10.4 - MIT OR Apache-2.0 https://github.com/rust-lang/regex Copyright (c) 2014 The Rust Project Developers @@ -6964,7 +6875,39 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -regex-syntax 0.7.2 - MIT OR Apache-2.0 +regex-automata 0.4.6 - MIT OR Apache-2.0 +https://github.com/rust-lang/regex/tree/master/regex-automata + +Copyright (c) 2014 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 +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. +--------------------------------------------------------- + +--------------------------------------------------------- + +regex-syntax 0.8.3 - MIT OR Apache-2.0 https://github.com/rust-lang/regex/tree/master/regex-syntax Copyright (c) 2014 The Rust Project Developers @@ -6996,7 +6939,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -reqwest 0.11.22 - MIT OR Apache-2.0 +reqwest 0.11.27 - MIT OR Apache-2.0 https://github.com/seanmonstar/reqwest Copyright (c) 2016 Sean McArthur @@ -7022,7 +6965,7 @@ THE SOFTWARE. --------------------------------------------------------- -rmp 0.8.11 - MIT +rmp 0.8.14 - MIT https://github.com/3Hren/msgpack-rust MIT License @@ -7050,7 +6993,7 @@ SOFTWARE. --------------------------------------------------------- -rmp-serde 1.1.1 - MIT +rmp-serde 1.3.0 - MIT https://github.com/3Hren/msgpack-rust MIT License @@ -7078,7 +7021,7 @@ SOFTWARE. --------------------------------------------------------- -russh 6a15199c784c0b6d171a6fec09ed730a5cd1350d +russh fd4f608a83753f9f3e137f95600faffede71cf65 https://github.com/microsoft/vscode-russh Apache License @@ -7286,7 +7229,7 @@ Apache License --------------------------------------------------------- -russh-cryptovec 6a15199c784c0b6d171a6fec09ed730a5cd1350d +russh-cryptovec fd4f608a83753f9f3e137f95600faffede71cf65 https://github.com/microsoft/vscode-russh Apache License @@ -7494,7 +7437,7 @@ Apache License --------------------------------------------------------- -russh-keys 6a15199c784c0b6d171a6fec09ed730a5cd1350d +russh-keys fd4f608a83753f9f3e137f95600faffede71cf65 https://github.com/microsoft/vscode-russh Apache License @@ -7702,8 +7645,10 @@ Apache License --------------------------------------------------------- -rustix 0.37.25 - Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT -https://github.com/bytecodealliance/rustix +rustc-demangle 0.1.24 - MIT/Apache-2.0 +https://github.com/rust-lang/rustc-demangle + +Copyright (c) 2014 Alex Crichton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -7732,46 +7677,9 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -ryu 1.0.11 - Apache-2.0 OR BSL-1.0 -https://github.com/dtolnay/ryu - - -Licensed under either of Apache License, Version -2.0 (LICENSE-APACHE) or Boost Software License 1.0 (LICENSE-BOOST) at your -option. - - -
- - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in this crate by you, as defined in the Apache-2.0 license, shall -be dual licensed as above, without any additional terms or conditions. - ---------------------------------------------------------- - ---------------------------------------------------------- - -schannel 0.1.20 - MIT -https://github.com/steffengy/schannel-rs - -The MIT License (MIT) - -Copyright (c) 2015 steffengy - -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. ---------------------------------------------------------- - ---------------------------------------------------------- - -scopeguard 1.1.0 - MIT/Apache-2.0 -https://github.com/bluss/scopeguard - -Copyright (c) 2016-2019 Ulrik Sverdrup "bluss" and scopeguard developers +rustix 0.37.27 - Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT +rustix 0.38.34 - Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT +https://github.com/bytecodealliance/rustix Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -7800,8 +7708,62 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -scratch 1.0.7 - MIT OR Apache-2.0 -https://github.com/dtolnay/scratch +rustls-pemfile 1.0.4 - Apache-2.0 OR ISC OR MIT +https://github.com/rustls/pemfile + +rustls-pemfile is distributed under the following three licenses: + +- Apache License version 2.0. +- MIT license. +- ISC license. + +These are included as LICENSE-APACHE, LICENSE-MIT and LICENSE-ISC +respectively. You may use this software under the terms of any +of these licenses, at your option. +--------------------------------------------------------- + +--------------------------------------------------------- + +ryu 1.0.18 - Apache-2.0 OR BSL-1.0 +https://github.com/dtolnay/ryu + + +Licensed under either of Apache License, Version +2.0 (LICENSE-APACHE) or Boost Software License 1.0 (LICENSE-BOOST) at your +option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + +--------------------------------------------------------- + +--------------------------------------------------------- + +schannel 0.1.23 - MIT +https://github.com/steffengy/schannel-rs + +The MIT License (MIT) + +Copyright (c) 2015 steffengy + +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. +--------------------------------------------------------- + +--------------------------------------------------------- + +scopeguard 1.2.0 - MIT OR Apache-2.0 +https://github.com/bluss/scopeguard + +Copyright (c) 2016-2019 Ulrik Sverdrup "bluss" and scopeguard developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -7862,7 +7824,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -security-framework 2.7.0 - MIT OR Apache-2.0 +security-framework 2.11.0 - MIT OR Apache-2.0 https://github.com/kornelski/rust-security-framework The MIT License (MIT) @@ -7889,7 +7851,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -security-framework-sys 2.6.1 - MIT OR Apache-2.0 +security-framework-sys 2.11.0 - MIT OR Apache-2.0 https://github.com/kornelski/rust-security-framework The MIT License (MIT) @@ -7916,7 +7878,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -serde 1.0.163 - MIT OR Apache-2.0 +serde 1.0.202 - MIT OR Apache-2.0 https://github.com/serde-rs/serde Permission is hereby granted, free of charge, to any @@ -7946,7 +7908,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -serde_bytes 0.11.9 - MIT OR Apache-2.0 +serde_bytes 0.11.14 - MIT OR Apache-2.0 https://github.com/serde-rs/bytes Permission is hereby granted, free of charge, to any @@ -7976,7 +7938,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -serde_derive 1.0.163 - MIT OR Apache-2.0 +serde_derive 1.0.202 - MIT OR Apache-2.0 https://github.com/serde-rs/serde Permission is hereby granted, free of charge, to any @@ -8006,7 +7968,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -serde_json 1.0.96 - MIT OR Apache-2.0 +serde_json 1.0.117 - MIT OR Apache-2.0 https://github.com/serde-rs/json Permission is hereby granted, free of charge, to any @@ -8036,7 +7998,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -serde_repr 0.1.9 - MIT OR Apache-2.0 +serde_repr 0.1.19 - MIT OR Apache-2.0 https://github.com/dtolnay/serde-repr Permission is hereby granted, free of charge, to any @@ -8098,7 +8060,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -sha1 0.10.5 - MIT OR Apache-2.0 +sha1 0.10.6 - MIT OR Apache-2.0 https://github.com/RustCrypto/hashes All crates in this repository are licensed under either of @@ -8193,7 +8155,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted --------------------------------------------------------- -sha2 0.10.6 - MIT OR Apache-2.0 +sha2 0.10.8 - MIT OR Apache-2.0 https://github.com/RustCrypto/hashes All crates in this repository are licensed under either of @@ -8352,39 +8314,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -signal-hook 0.3.15 - Apache-2.0/MIT -https://github.com/vorner/signal-hook - -Copyright (c) 2017 tokio-jsonrpc 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 -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. ---------------------------------------------------------- - ---------------------------------------------------------- - -signal-hook-registry 1.4.0 - Apache-2.0/MIT +signal-hook-registry 1.4.2 - Apache-2.0/MIT https://github.com/vorner/signal-hook Copyright (c) 2017 tokio-jsonrpc developers @@ -8416,7 +8346,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -slab 0.4.7 - MIT +slab 0.4.9 - MIT https://github.com/tokio-rs/slab The MIT License (MIT) @@ -8450,7 +8380,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -smallvec 1.10.0 - MIT OR Apache-2.0 +smallvec 1.13.2 - MIT OR Apache-2.0 https://github.com/servo/rust-smallvec Copyright (c) 2018 The Servo Project Developers @@ -8482,7 +8412,8 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -socket2 0.4.9 - MIT OR Apache-2.0 +socket2 0.4.10 - MIT OR Apache-2.0 +socket2 0.5.7 - MIT OR Apache-2.0 https://github.com/rust-lang/socket2 Copyright (c) 2014 Alex Crichton @@ -8542,7 +8473,7 @@ SOFTWARE. --------------------------------------------------------- -strsim 0.10.0 - MIT +strsim 0.11.1 - MIT https://github.com/rapidfuzz/strsim-rs The MIT License (MIT) @@ -8572,7 +8503,7 @@ SOFTWARE. --------------------------------------------------------- -subtle 2.4.1 - BSD-3-Clause +subtle 2.5.0 - BSD-3-Clause https://github.com/dalek-cryptography/subtle Copyright (c) 2016-2017 Isis Agora Lovecruft, Henry de Valence. All rights reserved. @@ -8607,8 +8538,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- -syn 1.0.103 - MIT OR Apache-2.0 -syn 2.0.18 - MIT OR Apache-2.0 +syn 1.0.109 - MIT OR Apache-2.0 +syn 2.0.65 - MIT OR Apache-2.0 https://github.com/dtolnay/syn Permission is hereby granted, free of charge, to any @@ -8638,7 +8569,190 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -sysinfo 0.29.0 - MIT +sync_wrapper 0.1.2 - Apache-2.0 +https://github.com/Actyx/sync_wrapper + +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 +--------------------------------------------------------- + +--------------------------------------------------------- + +sysinfo 0.29.11 - MIT https://github.com/GuillaumeGomez/sysinfo The MIT License (MIT) @@ -8730,7 +8844,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -tar 0.4.38 - MIT/Apache-2.0 +tar 0.4.40 - MIT/Apache-2.0 https://github.com/alexcrichton/tar-rs Copyright (c) 2014 Alex Crichton @@ -8762,7 +8876,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -tempfile 3.5.0 - MIT OR Apache-2.0 +tempfile 3.10.1 - MIT OR Apache-2.0 https://github.com/Stebalien/tempfile Copyright (c) 2015 Steven Allen @@ -8783,46 +8897,18 @@ 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. ---------------------------------------------------------- - ---------------------------------------------------------- - -termcolor 1.2.0 - Unlicense OR MIT -https://github.com/BurntSushi/termcolor - -The MIT License (MIT) - -Copyright (c) 2015 Andrew Gallant - -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. +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. --------------------------------------------------------- --------------------------------------------------------- -thiserror 1.0.40 - MIT OR Apache-2.0 +thiserror 1.0.61 - MIT OR Apache-2.0 https://github.com/dtolnay/thiserror Permission is hereby granted, free of charge, to any @@ -8852,7 +8938,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -thiserror-impl 1.0.40 - MIT OR Apache-2.0 +thiserror-impl 1.0.61 - MIT OR Apache-2.0 https://github.com/dtolnay/thiserror Permission is hereby granted, free of charge, to any @@ -8882,7 +8968,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -time 0.3.21 - MIT OR Apache-2.0 +time 0.3.36 - MIT OR Apache-2.0 https://github.com/time-rs/time Copyright (c) 2024 Jacob Pratt et al. @@ -8908,7 +8994,7 @@ SOFTWARE. --------------------------------------------------------- -time-core 0.1.1 - MIT OR Apache-2.0 +time-core 0.1.2 - MIT OR Apache-2.0 https://github.com/time-rs/time Copyright (c) 2024 Jacob Pratt et al. @@ -8946,7 +9032,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -tinyvec_macros 0.1.0 - MIT OR Apache-2.0 OR Zlib +tinyvec_macros 0.1.1 - MIT OR Apache-2.0 OR Zlib https://github.com/Soveu/tinyvec_macros MIT License @@ -8974,70 +9060,58 @@ SOFTWARE. --------------------------------------------------------- -tokio 1.28.2 - MIT +tokio 1.37.0 - MIT https://github.com/tokio-rs/tokio -The MIT License (MIT) +MIT License -Copyright (c) 2023 Tokio Contributors +Copyright (c) Tokio Contributors -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: +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 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. +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. --------------------------------------------------------- --------------------------------------------------------- -tokio-macros 2.1.0 - MIT +tokio-macros 2.2.0 - MIT https://github.com/tokio-rs/tokio -The MIT License (MIT) +MIT License -Copyright (c) 2023 Tokio Contributors +Copyright (c) Tokio Contributors -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: +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 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. +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. --------------------------------------------------------- --------------------------------------------------------- @@ -9076,36 +9150,30 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -tokio-stream 0.1.11 - MIT +tokio-stream 0.1.15 - MIT https://github.com/tokio-rs/tokio -The MIT License (MIT) +MIT License -Copyright (c) 2023 Tokio Contributors +Copyright (c) Tokio Contributors -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: +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 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. +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. --------------------------------------------------------- --------------------------------------------------------- @@ -9139,41 +9207,61 @@ THE SOFTWARE. --------------------------------------------------------- -tokio-util 0.7.8 - MIT +tokio-util 0.7.11 - MIT https://github.com/tokio-rs/tokio -The MIT License (MIT) +MIT License -Copyright (c) 2023 Tokio Contributors +Copyright (c) Tokio Contributors -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: +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 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. +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. +--------------------------------------------------------- + +--------------------------------------------------------- + +toml_datetime 0.6.6 - MIT OR Apache-2.0 +https://github.com/toml-rs/toml + +Copyright (c) Individual contributors + +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. --------------------------------------------------------- --------------------------------------------------------- -toml 0.5.9 - MIT/Apache-2.0 +toml_edit 0.19.15 - MIT OR Apache-2.0 https://github.com/toml-rs/toml Copyright (c) Individual contributors @@ -9233,7 +9321,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -tracing 0.1.37 - MIT +tracing 0.1.40 - MIT https://github.com/tokio-rs/tracing The MIT License (MIT) @@ -9267,7 +9355,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -tracing-attributes 0.1.23 - MIT +tracing-attributes 0.1.27 - MIT https://github.com/tokio-rs/tracing The MIT License (MIT) @@ -9301,7 +9389,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -tracing-core 0.1.30 - MIT +tracing-core 0.1.32 - MIT https://github.com/tokio-rs/tracing The MIT License (MIT) @@ -9335,7 +9423,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -try-lock 0.2.3 - MIT +try-lock 0.2.5 - MIT https://github.com/seanmonstar/try-lock The MIT License (MIT) @@ -9419,7 +9507,7 @@ MIT License --------------------------------------------------------- -typenum 1.15.0 - MIT OR Apache-2.0 +typenum 1.17.0 - MIT OR Apache-2.0 https://github.com/paholg/typenum MIT OR Apache-2.0 @@ -9427,7 +9515,7 @@ MIT OR Apache-2.0 --------------------------------------------------------- -uds_windows 1.0.2 - MIT +uds_windows 1.1.0 - MIT https://github.com/haraldh/rust_uds_windows MIT License @@ -9455,7 +9543,7 @@ MIT License --------------------------------------------------------- -unicode-bidi 0.3.8 - MIT OR Apache-2.0 +unicode-bidi 0.3.15 - MIT OR Apache-2.0 https://github.com/servo/unicode-bidi Copyright (c) 2015 The Rust Project Developers @@ -9487,7 +9575,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -unicode-ident 1.0.5 - (MIT OR Apache-2.0) AND Unicode-DFS-2016 +unicode-ident 1.0.12 - (MIT OR Apache-2.0) AND Unicode-DFS-2016 https://github.com/dtolnay/unicode-ident Permission is hereby granted, free of charge, to any @@ -9517,7 +9605,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -unicode-normalization 0.1.22 - MIT/Apache-2.0 +unicode-normalization 0.1.23 - MIT/Apache-2.0 https://github.com/unicode-rs/unicode-normalization Copyright (c) 2015 The Rust Project Developers @@ -9549,7 +9637,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -unicode-width 0.1.10 - MIT/Apache-2.0 +unicode-width 0.1.12 - MIT OR Apache-2.0 https://github.com/unicode-rs/unicode-width Copyright (c) 2015 The Rust Project Developers @@ -9613,7 +9701,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -url 2.3.1 - MIT OR Apache-2.0 +url 2.5.0 - MIT OR Apache-2.0 https://github.com/servo/rust-url Copyright (c) 2013-2022 The rust-url developers @@ -9736,7 +9824,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -uuid 1.4.1 - Apache-2.0 OR MIT +uuid 1.8.0 - Apache-2.0 OR MIT https://github.com/uuid-rs/uuid Copyright (c) 2014 The Rust Project Developers @@ -9827,7 +9915,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -waker-fn 1.1.0 - Apache-2.0 OR MIT +waker-fn 1.2.0 - Apache-2.0 OR MIT https://github.com/smol-rs/waker-fn Permission is hereby granted, free of charge, to any @@ -9857,7 +9945,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -want 0.3.0 - MIT +want 0.3.1 - MIT https://github.com/seanmonstar/want The MIT License (MIT) @@ -9887,7 +9975,7 @@ THE SOFTWARE. wasi 0.11.0+wasi-snapshot-preview1 - Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT wasi 0.9.0+wasi-snapshot-preview1 - Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT -https://github.com/bytecodealliance/wasi +https://github.com/bytecodealliance/wasi-rs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -9916,7 +10004,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -wasm-bindgen 0.2.83 - MIT/Apache-2.0 +wasm-bindgen 0.2.92 - MIT OR Apache-2.0 https://github.com/rustwasm/wasm-bindgen Copyright (c) 2014 Alex Crichton @@ -9948,7 +10036,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -wasm-bindgen-backend 0.2.83 - MIT/Apache-2.0 +wasm-bindgen-backend 0.2.92 - MIT OR Apache-2.0 https://github.com/rustwasm/wasm-bindgen/tree/master/crates/backend Copyright (c) 2014 Alex Crichton @@ -9980,7 +10068,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -wasm-bindgen-futures 0.4.33 - MIT/Apache-2.0 +wasm-bindgen-futures 0.4.42 - MIT OR Apache-2.0 https://github.com/rustwasm/wasm-bindgen/tree/master/crates/futures Copyright (c) 2014 Alex Crichton @@ -10012,7 +10100,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -wasm-bindgen-macro 0.2.83 - MIT/Apache-2.0 +wasm-bindgen-macro 0.2.92 - MIT OR Apache-2.0 https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro Copyright (c) 2014 Alex Crichton @@ -10044,7 +10132,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -wasm-bindgen-macro-support 0.2.83 - MIT/Apache-2.0 +wasm-bindgen-macro-support 0.2.92 - MIT OR Apache-2.0 https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro-support Copyright (c) 2014 Alex Crichton @@ -10076,7 +10164,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -wasm-bindgen-shared 0.2.83 - MIT/Apache-2.0 +wasm-bindgen-shared 0.2.92 - MIT OR Apache-2.0 https://github.com/rustwasm/wasm-bindgen/tree/master/crates/shared Copyright (c) 2014 Alex Crichton @@ -10108,7 +10196,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -wasm-streams 0.3.0 - MIT OR Apache-2.0 +wasm-streams 0.4.0 - MIT OR Apache-2.0 https://github.com/MattiasBuelens/wasm-streams/ Permission is hereby granted, free of charge, to any @@ -10138,7 +10226,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -web-sys 0.3.60 - MIT/Apache-2.0 +web-sys 0.3.69 - MIT OR Apache-2.0 https://github.com/rustwasm/wasm-bindgen/tree/master/crates/web-sys Copyright (c) 2014 Alex Crichton @@ -10170,12 +10258,10 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -wepoll-ffi 0.1.2 - MIT OR Apache-2.0 OR BSD-2-Clause -https://github.com/aclysma/wepoll-ffi - -MIT License +winapi 0.3.9 - MIT/Apache-2.0 +https://github.com/retep998/winapi-rs -Copyright (c) 2019-2020 Philip Degarmo and other wepoll-ffi contributors +Copyright (c) 2015-2018 The winapi-rs 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 @@ -10198,7 +10284,7 @@ SOFTWARE. --------------------------------------------------------- -winapi 0.3.9 - MIT/Apache-2.0 +winapi-i686-pc-windows-gnu 0.4.0 - MIT/Apache-2.0 https://github.com/retep998/winapi-rs Copyright (c) 2015-2018 The winapi-rs Developers @@ -10224,7 +10310,7 @@ SOFTWARE. --------------------------------------------------------- -winapi-i686-pc-windows-gnu 0.4.0 - MIT/Apache-2.0 +winapi-x86_64-pc-windows-gnu 0.4.0 - MIT/Apache-2.0 https://github.com/retep998/winapi-rs Copyright (c) 2015-2018 The winapi-rs Developers @@ -10250,61 +10336,36 @@ SOFTWARE. --------------------------------------------------------- -winapi-util 0.1.5 - Unlicense/MIT -https://github.com/BurntSushi/winapi-util - -The MIT License (MIT) - -Copyright (c) 2017 Andrew Gallant - -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. ---------------------------------------------------------- - ---------------------------------------------------------- +windows-core 0.52.0 - MIT OR Apache-2.0 +https://github.com/microsoft/windows-rs -winapi-x86_64-pc-windows-gnu 0.4.0 - MIT/Apache-2.0 -https://github.com/retep998/winapi-rs +MIT License -Copyright (c) 2015-2018 The winapi-rs Developers + Copyright (c) Microsoft Corporation. -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: + 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 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. + 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 --------------------------------------------------------- --------------------------------------------------------- -windows 0.48.0 - MIT OR Apache-2.0 +windows-sys 0.48.0 - MIT OR Apache-2.0 +windows-sys 0.52.0 - MIT OR Apache-2.0 https://github.com/microsoft/windows-rs MIT License @@ -10332,9 +10393,8 @@ MIT License --------------------------------------------------------- -windows-sys 0.36.1 - MIT OR Apache-2.0 -windows-sys 0.45.0 - MIT OR Apache-2.0 -windows-sys 0.48.0 - MIT OR Apache-2.0 +windows-targets 0.48.5 - MIT OR Apache-2.0 +windows-targets 0.52.5 - MIT OR Apache-2.0 https://github.com/microsoft/windows-rs MIT License @@ -10362,8 +10422,8 @@ MIT License --------------------------------------------------------- -windows-targets 0.42.2 - MIT OR Apache-2.0 -windows-targets 0.48.0 - MIT OR Apache-2.0 +windows_aarch64_gnullvm 0.48.5 - MIT OR Apache-2.0 +windows_aarch64_gnullvm 0.52.5 - MIT OR Apache-2.0 https://github.com/microsoft/windows-rs MIT License @@ -10391,8 +10451,8 @@ MIT License --------------------------------------------------------- -windows_aarch64_gnullvm 0.42.2 - MIT OR Apache-2.0 -windows_aarch64_gnullvm 0.48.0 - MIT OR Apache-2.0 +windows_aarch64_msvc 0.48.5 - MIT OR Apache-2.0 +windows_aarch64_msvc 0.52.5 - MIT OR Apache-2.0 https://github.com/microsoft/windows-rs MIT License @@ -10420,9 +10480,8 @@ MIT License --------------------------------------------------------- -windows_aarch64_msvc 0.36.1 - MIT OR Apache-2.0 -windows_aarch64_msvc 0.42.2 - MIT OR Apache-2.0 -windows_aarch64_msvc 0.48.0 - MIT OR Apache-2.0 +windows_i686_gnu 0.48.5 - MIT OR Apache-2.0 +windows_i686_gnu 0.52.5 - MIT OR Apache-2.0 https://github.com/microsoft/windows-rs MIT License @@ -10450,9 +10509,7 @@ MIT License --------------------------------------------------------- -windows_i686_gnu 0.36.1 - MIT OR Apache-2.0 -windows_i686_gnu 0.42.2 - MIT OR Apache-2.0 -windows_i686_gnu 0.48.0 - MIT OR Apache-2.0 +windows_i686_gnullvm 0.52.5 - MIT OR Apache-2.0 https://github.com/microsoft/windows-rs MIT License @@ -10480,9 +10537,8 @@ MIT License --------------------------------------------------------- -windows_i686_msvc 0.36.1 - MIT OR Apache-2.0 -windows_i686_msvc 0.42.2 - MIT OR Apache-2.0 -windows_i686_msvc 0.48.0 - MIT OR Apache-2.0 +windows_i686_msvc 0.48.5 - MIT OR Apache-2.0 +windows_i686_msvc 0.52.5 - MIT OR Apache-2.0 https://github.com/microsoft/windows-rs MIT License @@ -10510,9 +10566,8 @@ MIT License --------------------------------------------------------- -windows_x86_64_gnu 0.36.1 - MIT OR Apache-2.0 -windows_x86_64_gnu 0.42.2 - MIT OR Apache-2.0 -windows_x86_64_gnu 0.48.0 - MIT OR Apache-2.0 +windows_x86_64_gnu 0.48.5 - MIT OR Apache-2.0 +windows_x86_64_gnu 0.52.5 - MIT OR Apache-2.0 https://github.com/microsoft/windows-rs MIT License @@ -10540,8 +10595,8 @@ MIT License --------------------------------------------------------- -windows_x86_64_gnullvm 0.42.2 - MIT OR Apache-2.0 -windows_x86_64_gnullvm 0.48.0 - MIT OR Apache-2.0 +windows_x86_64_gnullvm 0.48.5 - MIT OR Apache-2.0 +windows_x86_64_gnullvm 0.52.5 - MIT OR Apache-2.0 https://github.com/microsoft/windows-rs MIT License @@ -10569,9 +10624,8 @@ MIT License --------------------------------------------------------- -windows_x86_64_msvc 0.36.1 - MIT OR Apache-2.0 -windows_x86_64_msvc 0.42.2 - MIT OR Apache-2.0 -windows_x86_64_msvc 0.48.0 - MIT OR Apache-2.0 +windows_x86_64_msvc 0.48.5 - MIT OR Apache-2.0 +windows_x86_64_msvc 0.52.5 - MIT OR Apache-2.0 https://github.com/microsoft/windows-rs MIT License @@ -10599,7 +10653,7 @@ MIT License --------------------------------------------------------- -winnow 0.4.1 - MIT +winnow 0.5.40 - MIT https://github.com/winnow-rs/winnow The MIT License (MIT) @@ -10655,7 +10709,7 @@ THE SOFTWARE. --------------------------------------------------------- -xattr 0.2.3 - MIT/Apache-2.0 +xattr 1.3.1 - MIT/Apache-2.0 https://github.com/Stebalien/xattr Copyright (c) 2015 Steven Allen @@ -10687,7 +10741,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -xdg-home 1.0.0 - MIT +xdg-home 1.1.0 - MIT https://github.com/zeenix/xdg-home The MIT License (MIT) @@ -10733,7 +10787,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -zbus 3.13.1 - MIT +zbus 3.15.2 - MIT https://github.com/dbus2/zbus/ The MIT License (MIT) @@ -10767,7 +10821,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -zbus_macros 3.13.1 - MIT +zbus_macros 3.15.2 - MIT https://github.com/dbus2/zbus/ The MIT License (MIT) @@ -10801,7 +10855,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -zbus_names 2.5.1 - MIT +zbus_names 2.6.1 - MIT https://github.com/dbus2/zbus/ The MIT License (MIT) @@ -10835,7 +10889,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -zeroize 1.3.0 - Apache-2.0 OR MIT +zeroize 1.7.0 - Apache-2.0 OR MIT https://github.com/RustCrypto/utils/tree/master/zeroize All crates licensed under either of @@ -10890,7 +10944,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted --------------------------------------------------------- zip 0.6.6 - MIT -https://github.com/Pr0methean/zip +https://github.com/zip-rs/zip2 The MIT License (MIT) @@ -10913,11 +10967,14 @@ 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. + +Some files in the "tests/data" subdirectory of this repository are under other +licences; see files named LICENSE.*.txt for details. --------------------------------------------------------- --------------------------------------------------------- -zvariant 3.14.0 - MIT +zvariant 3.15.2 - MIT https://github.com/dbus2/zbus/ The MIT License (MIT) @@ -10951,7 +11008,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -zvariant_derive 3.14.0 - MIT +zvariant_derive 3.15.2 - MIT https://github.com/dbus2/zbus/ The MIT License (MIT) diff --git a/cli/src/commands/tunnels.rs b/cli/src/commands/tunnels.rs index 1755dbbfaef..688f603f593 100644 --- a/cli/src/commands/tunnels.rs +++ b/cli/src/commands/tunnels.rs @@ -562,7 +562,7 @@ async fn serve_with_csa( match acquire_singleton(&paths.tunnel_lockfile()).await { Ok(SingletonConnection::Client(stream)) => { debug!(log, "starting as client to singleton"); - if gateway_args.name.is_none() + if gateway_args.name.is_some() || !gateway_args.install_extension.is_empty() || gateway_args.tunnel.tunnel_id.is_some() { diff --git a/extensions/javascript/javascript-language-configuration.json b/extensions/javascript/javascript-language-configuration.json index fb2fb0397d7..f7c332337cb 100644 --- a/extensions/javascript/javascript-language-configuration.json +++ b/extensions/javascript/javascript-language-configuration.json @@ -111,10 +111,10 @@ }, "indentationRules": { "decreaseIndentPattern": { - "pattern": "^((?!.*?/\\*).*\\*\/)?\\s*[\\}\\]\\)].*$" + "pattern": "^\\s*[\\}\\]\\)].*$" }, "increaseIndentPattern": { - "pattern": "^((?!//).)*(\\{([^}\"'`/]*|(\\t|[ ])*//.*)|\\([^)\"'`/]*|\\[[^\\]\"'`/]*)$" + "pattern": "^.*(\\{[^}]*|\\([^)]*|\\[[^\\]]*)$" }, // e.g. * ...| or */| or *-----*/| "unIndentedLinePattern": { diff --git a/extensions/typescript-basics/language-configuration.json b/extensions/typescript-basics/language-configuration.json index 070b8911a82..25a23685738 100644 --- a/extensions/typescript-basics/language-configuration.json +++ b/extensions/typescript-basics/language-configuration.json @@ -129,10 +129,10 @@ }, "indentationRules": { "decreaseIndentPattern": { - "pattern": "^((?!.*?/\\*).*\\*\/)?\\s*[\\}\\]\\)].*$" + "pattern": "^\\s*[\\}\\]\\)].*$" }, "increaseIndentPattern": { - "pattern": "^((?!//).)*(\\{([^}\"'`/]*|(\\t|[ ])*//.*)|\\([^)\"'`/]*|\\[[^\\]\"'`/]*)$" + "pattern": "^.*(\\{[^}]*|\\([^)]*|\\[[^\\]]*)$" }, // e.g. * ...| or */| or *-----*/| "unIndentedLinePattern": { diff --git a/extensions/typescript-language-features/src/configuration/fileSchemes.ts b/extensions/typescript-language-features/src/configuration/fileSchemes.ts index cfc3f66db17..ca268e29e0b 100644 --- a/extensions/typescript-language-features/src/configuration/fileSchemes.ts +++ b/extensions/typescript-language-features/src/configuration/fileSchemes.ts @@ -17,8 +17,13 @@ export const vsls = 'vsls'; export const walkThroughSnippet = 'walkThroughSnippet'; export const vscodeNotebookCell = 'vscode-notebook-cell'; export const officeScript = 'office-script'; + +/** Used for code blocks in chat by vs code core */ export const chatCodeBlock = 'vscode-chat-code-block'; +/** Used for code blocks in chat by copilot. */ +export const chatBackingCodeBlock = 'vscode-copilot-chat-code-block'; + export function getSemanticSupportedSchemes() { if (isWeb() && vscode.workspace.workspaceFolders) { return vscode.workspace.workspaceFolders.map(folder => folder.uri.scheme); @@ -30,6 +35,7 @@ export function getSemanticSupportedSchemes() { walkThroughSnippet, vscodeNotebookCell, chatCodeBlock, + chatBackingCodeBlock, ]; } @@ -42,3 +48,8 @@ export const disabledSchemes = new Set([ github, azurerepos, ]); + +export function isOfScheme(uri: vscode.Uri, ...schemes: string[]): boolean { + const normalizedUriScheme = uri.scheme.toLowerCase(); + return schemes.some(scheme => normalizedUriScheme === scheme); +} diff --git a/extensions/typescript-language-features/src/languageFeatures/workspaceSymbols.ts b/extensions/typescript-language-features/src/languageFeatures/workspaceSymbols.ts index 98995cc6baa..3240c524781 100644 --- a/extensions/typescript-language-features/src/languageFeatures/workspaceSymbols.ts +++ b/extensions/typescript-language-features/src/languageFeatures/workspaceSymbols.ts @@ -94,7 +94,7 @@ class TypeScriptWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvide } const uri = this.client.toResource(item.file); - if (uri.scheme === fileSchemes.chatCodeBlock) { + if (fileSchemes.isOfScheme(uri, fileSchemes.chatCodeBlock, fileSchemes.chatBackingCodeBlock)) { return; } diff --git a/extensions/typescript-language-features/src/tsServer/bufferSyncSupport.ts b/extensions/typescript-language-features/src/tsServer/bufferSyncSupport.ts index 9f5d76f5ac3..87c715982c2 100644 --- a/extensions/typescript-language-features/src/tsServer/bufferSyncSupport.ts +++ b/extensions/typescript-language-features/src/tsServer/bufferSyncSupport.ts @@ -227,7 +227,7 @@ class SyncedBuffer { return tsRoot?.startsWith(inMemoryResourcePrefix) ? undefined : tsRoot; } - return resource.scheme === fileSchemes.officeScript || resource.scheme === fileSchemes.chatCodeBlock ? '/' : undefined; + return fileSchemes.isOfScheme(resource, fileSchemes.officeScript, fileSchemes.chatCodeBlock, fileSchemes.chatBackingCodeBlock) ? '/' : undefined; } public get resource(): vscode.Uri { @@ -752,7 +752,7 @@ export default class BufferSyncSupport extends Disposable { } private shouldValidate(buffer: SyncedBuffer): boolean { - if (buffer.resource.scheme === fileSchemes.chatCodeBlock) { + if (fileSchemes.isOfScheme(buffer.resource, fileSchemes.chatCodeBlock, fileSchemes.chatBackingCodeBlock)) { return false; } diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 51a74ad7b00..868f7cfd4e7 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -8,6 +8,7 @@ "activeComment", "authSession", "defaultChatParticipant", + "chatParticipantPrivate", "chatVariableResolver", "contribViewsRemote", "contribStatusBarItems", diff --git a/product.json b/product.json index ad46ae24e97..d2d3bf7a361 100644 --- a/product.json +++ b/product.json @@ -50,8 +50,8 @@ }, { "name": "ms-vscode.js-debug", - "version": "1.89.0", - "sha256": "2abd9c01f711c0d60d40b722b5bed0930701be173931f3c6251906f692858221", + "version": "1.90.0", + "sha256": "1317dd7d1ac50641c1534a3e957ecbc94349f4fbd897acb916da11eea3208a66", "repo": "https://github.com/microsoft/vscode-js-debug", "metadata": { "id": "25629058-ddac-4e17-abba-74678e126c5d", diff --git a/remote/package.json b/remote/package.json index 3cdd8501efd..b84f5136fb1 100644 --- a/remote/package.json +++ b/remote/package.json @@ -6,6 +6,7 @@ "@microsoft/1ds-core-js": "^3.2.13", "@microsoft/1ds-post-js": "^3.2.13", "@parcel/watcher": "2.1.0", + "@vscode/deviceid": "^0.1.1", "@vscode/iconv-lite-umd": "0.7.0", "@vscode/proxy-agent": "^0.19.0", "@vscode/ripgrep": "^1.15.9", diff --git a/remote/yarn.lock b/remote/yarn.lock index 71e8b408a1f..4241bf03b14 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -53,6 +53,14 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-3.0.0.tgz#d52238c9052d746c9689523e650160e70786bc9a" integrity sha512-OAdBVB7rlwvLD+DiecSAyVKzKVmSfXbouCyM5I6wHGi4MGXIyFqErg1IvyJ7PI1e+GYZuZh7cCHV/c4LA8SKMw== +"@vscode/deviceid@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@vscode/deviceid/-/deviceid-0.1.1.tgz#750e2930a3a8fbf3fd610096a8b915dfdb493c89" + integrity sha512-ErpoMeKKNYAkR1IT3zxB5RtiTqEECdh8fxggupWvzuxpTAX77hwOI2NdJ7um+vupnXRBZVx4ugo0+dVHJWUkag== + dependencies: + fs-extra "^11.2.0" + uuid "^9.0.1" + "@vscode/iconv-lite-umd@0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz#d2f1e0664ee6036408f9743fee264ea0699b0e48" @@ -267,12 +275,21 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== +fs-extra@^11.2.0: + version "11.2.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + github-from-package@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= -graceful-fs@4.2.11: +graceful-fs@4.2.11, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -335,6 +352,15 @@ jschardet@3.0.0: resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882" integrity sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ== +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + kerberos@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/kerberos/-/kerberos-2.0.1.tgz#663b0b46883b4da84495f60f2e9e399a43a33ef5" @@ -600,11 +626,21 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + vscode-oniguruma@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" diff --git a/src/typings/require.d.ts b/src/typings/require.d.ts index f051253046f..7934279012f 100644 --- a/src/typings/require.d.ts +++ b/src/typings/require.d.ts @@ -3,30 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -declare enum LoaderEventType { - LoaderAvailable = 1, - - BeginLoadingScript = 10, - EndLoadingScriptOK = 11, - EndLoadingScriptError = 12, - - BeginInvokeFactory = 21, - EndInvokeFactory = 22, - - NodeBeginEvaluatingScript = 31, - NodeEndEvaluatingScript = 32, - - NodeBeginNativeRequire = 33, - NodeEndNativeRequire = 34, - - CachedDataFound = 60, - CachedDataMissed = 61, - CachedDataRejected = 62, - CachedDataCreated = 63, -} - declare class LoaderEvent { - readonly type: LoaderEventType; + readonly type: number; readonly timestamp: number; readonly detail: string; } diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 76abbb844ec..3614986c445 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -795,7 +795,7 @@ export function isAncestorUsingFlowTo(testChild: Node, testAncestor: Node): bool return true; } - if (node instanceof HTMLElement) { + if (isHTMLElement(node)) { const flowToParentElement = getParentFlowToElement(node); if (flowToParentElement) { node = flowToParentElement; @@ -1148,6 +1148,41 @@ function isCSSStyleRule(rule: CSSRule): rule is CSSStyleRule { return typeof (rule as CSSStyleRule).selectorText === 'string'; } +export function isHTMLElement(e: unknown): e is HTMLElement { + // eslint-disable-next-line no-restricted-syntax + return e instanceof HTMLElement || e instanceof getWindow(e as Node).HTMLElement; +} + +export function isHTMLAnchorElement(e: unknown): e is HTMLAnchorElement { + // eslint-disable-next-line no-restricted-syntax + return e instanceof HTMLAnchorElement || e instanceof getWindow(e as Node).HTMLAnchorElement; +} + +export function isHTMLSpanElement(e: unknown): e is HTMLSpanElement { + // eslint-disable-next-line no-restricted-syntax + return e instanceof HTMLSpanElement || e instanceof getWindow(e as Node).HTMLSpanElement; +} + +export function isHTMLTextAreaElement(e: unknown): e is HTMLTextAreaElement { + // eslint-disable-next-line no-restricted-syntax + return e instanceof HTMLTextAreaElement || e instanceof getWindow(e as Node).HTMLTextAreaElement; +} + +export function isHTMLInputElement(e: unknown): e is HTMLInputElement { + // eslint-disable-next-line no-restricted-syntax + return e instanceof HTMLInputElement || e instanceof getWindow(e as Node).HTMLInputElement; +} + +export function isHTMLButtonElement(e: unknown): e is HTMLButtonElement { + // eslint-disable-next-line no-restricted-syntax + return e instanceof HTMLButtonElement || e instanceof getWindow(e as Node).HTMLButtonElement; +} + +export function isHTMLDivElement(e: unknown): e is HTMLDivElement { + // eslint-disable-next-line no-restricted-syntax + return e instanceof HTMLDivElement || e instanceof getWindow(e as Node).HTMLDivElement; +} + export function isMouseEvent(e: unknown): e is MouseEvent { // eslint-disable-next-line no-restricted-syntax return e instanceof MouseEvent || e instanceof getWindow(e as UIEvent).MouseEvent; @@ -1286,7 +1321,7 @@ class FocusTracker extends Disposable implements IFocusTracker { private _refreshStateHandler: () => void; private static hasFocusWithin(element: HTMLElement | Window): boolean { - if (element instanceof HTMLElement) { + if (isHTMLElement(element)) { const shadowRoot = getShadowRoot(element); const activeElement = (shadowRoot ? shadowRoot.activeElement : element.ownerDocument.activeElement); return isAncestor(activeElement, element); @@ -1312,7 +1347,7 @@ class FocusTracker extends Disposable implements IFocusTracker { const onBlur = () => { if (hasFocus) { loosingFocus = true; - (element instanceof HTMLElement ? getWindow(element) : element).setTimeout(() => { + (isHTMLElement(element) ? getWindow(element) : element).setTimeout(() => { if (loosingFocus) { loosingFocus = false; hasFocus = false; @@ -1335,7 +1370,7 @@ class FocusTracker extends Disposable implements IFocusTracker { this._register(addDisposableListener(element, EventType.FOCUS, onFocus, true)); this._register(addDisposableListener(element, EventType.BLUR, onBlur, true)); - if (element instanceof HTMLElement) { + if (isHTMLElement(element)) { this._register(addDisposableListener(element, EventType.FOCUS_IN, () => this._refreshStateHandler())); this._register(addDisposableListener(element, EventType.FOCUS_OUT, () => this._refreshStateHandler())); } @@ -1488,7 +1523,7 @@ export function hide(...elements: HTMLElement[]): void { function findParentWithAttribute(node: Node | null, attribute: string): HTMLElement | null { while (node && node.nodeType === node.ELEMENT_NODE) { - if (node instanceof HTMLElement && node.hasAttribute(attribute)) { + if (isHTMLElement(node) && node.hasAttribute(attribute)) { return node; } @@ -2304,7 +2339,7 @@ export function h(tag: string, ...args: [] | [attributes: { $: string } & Partia if (children) { for (const c of children) { - if (c instanceof HTMLElement) { + if (isHTMLElement(c)) { el.appendChild(c); } else if (typeof c === 'string') { el.append(c); diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index 05505b768a5..a9b62dd7be5 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -328,7 +328,7 @@ export class ActionBar extends Disposable implements IActionRunner { } // by element - if (indexOrElement instanceof HTMLElement) { + if (DOM.isHTMLElement(indexOrElement)) { while (indexOrElement.parentElement !== this.actionsList) { if (!indexOrElement.parentElement) { return undefined; diff --git a/src/vs/base/browser/ui/contextview/contextview.ts b/src/vs/base/browser/ui/contextview/contextview.ts index c10dda88f89..4f07df5b8f9 100644 --- a/src/vs/base/browser/ui/contextview/contextview.ts +++ b/src/vs/base/browser/ui/contextview/contextview.ts @@ -274,7 +274,7 @@ export class ContextView extends Disposable { let around: IView; // Get the element's position and size (to anchor the view) - if (anchor instanceof HTMLElement) { + if (DOM.isHTMLElement(anchor)) { const elementPosition = DOM.getDomNodePagePosition(anchor); // In areas where zoom is applied to the element or its ancestors, we need to adjust the size of the element diff --git a/src/vs/base/browser/ui/hover/hoverWidget.css b/src/vs/base/browser/ui/hover/hoverWidget.css index 094b16e58be..a1d72c2e581 100644 --- a/src/vs/base/browser/ui/hover/hoverWidget.css +++ b/src/vs/base/browser/ui/hover/hoverWidget.css @@ -171,12 +171,6 @@ display: inline-block; } -.monaco-hover-content { - padding-right: 2px; - padding-bottom: 2px; - box-sizing: border-box; -} - .monaco-hover-content .action-container a { -webkit-user-select: none; user-select: none; diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index 2b297fa6def..214af03716c 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -158,7 +158,7 @@ export class IconLabel extends Disposable { const existingIconNode = this.domNode.element.querySelector('.monaco-icon-label-iconpath'); if (options?.iconPath) { let iconNode; - if (!existingIconNode || !(existingIconNode instanceof HTMLElement)) { + if (!existingIconNode || !(dom.isHTMLElement(existingIconNode))) { iconNode = dom.$('.monaco-icon-label-iconpath'); this.domNode.element.prepend(iconNode); } else { diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 1550e7cc10e..005d34d6738 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd'; -import { $, addDisposableListener, animate, Dimension, getContentHeight, getContentWidth, getTopLeftOffset, getWindow, isAncestor, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom'; +import { $, addDisposableListener, animate, Dimension, getContentHeight, getContentWidth, getTopLeftOffset, getWindow, isAncestor, isHTMLElement, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom'; import { DomEmitter } from 'vs/base/browser/event'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { EventType as TouchEventType, Gesture, GestureEvent } from 'vs/base/browser/touch'; @@ -1384,7 +1384,7 @@ export class ListView implements IListView { const scrollableElement = this.scrollableElement.getDomNode(); let element: HTMLElement | null = target as (HTMLElement | null); - while (element instanceof HTMLElement && element !== this.rowsContainer && scrollableElement.contains(element)) { + while (isHTMLElement(element) && element !== this.rowsContainer && scrollableElement.contains(element)) { const rawIndex = element.getAttribute('data-index'); if (rawIndex) { diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 576a0bfa640..535b245d71d 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IDragAndDropData } from 'vs/base/browser/dnd'; -import { asCssValueWithDefault, createStyleSheet, Dimension, EventHelper, getActiveElement, getWindow, isActiveElement, isMouseEvent } from 'vs/base/browser/dom'; +import { asCssValueWithDefault, createStyleSheet, Dimension, EventHelper, getActiveElement, getWindow, isActiveElement, isHTMLElement, isMouseEvent } from 'vs/base/browser/dom'; import { DomEmitter } from 'vs/base/browser/event'; import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { Gesture } from 'vs/base/browser/touch'; @@ -635,7 +635,7 @@ class DOMFocusController implements IDisposable { const tabIndexElement = focusedDomElement.querySelector('[tabIndex]'); - if (!tabIndexElement || !(tabIndexElement instanceof HTMLElement) || tabIndexElement.tabIndex === -1) { + if (!tabIndexElement || !(isHTMLElement(tabIndexElement)) || tabIndexElement.tabIndex === -1) { return; } diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts index 44fa17be826..dfacef7d6e2 100644 --- a/src/vs/base/browser/ui/sash/sash.ts +++ b/src/vs/base/browser/ui/sash/sash.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { $, append, createStyleSheet, EventHelper, EventLike, getWindow } from 'vs/base/browser/dom'; +import { $, append, createStyleSheet, EventHelper, EventLike, getWindow, isHTMLElement } from 'vs/base/browser/dom'; import { DomEmitter } from 'vs/base/browser/event'; import { EventType, Gesture } from 'vs/base/browser/touch'; import { Delayer } from 'vs/base/common/async'; @@ -670,7 +670,7 @@ export class Sash extends Disposable { private getOrthogonalSash(e: PointerEvent): Sash | undefined { const target = e.initialTarget ?? e.target; - if (!target || !(target instanceof HTMLElement)) { + if (!target || !(isHTMLElement(target))) { return undefined; } diff --git a/src/vs/base/browser/ui/splitview/paneview.ts b/src/vs/base/browser/ui/splitview/paneview.ts index 0b519e43411..a934addd1fb 100644 --- a/src/vs/base/browser/ui/splitview/paneview.ts +++ b/src/vs/base/browser/ui/splitview/paneview.ts @@ -5,7 +5,7 @@ import { isFirefox } from 'vs/base/browser/browser'; import { DataTransfers } from 'vs/base/browser/dnd'; -import { $, addDisposableListener, append, clearNode, EventHelper, EventType, getWindow, trackFocus } from 'vs/base/browser/dom'; +import { $, addDisposableListener, append, clearNode, EventHelper, EventType, getWindow, isHTMLElement, trackFocus } from 'vs/base/browser/dom'; import { DomEmitter } from 'vs/base/browser/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { Gesture, EventType as TouchEventType } from 'vs/base/browser/touch'; @@ -513,7 +513,7 @@ export class PaneView extends Disposable { const eventDisposables = this._register(new DisposableStore()); const onKeyDown = this._register(new DomEmitter(this.element, 'keydown')); - const onHeaderKeyDown = Event.map(Event.filter(onKeyDown.event, e => e.target instanceof HTMLElement && e.target.classList.contains('pane-header'), eventDisposables), e => new StandardKeyboardEvent(e), eventDisposables); + const onHeaderKeyDown = Event.map(Event.filter(onKeyDown.event, e => isHTMLElement(e.target) && e.target.classList.contains('pane-header'), eventDisposables), e => new StandardKeyboardEvent(e), eventDisposables); this._register(Event.filter(onHeaderKeyDown, e => e.keyCode === KeyCode.UpArrow, eventDisposables)(() => this.focusPrevious())); this._register(Event.filter(onHeaderKeyDown, e => e.keyCode === KeyCode.DownArrow, eventDisposables)(() => this.focusNext())); diff --git a/src/vs/base/common/amd.ts b/src/vs/base/common/amd.ts index 2ee86a98646..6d228840331 100644 --- a/src/vs/base/common/amd.ts +++ b/src/vs/base/common/amd.ts @@ -10,6 +10,28 @@ export const isESM = false; // export const isESM = true; // ESM-uncomment-end +export const enum LoaderEventType { + LoaderAvailable = 1, + + BeginLoadingScript = 10, + EndLoadingScriptOK = 11, + EndLoadingScriptError = 12, + + BeginInvokeFactory = 21, + EndInvokeFactory = 22, + + NodeBeginEvaluatingScript = 31, + NodeEndEvaluatingScript = 32, + + NodeBeginNativeRequire = 33, + NodeEndNativeRequire = 34, + + CachedDataFound = 60, + CachedDataMissed = 61, + CachedDataRejected = 62, + CachedDataCreated = 63, +} + export abstract class LoaderStats { abstract get amdLoad(): [string, number][]; abstract get amdInvoke(): [string, number][]; diff --git a/src/vs/base/test/browser/browser.test.ts b/src/vs/base/test/browser/browser.test.ts index da58ddd6a91..115112ff753 100644 --- a/src/vs/base/test/browser/browser.test.ts +++ b/src/vs/base/test/browser/browser.test.ts @@ -4,8 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; import { isMacintosh, isWindows } from 'vs/base/common/platform'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; suite('Browsers', () => { + + ensureNoDisposablesAreLeakedInTestSuite(); + test('all', () => { assert(!(isWindows && isMacintosh)); }); diff --git a/src/vs/base/test/browser/dom.test.ts b/src/vs/base/test/browser/dom.test.ts index f3ad0d55eff..03d618b1f0c 100644 --- a/src/vs/base/test/browser/dom.test.ts +++ b/src/vs/base/test/browser/dom.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { $, asCssValueWithDefault, h, multibyteAwareBtoa, trackAttributes, copyAttributes, disposableWindowInterval, getWindows, getWindowsCount, getWindowId, getWindowById, hasWindow, getWindow, getDocument } from 'vs/base/browser/dom'; +import { $, asCssValueWithDefault, h, multibyteAwareBtoa, trackAttributes, copyAttributes, disposableWindowInterval, getWindows, getWindowsCount, getWindowId, getWindowById, hasWindow, getWindow, getDocument, isHTMLElement } from 'vs/base/browser/dom'; import { ensureCodeWindow, isAuxiliaryWindow, mainWindow } from 'vs/base/browser/window'; import { DeferredPromise, timeout } from 'vs/base/common/async'; import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler'; @@ -85,7 +85,7 @@ suite('dom', () => { test('should build simple nodes', () => { const div = $('div'); assert(div); - assert(div instanceof HTMLElement); + assert(isHTMLElement(div)); assert.strictEqual(div.tagName, 'DIV'); assert(!div.firstChild); }); @@ -93,7 +93,7 @@ suite('dom', () => { test('should build nodes with id', () => { const div = $('div#foo'); assert(div); - assert(div instanceof HTMLElement); + assert(isHTMLElement(div)); assert.strictEqual(div.tagName, 'DIV'); assert.strictEqual(div.id, 'foo'); }); @@ -101,7 +101,7 @@ suite('dom', () => { test('should build nodes with class-name', () => { const div = $('div.foo'); assert(div); - assert(div instanceof HTMLElement); + assert(isHTMLElement(div)); assert.strictEqual(div.tagName, 'DIV'); assert.strictEqual(div.className, 'foo'); }); @@ -136,15 +136,15 @@ suite('dom', () => { suite('h', () => { test('should build simple nodes', () => { const div = h('div'); - assert(div.root instanceof HTMLElement); + assert(isHTMLElement(div.root)); assert.strictEqual(div.root.tagName, 'DIV'); const span = h('span'); - assert(span.root instanceof HTMLElement); + assert(isHTMLElement(span.root)); assert.strictEqual(span.root.tagName, 'SPAN'); const img = h('img'); - assert(img.root instanceof HTMLElement); + assert(isHTMLElement(img.root)); assert.strictEqual(img.root.tagName, 'IMG'); }); diff --git a/src/vs/base/test/browser/iconLabels.test.ts b/src/vs/base/test/browser/iconLabels.test.ts index c076d4ec38e..3972977f65f 100644 --- a/src/vs/base/test/browser/iconLabels.test.ts +++ b/src/vs/base/test/browser/iconLabels.test.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; +import { isHTMLElement } from 'vs/base/browser/dom'; import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; @@ -47,7 +48,7 @@ suite('renderLabelWithIcons', () => { const elementsToString = (elements: Array): string => { return elements - .map(elem => elem instanceof HTMLElement ? elem.outerHTML : elem) + .map(elem => isHTMLElement(elem) ? elem.outerHTML : elem) .reduce((a, b) => a + b, ''); }; diff --git a/src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts b/src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts index 2ea6a9c1df9..30879e441db 100644 --- a/src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts +++ b/src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts @@ -5,11 +5,14 @@ import * as assert from 'assert'; import { MouseWheelClassifier } from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; export type IMouseWheelEvent = [number, number, number]; suite('MouseWheelClassifier', () => { + ensureNoDisposablesAreLeakedInTestSuite(); + test('OSX - Apple Magic Mouse', () => { const testData: IMouseWheelEvent[] = [ [1503409622410, -0.025, 0], diff --git a/src/vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts b/src/vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts index 24d4915cca2..0a4a2dd00db 100644 --- a/src/vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts +++ b/src/vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts @@ -5,8 +5,12 @@ import * as assert from 'assert'; import { ScrollbarState } from 'vs/base/browser/ui/scrollbar/scrollbarState'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; suite('ScrollbarState', () => { + + ensureNoDisposablesAreLeakedInTestSuite(); + test('inflates slider size', () => { const actual = new ScrollbarState(0, 14, 0, 339, 42423, 32787); diff --git a/src/vs/editor/browser/services/hoverService/hoverService.ts b/src/vs/editor/browser/services/hoverService/hoverService.ts index 8c5e7319331..0c554ca039e 100644 --- a/src/vs/editor/browser/services/hoverService/hoverService.ts +++ b/src/vs/editor/browser/services/hoverService/hoverService.ts @@ -12,7 +12,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { HoverWidget } from 'vs/editor/browser/services/hoverService/hoverWidget'; import { IContextViewProvider, IDelegate } from 'vs/base/browser/ui/contextview/contextview'; import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { addDisposableListener, EventType, getActiveElement, isAncestorOfActiveElement, isAncestor, getWindow } from 'vs/base/browser/dom'; +import { addDisposableListener, EventType, getActiveElement, isAncestorOfActiveElement, isAncestor, getWindow, isHTMLElement } from 'vs/base/browser/dom'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { ResultKind } from 'vs/platform/keybinding/common/keybindingResolver'; @@ -90,7 +90,7 @@ export class HoverService extends Disposable implements IHoverService { }, undefined, hoverDisposables); // Set the container explicitly to enable aux window support if (!options.container) { - const targetElement = options.target instanceof HTMLElement ? options.target : options.target.targetElements[0]; + const targetElement = isHTMLElement(options.target) ? options.target : options.target.targetElements[0]; options.container = this._layoutService.getContainer(getWindow(targetElement)); } @@ -259,7 +259,7 @@ export class HoverService extends Disposable implements IHoverService { // track the mouse position const onMouseMove = (e: MouseEvent) => { target.x = e.x + 10; - if ((e.target instanceof HTMLElement) && getHoverTargetElement(e.target, htmlElement) !== htmlElement) { + if ((isHTMLElement(e.target)) && getHoverTargetElement(e.target, htmlElement) !== htmlElement) { hideHover(true, true); } }; @@ -268,7 +268,7 @@ export class HoverService extends Disposable implements IHoverService { hoverPreparation = toDispose; - if ((e.target instanceof HTMLElement) && getHoverTargetElement(e.target as HTMLElement, htmlElement) !== htmlElement) { + if ((isHTMLElement(e.target)) && getHoverTargetElement(e.target as HTMLElement, htmlElement) !== htmlElement) { return; // Do not show hover when the mouse is over another hover target } diff --git a/src/vs/editor/browser/services/hoverService/hoverWidget.ts b/src/vs/editor/browser/services/hoverService/hoverWidget.ts index 163633fa206..ed929bc965c 100644 --- a/src/vs/editor/browser/services/hoverService/hoverWidget.ts +++ b/src/vs/editor/browser/services/hoverService/hoverWidget.ts @@ -150,7 +150,7 @@ export class HoverWidget extends Widget implements IHoverWidget { contentsElement.textContent = options.content; contentsElement.style.whiteSpace = 'pre-wrap'; - } else if (options.content instanceof HTMLElement) { + } else if (dom.isHTMLElement(options.content)) { contentsElement.appendChild(options.content); contentsElement.classList.add('html-hover-contents'); diff --git a/src/vs/editor/browser/services/hoverService/updatableHoverWidget.ts b/src/vs/editor/browser/services/hoverService/updatableHoverWidget.ts index 762b6626aff..3b746de6f43 100644 --- a/src/vs/editor/browser/services/hoverService/updatableHoverWidget.ts +++ b/src/vs/editor/browser/services/hoverService/updatableHoverWidget.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { isHTMLElement } from 'vs/base/browser/dom'; import type { IHoverWidget, IUpdatableHoverContent, IUpdatableHoverOptions } from 'vs/base/browser/ui/hover/hover'; import type { IHoverDelegate, IHoverDelegateOptions, IHoverDelegateTarget } from 'vs/base/browser/ui/hover/hoverDelegate'; import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget'; @@ -33,7 +34,7 @@ export class UpdatableHoverWidget implements IDisposable { } let resolvedContent; - if (content === undefined || isString(content) || content instanceof HTMLElement) { + if (content === undefined || isString(content) || isHTMLElement(content)) { resolvedContent = content; } else if (!isFunction(content.markdown)) { resolvedContent = content.markdown ?? content.markdownNotSupportedFallback; diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 427df7cd3d8..7b49f5b0dea 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -94,6 +94,10 @@ class MinimapOptions { public readonly minimapCharWidth: number; public readonly sectionHeaderFontFamily: string; public readonly sectionHeaderFontSize: number; + /** + * Space in between the characters of the section header (in CSS px) + */ + public readonly sectionHeaderLetterSpacing: number; public readonly sectionHeaderFontColor: RGBA8; public readonly charRenderer: () => MinimapCharRenderer; @@ -139,6 +143,7 @@ class MinimapOptions { this.minimapCharWidth = Constants.BASE_CHAR_WIDTH * this.fontScale; this.sectionHeaderFontFamily = DEFAULT_FONT_FAMILY; this.sectionHeaderFontSize = minimapOpts.sectionHeaderFontSize * pixelRatio; + this.sectionHeaderLetterSpacing = minimapOpts.sectionHeaderLetterSpacing; // intentionally not multiplying by pixelRatio this.sectionHeaderFontColor = MinimapOptions._getSectionHeaderColor(theme, tokensColorTracker.getColor(ColorId.DefaultForeground)); this.charRenderer = createSingleCallFunction(() => MinimapCharRendererFactory.create(this.fontScale, fontInfo.fontFamily)); @@ -196,6 +201,7 @@ class MinimapOptions { && this.minimapLineHeight === other.minimapLineHeight && this.minimapCharWidth === other.minimapCharWidth && this.sectionHeaderFontSize === other.sectionHeaderFontSize + && this.sectionHeaderLetterSpacing === other.sectionHeaderLetterSpacing && this.defaultBackgroundColor && this.defaultBackgroundColor.equals(other.defaultBackgroundColor) && this.backgroundColor && this.backgroundColor.equals(other.backgroundColor) && this.foregroundAlpha === other.foregroundAlpha @@ -1788,6 +1794,7 @@ class InnerMinimap extends Disposable { private _renderSectionHeaders(layout: MinimapLayout) { const minimapLineHeight = this._model.options.minimapLineHeight; const sectionHeaderFontSize = this._model.options.sectionHeaderFontSize; + const sectionHeaderLetterSpacing = this._model.options.sectionHeaderLetterSpacing; const backgroundFillHeight = sectionHeaderFontSize * 1.5; const { canvasInnerWidth } = this._model.options; @@ -1798,7 +1805,8 @@ class InnerMinimap extends Disposable { const separatorStroke = foregroundFill; const canvasContext = this._decorationsCanvas.domNode.getContext('2d')!; - canvasContext.font = sectionHeaderFontSize + 'px ' + this._model.options.sectionHeaderFontFamily; + canvasContext.letterSpacing = sectionHeaderLetterSpacing + 'px'; + canvasContext.font = '500 ' + sectionHeaderFontSize + 'px ' + this._model.options.sectionHeaderFontFamily; canvasContext.strokeStyle = separatorStroke; canvasContext.lineWidth = 0.2; diff --git a/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts index cd5c2e8b606..c3c798529ca 100644 --- a/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts @@ -345,6 +345,12 @@ export class DiffEditorWidget extends DelegatingEditor implements IDiffEditor { const fullWidth = this._rootSizeObserver.width.read(reader); const fullHeight = this._rootSizeObserver.height.read(reader); + if (this._rootSizeObserver.automaticLayout) { + this.elements.root.style.height = '100%'; + } else { + this.elements.root.style.height = fullHeight + 'px'; + } + const sash = this._sash.read(reader); const gutter = this._gutter.read(reader); diff --git a/src/vs/editor/browser/widget/diffEditor/features/gutterFeature.ts b/src/vs/editor/browser/widget/diffEditor/features/gutterFeature.ts index e6ba7e45ce1..e7c76c727cf 100644 --- a/src/vs/editor/browser/widget/diffEditor/features/gutterFeature.ts +++ b/src/vs/editor/browser/widget/diffEditor/features/gutterFeature.ts @@ -278,9 +278,6 @@ class DiffToolBar extends Disposable implements IGutterItemView { // Item might have changed itemHeight = this._elements.buttons.clientHeight; - this._elements.root.style.top = itemRange.start + 'px'; - this._elements.root.style.height = itemRange.length + 'px'; - const middleHeight = itemRange.length / 2 - itemHeight / 2; const margin = itemHeight; diff --git a/src/vs/editor/browser/widget/diffEditor/style.css b/src/vs/editor/browser/widget/diffEditor/style.css index 49ad115e36b..ebb52234658 100644 --- a/src/vs/editor/browser/widget/diffEditor/style.css +++ b/src/vs/editor/browser/widget/diffEditor/style.css @@ -328,6 +328,10 @@ flex-shrink: 0; flex-grow: 0; + & > div { + position: absolute; + } + .gutterItem { opacity: 0; transition: opacity 0.7s; @@ -374,8 +378,7 @@ .actions-container { width: fit-content; border-radius: 4px; - border: 1px var(--vscode-menu-border) solid; - background: var(--vscode-editor-background); + background: var(--vscode-editorGutter-commentRangeForeground); .action-item { &:hover { @@ -383,7 +386,7 @@ } .action-label { - padding: 0.5px 1px; + padding: 1px 2px; } } } diff --git a/src/vs/editor/browser/widget/diffEditor/utils.ts b/src/vs/editor/browser/widget/diffEditor/utils.ts index 3b968353291..76c37c4185d 100644 --- a/src/vs/editor/browser/widget/diffEditor/utils.ts +++ b/src/vs/editor/browser/widget/diffEditor/utils.ts @@ -96,6 +96,9 @@ export class ObservableElementSizeObserver extends Disposable { private readonly _height: ISettableObservable; public get height(): IObservable { return this._height; } + private _automaticLayout: boolean = false; + public get automaticLayout(): boolean { return this._automaticLayout; } + constructor(element: HTMLElement | null, dimension: IDimension | undefined) { super(); @@ -115,6 +118,7 @@ export class ObservableElementSizeObserver extends Disposable { } public setAutomaticLayout(automaticLayout: boolean): void { + this._automaticLayout = automaticLayout; if (automaticLayout) { this.elementSizeObserver.startObserving(); } else { diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index fab223456fe..be4de9dc7c6 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -3071,6 +3071,10 @@ export interface IEditorMinimapOptions { * Font size of section headers. Defaults to 9. */ sectionHeaderFontSize?: number; + /** + * Spacing between the section header characters (in CSS px). Defaults to 1. + */ + sectionHeaderLetterSpacing?: number; } /** @@ -3093,6 +3097,7 @@ class EditorMinimap extends BaseEditorOption 1) { let lastLineNumber: number; @@ -46,7 +47,7 @@ function getPrecedingValidLine(model: IVirtualModel, lineNumber: number, indentR return resultLineNumber; } const text = model.getLineContent(lastLineNumber); - if (indentRulesSupport.shouldIgnore(text) || /^\s+$/.test(text) || text === '') { + if (processedIndentRulesSupport.shouldIgnore(lastLineNumber) || /^\s+$/.test(text) || text === '') { resultLineNumber = lastLineNumber; continue; } @@ -85,6 +86,7 @@ export function getInheritIndentForLine( if (!indentRulesSupport) { return null; } + const processedIndentRulesSupport = new ProcessedIndentRulesSupport(model, indentRulesSupport, languageConfigurationService); if (lineNumber <= 1) { return { @@ -106,7 +108,7 @@ export function getInheritIndentForLine( } } - const precedingUnIgnoredLine = getPrecedingValidLine(model, lineNumber, indentRulesSupport); + const precedingUnIgnoredLine = getPrecedingValidLine(model, lineNumber, processedIndentRulesSupport); if (precedingUnIgnoredLine < 0) { return null; } else if (precedingUnIgnoredLine < 1) { @@ -116,14 +118,15 @@ export function getInheritIndentForLine( }; } - const precedingUnIgnoredLineContent = model.getLineContent(precedingUnIgnoredLine); - if (indentRulesSupport.shouldIncrease(precedingUnIgnoredLineContent) || indentRulesSupport.shouldIndentNextLine(precedingUnIgnoredLineContent)) { + if (processedIndentRulesSupport.shouldIncrease(precedingUnIgnoredLine) || processedIndentRulesSupport.shouldIndentNextLine(precedingUnIgnoredLine)) { + const precedingUnIgnoredLineContent = model.getLineContent(precedingUnIgnoredLine); return { indentation: strings.getLeadingWhitespace(precedingUnIgnoredLineContent), action: IndentAction.Indent, line: precedingUnIgnoredLine }; - } else if (indentRulesSupport.shouldDecrease(precedingUnIgnoredLineContent)) { + } else if (processedIndentRulesSupport.shouldDecrease(precedingUnIgnoredLine)) { + const precedingUnIgnoredLineContent = model.getLineContent(precedingUnIgnoredLine); return { indentation: strings.getLeadingWhitespace(precedingUnIgnoredLineContent), action: null, @@ -150,7 +153,7 @@ export function getInheritIndentForLine( (previousLineIndentMetadata & IndentConsts.INDENT_NEXTLINE_MASK)) { let stopLine = 0; for (let i = previousLine - 1; i > 0; i--) { - if (indentRulesSupport.shouldIndentNextLine(model.getLineContent(i))) { + if (processedIndentRulesSupport.shouldIndentNextLine(i)) { continue; } stopLine = i; @@ -173,17 +176,16 @@ export function getInheritIndentForLine( } else { // search from precedingUnIgnoredLine until we find one whose indent is not temporary for (let i = precedingUnIgnoredLine; i > 0; i--) { - const lineContent = model.getLineContent(i); - if (indentRulesSupport.shouldIncrease(lineContent)) { + if (processedIndentRulesSupport.shouldIncrease(i)) { return { - indentation: strings.getLeadingWhitespace(lineContent), + indentation: strings.getLeadingWhitespace(model.getLineContent(i)), action: IndentAction.Indent, line: i }; - } else if (indentRulesSupport.shouldIndentNextLine(lineContent)) { + } else if (processedIndentRulesSupport.shouldIndentNextLine(i)) { let stopLine = 0; for (let j = i - 1; j > 0; j--) { - if (indentRulesSupport.shouldIndentNextLine(model.getLineContent(i))) { + if (processedIndentRulesSupport.shouldIndentNextLine(i)) { continue; } stopLine = j; @@ -195,9 +197,9 @@ export function getInheritIndentForLine( action: null, line: stopLine + 1 }; - } else if (indentRulesSupport.shouldDecrease(lineContent)) { + } else if (processedIndentRulesSupport.shouldDecrease(i)) { return { - indentation: strings.getLeadingWhitespace(lineContent), + indentation: strings.getLeadingWhitespace(model.getLineContent(i)), action: null, line: i }; @@ -235,8 +237,8 @@ export function getGoodIndentForLine( return null; } + const processedIndentRulesSupport = new ProcessedIndentRulesSupport(virtualModel, indentRulesSupport, languageConfigurationService); const indent = getInheritIndentForLine(autoIndent, virtualModel, lineNumber, undefined, languageConfigurationService); - const lineContent = virtualModel.getLineContent(lineNumber); if (indent) { const inheritLine = indent.line; @@ -268,7 +270,7 @@ export function getGoodIndentForLine( indentation = indentConverter.unshiftIndent(indentation); } - if (indentRulesSupport.shouldDecrease(lineContent)) { + if (processedIndentRulesSupport.shouldDecrease(lineNumber)) { indentation = indentConverter.unshiftIndent(indentation); } @@ -281,7 +283,7 @@ export function getGoodIndentForLine( } } - if (indentRulesSupport.shouldDecrease(lineContent)) { + if (processedIndentRulesSupport.shouldDecrease(lineNumber)) { if (indent.action === IndentAction.Indent) { return indent.indentation; } else { @@ -308,80 +310,44 @@ export function getIndentForEnter( if (autoIndent < EditorAutoIndentStrategy.Full) { return null; } - model.tokenization.forceTokenization(range.startLineNumber); - const lineTokens = model.tokenization.getLineTokens(range.startLineNumber); - const scopedLineTokens = createScopedLineTokens(lineTokens, range.startColumn - 1); - const scopedLineText = scopedLineTokens.getLineContent(); - - let embeddedLanguage = false; - let beforeEnterText: string; - if (scopedLineTokens.firstCharOffset > 0 && lineTokens.getLanguageId(0) !== scopedLineTokens.languageId) { - // we are in the embeded language content - embeddedLanguage = true; // if embeddedLanguage is true, then we don't touch the indentation of current line - beforeEnterText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset); - } else { - beforeEnterText = lineTokens.getLineContent().substring(0, range.startColumn - 1); - } - - let afterEnterText: string; - if (range.isEmpty()) { - afterEnterText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset); - } else { - const endScopedLineTokens = getScopedLineTokens(model, range.endLineNumber, range.endColumn); - afterEnterText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset); - } - - const indentRulesSupport = languageConfigurationService.getLanguageConfiguration(scopedLineTokens.languageId).indentRulesSupport; + const languageId = model.getLanguageIdAtPosition(range.startLineNumber, range.startColumn); + const indentRulesSupport = languageConfigurationService.getLanguageConfiguration(languageId).indentRulesSupport; if (!indentRulesSupport) { return null; } - const beforeEnterResult = beforeEnterText; - const beforeEnterIndent = strings.getLeadingWhitespace(beforeEnterText); - - const virtualModel: IVirtualModel = { - tokenization: { - getLineTokens: (lineNumber: number) => { - return model.tokenization.getLineTokens(lineNumber); - }, - getLanguageId: () => { - return model.getLanguageId(); - }, - getLanguageIdAtPosition: (lineNumber: number, column: number) => { - return model.getLanguageIdAtPosition(lineNumber, column); - }, - }, - getLineContent: (lineNumber: number) => { - if (lineNumber === range.startLineNumber) { - return beforeEnterResult; - } else { - return model.getLineContent(lineNumber); - } - } - }; - - const currentLineIndent = strings.getLeadingWhitespace(lineTokens.getLineContent()); + model.tokenization.forceTokenization(range.startLineNumber); + const indentationContextProcessor = new IndentationContextProcessor(model, languageConfigurationService); + const processedContextTokens = indentationContextProcessor.getProcessedTokenContextAroundRange(range); + const afterEnterProcessedTokens = processedContextTokens.afterRangeProcessedTokens; + const beforeEnterProcessedTokens = processedContextTokens.beforeRangeProcessedTokens; + const beforeEnterIndent = strings.getLeadingWhitespace(beforeEnterProcessedTokens.getLineContent()); + + const virtualModel = createVirtualModelWithModifiedTokensAtLine(model, range.startLineNumber, beforeEnterProcessedTokens); + const languageIsDifferentFromLineStart = isLanguageDifferentFromLineStart(model, range.getStartPosition()); + const currentLine = model.getLineContent(range.startLineNumber); + const currentLineIndent = strings.getLeadingWhitespace(currentLine); const afterEnterAction = getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1, undefined, languageConfigurationService); if (!afterEnterAction) { - const beforeEnter = embeddedLanguage ? currentLineIndent : beforeEnterIndent; + const beforeEnter = languageIsDifferentFromLineStart ? currentLineIndent : beforeEnterIndent; return { beforeEnter: beforeEnter, afterEnter: beforeEnter }; } - let afterEnterIndent = embeddedLanguage ? currentLineIndent : afterEnterAction.indentation; + let afterEnterIndent = languageIsDifferentFromLineStart ? currentLineIndent : afterEnterAction.indentation; if (afterEnterAction.action === IndentAction.Indent) { afterEnterIndent = indentConverter.shiftIndent(afterEnterIndent); } - if (indentRulesSupport.shouldDecrease(afterEnterText)) { + if (indentRulesSupport.shouldDecrease(afterEnterProcessedTokens.getLineContent())) { afterEnterIndent = indentConverter.unshiftIndent(afterEnterIndent); } return { - beforeEnter: embeddedLanguage ? currentLineIndent : beforeEnterIndent, + beforeEnter: languageIsDifferentFromLineStart ? currentLineIndent : beforeEnterIndent, afterEnter: afterEnterIndent }; } @@ -401,33 +367,28 @@ export function getIndentActionForType( if (autoIndent < EditorAutoIndentStrategy.Full) { return null; } - const scopedLineTokens = getScopedLineTokens(model, range.startLineNumber, range.startColumn); - - if (scopedLineTokens.firstCharOffset) { + const languageIsDifferentFromLineStart = isLanguageDifferentFromLineStart(model, range.getStartPosition()); + if (languageIsDifferentFromLineStart) { // this line has mixed languages and indentation rules will not work return null; } - const indentRulesSupport = languageConfigurationService.getLanguageConfiguration(scopedLineTokens.languageId).indentRulesSupport; + const languageId = model.getLanguageIdAtPosition(range.startLineNumber, range.startColumn); + const indentRulesSupport = languageConfigurationService.getLanguageConfiguration(languageId).indentRulesSupport; if (!indentRulesSupport) { return null; } - const scopedLineText = scopedLineTokens.getLineContent(); - const beforeTypeText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset); - - // selection support - let afterTypeText: string; - if (range.isEmpty()) { - afterTypeText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset); - } else { - const endScopedLineTokens = getScopedLineTokens(model, range.endLineNumber, range.endColumn); - afterTypeText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset); - } + const indentationContextProcessor = new IndentationContextProcessor(model, languageConfigurationService); + const processedContextTokens = indentationContextProcessor.getProcessedTokenContextAroundRange(range); + const beforeRangeText = processedContextTokens.beforeRangeProcessedTokens.getLineContent(); + const afterRangeText = processedContextTokens.afterRangeProcessedTokens.getLineContent(); + const textAroundRange = beforeRangeText + afterRangeText; + const textAroundRangeWithCharacter = beforeRangeText + ch + afterRangeText; // If previous content already matches decreaseIndentPattern, it means indentation of this line should already be adjusted // Users might change the indentation by purpose and we should honor that instead of readjusting. - if (!indentRulesSupport.shouldDecrease(beforeTypeText + afterTypeText) && indentRulesSupport.shouldDecrease(beforeTypeText + ch + afterTypeText)) { + if (!indentRulesSupport.shouldDecrease(textAroundRange) && indentRulesSupport.shouldDecrease(textAroundRangeWithCharacter)) { // after typing `ch`, the content matches decreaseIndentPattern, we should adjust the indent to a good manner. // 1. Get inherited indent action const r = getInheritIndentForLine(autoIndent, model, range.startLineNumber, false, languageConfigurationService); @@ -460,3 +421,32 @@ export function getIndentMetadata( } return indentRulesSupport.getIndentMetadata(model.getLineContent(lineNumber)); } + +function createVirtualModelWithModifiedTokensAtLine(model: ITextModel, modifiedLineNumber: number, modifiedTokens: IViewLineTokens): IVirtualModel { + const virtualModel: IVirtualModel = { + tokenization: { + getLineTokens: (lineNumber: number): IViewLineTokens => { + if (lineNumber === modifiedLineNumber) { + return modifiedTokens; + } else { + return model.tokenization.getLineTokens(lineNumber); + } + }, + getLanguageId: (): string => { + return model.getLanguageId(); + }, + getLanguageIdAtPosition: (lineNumber: number, column: number): string => { + return model.getLanguageIdAtPosition(lineNumber, column); + }, + }, + getLineContent: (lineNumber: number): string => { + if (lineNumber === modifiedLineNumber) { + return modifiedTokens.getLineContent(); + } else { + return model.getLineContent(lineNumber); + } + } + }; + return virtualModel; +} + diff --git a/src/vs/editor/common/languages/enterAction.ts b/src/vs/editor/common/languages/enterAction.ts index 447665fe816..27669db6ebe 100644 --- a/src/vs/editor/common/languages/enterAction.ts +++ b/src/vs/editor/common/languages/enterAction.ts @@ -7,7 +7,8 @@ import { Range } from 'vs/editor/common/core/range'; import { ITextModel } from 'vs/editor/common/model'; import { IndentAction, CompleteEnterAction } from 'vs/editor/common/languages/languageConfiguration'; import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions'; -import { getIndentationAtPosition, getScopedLineTokens, ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry'; +import { getIndentationAtPosition, ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry'; +import { IndentationContextProcessor } from 'vs/editor/common/languages/supports/indentationLineProcessor'; export function getEnterAction( autoIndent: EditorAutoIndentStrategy, @@ -15,33 +16,17 @@ export function getEnterAction( range: Range, languageConfigurationService: ILanguageConfigurationService ): CompleteEnterAction | null { - const scopedLineTokens = getScopedLineTokens(model, range.startLineNumber, range.startColumn); - const richEditSupport = languageConfigurationService.getLanguageConfiguration(scopedLineTokens.languageId); + model.tokenization.forceTokenization(range.startLineNumber); + const languageId = model.getLanguageIdAtPosition(range.startLineNumber, range.startColumn); + const richEditSupport = languageConfigurationService.getLanguageConfiguration(languageId); if (!richEditSupport) { return null; } - - const scopedLineText = scopedLineTokens.getLineContent(); - const beforeEnterText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset); - - // selection support - let afterEnterText: string; - if (range.isEmpty()) { - afterEnterText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset); - } else { - const endScopedLineTokens = getScopedLineTokens(model, range.endLineNumber, range.endColumn); - afterEnterText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset); - } - - let previousLineText = ''; - if (range.startLineNumber > 1 && scopedLineTokens.firstCharOffset === 0) { - // This is not the first line and the entire line belongs to this mode - const oneLineAboveScopedLineTokens = getScopedLineTokens(model, range.startLineNumber - 1); - if (oneLineAboveScopedLineTokens.languageId === scopedLineTokens.languageId) { - // The line above ends with text belonging to the same mode - previousLineText = oneLineAboveScopedLineTokens.getLineContent(); - } - } + const indentationContextProcessor = new IndentationContextProcessor(model, languageConfigurationService); + const processedContextTokens = indentationContextProcessor.getProcessedTokenContextAroundRange(range); + const previousLineText = processedContextTokens.previousLineProcessedTokens.getLineContent(); + const beforeEnterText = processedContextTokens.beforeRangeProcessedTokens.getLineContent(); + const afterEnterText = processedContextTokens.afterRangeProcessedTokens.getLineContent(); const enterResult = richEditSupport.onEnter(autoIndent, previousLineText, beforeEnterText, afterEnterText); if (!enterResult) { diff --git a/src/vs/editor/common/languages/languageConfigurationRegistry.ts b/src/vs/editor/common/languages/languageConfigurationRegistry.ts index d8598afe6fd..7ff5ddec8a6 100644 --- a/src/vs/editor/common/languages/languageConfigurationRegistry.ts +++ b/src/vs/editor/common/languages/languageConfigurationRegistry.ts @@ -9,7 +9,6 @@ import * as strings from 'vs/base/common/strings'; import { ITextModel } from 'vs/editor/common/model'; import { DEFAULT_WORD_REGEXP, ensureValidWordDefinition } from 'vs/editor/common/core/wordHelper'; import { EnterAction, FoldingRules, IAutoClosingPair, IndentationRule, LanguageConfiguration, AutoClosingPairs, CharacterPair, ExplicitLanguageConfiguration } from 'vs/editor/common/languages/languageConfiguration'; -import { createScopedLineTokens, ScopedLineTokens } from 'vs/editor/common/languages/supports'; import { CharacterPairSupport } from 'vs/editor/common/languages/supports/characterPair'; import { BracketElectricCharacterSupport } from 'vs/editor/common/languages/supports/electricCharacter'; import { IndentRulesSupport } from 'vs/editor/common/languages/supports/indentRules'; @@ -181,13 +180,6 @@ export function getIndentationAtPosition(model: ITextModel, lineNumber: number, return indentation; } -export function getScopedLineTokens(model: ITextModel, lineNumber: number, columnNumber?: number): ScopedLineTokens { - model.tokenization.forceTokenization(lineNumber); - const lineTokens = model.tokenization.getLineTokens(lineNumber); - const column = (typeof columnNumber === 'undefined' ? model.getLineMaxColumn(lineNumber) - 1 : columnNumber - 1); - return createScopedLineTokens(lineTokens, column); -} - class ComposedLanguageConfiguration { private readonly _entries: LanguageConfigurationContribution[]; private _order: number; diff --git a/src/vs/editor/common/languages/supports.ts b/src/vs/editor/common/languages/supports.ts index 8fdfa17bb51..730fa2a1b73 100644 --- a/src/vs/editor/common/languages/supports.ts +++ b/src/vs/editor/common/languages/supports.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { LineTokens } from 'vs/editor/common/tokens/lineTokens'; +import { IViewLineTokens, LineTokens } from 'vs/editor/common/tokens/lineTokens'; import { StandardTokenType } from 'vs/editor/common/encodedTokenAttributes'; +import { ILanguageIdCodec } from 'vs/editor/common/languages'; export function createScopedLineTokens(context: LineTokens, offset: number): ScopedLineTokens { const tokenCount = context.getCount(); @@ -34,6 +35,7 @@ export function createScopedLineTokens(context: LineTokens, offset: number): Sco export class ScopedLineTokens { _scopedLineTokensBrand: void = undefined; + public readonly languageIdCodec: ILanguageIdCodec; public readonly languageId: string; private readonly _actual: LineTokens; private readonly _firstTokenIndex: number; @@ -55,6 +57,7 @@ export class ScopedLineTokens { this._lastTokenIndex = lastTokenIndex; this.firstCharOffset = firstCharOffset; this._lastCharOffset = lastCharOffset; + this.languageIdCodec = actual.languageIdCodec; } public getLineContent(): string { @@ -62,6 +65,10 @@ export class ScopedLineTokens { return actualLineContent.substring(this.firstCharOffset, this._lastCharOffset); } + public getLineLength(): number { + return this._lastCharOffset - this.firstCharOffset; + } + public getActualLineContentBefore(offset: number): string { const actualLineContent = this._actual.getLineContent(); return actualLineContent.substring(0, this.firstCharOffset + offset); @@ -78,6 +85,10 @@ export class ScopedLineTokens { public getStandardTokenType(tokenIndex: number): StandardTokenType { return this._actual.getStandardTokenType(tokenIndex + this._firstTokenIndex); } + + public toIViewLineTokens(): IViewLineTokens { + return this._actual.sliceAndInflate(this.firstCharOffset, this._lastCharOffset, 0); + } } const enum IgnoreBracketsInTokens { diff --git a/src/vs/editor/common/languages/supports/indentationLineProcessor.ts b/src/vs/editor/common/languages/supports/indentationLineProcessor.ts new file mode 100644 index 00000000000..919cb3cd4c8 --- /dev/null +++ b/src/vs/editor/common/languages/supports/indentationLineProcessor.ts @@ -0,0 +1,236 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as strings from 'vs/base/common/strings'; +import { Range } from 'vs/editor/common/core/range'; +import { ITextModel } from 'vs/editor/common/model'; +import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry'; +import { createScopedLineTokens, ScopedLineTokens } from 'vs/editor/common/languages/supports'; +import { IVirtualModel } from 'vs/editor/common/languages/autoIndent'; +import { IViewLineTokens, LineTokens } from 'vs/editor/common/tokens/lineTokens'; +import { IndentRulesSupport } from 'vs/editor/common/languages/supports/indentRules'; +import { StandardTokenType } from 'vs/editor/common/encodedTokenAttributes'; +import { Position } from 'vs/editor/common/core/position'; + +/** + * This class is a wrapper class around {@link IndentRulesSupport}. + * It processes the lines by removing the language configuration brackets from the regex, string and comment tokens. + * It then calls into the {@link IndentRulesSupport} to validate the indentation conditions. + */ +export class ProcessedIndentRulesSupport { + + private readonly _indentRulesSupport: IndentRulesSupport; + private readonly _indentationLineProcessor: IndentationLineProcessor; + + constructor( + model: IVirtualModel, + indentRulesSupport: IndentRulesSupport, + languageConfigurationService: ILanguageConfigurationService + ) { + this._indentRulesSupport = indentRulesSupport; + this._indentationLineProcessor = new IndentationLineProcessor(model, languageConfigurationService); + } + + /** + * Apply the new indentation and return whether the indentation level should be increased after the given line number + */ + public shouldIncrease(lineNumber: number, newIndentation?: string): boolean { + const processedLine = this._indentationLineProcessor.getProcessedLine(lineNumber, newIndentation); + return this._indentRulesSupport.shouldIncrease(processedLine); + } + + /** + * Apply the new indentation and return whether the indentation level should be decreased after the given line number + */ + public shouldDecrease(lineNumber: number, newIndentation?: string): boolean { + const processedLine = this._indentationLineProcessor.getProcessedLine(lineNumber, newIndentation); + return this._indentRulesSupport.shouldDecrease(processedLine); + } + + /** + * Apply the new indentation and return whether the indentation level should remain unchanged at the given line number + */ + public shouldIgnore(lineNumber: number, newIndentation?: string): boolean { + const processedLine = this._indentationLineProcessor.getProcessedLine(lineNumber, newIndentation); + return this._indentRulesSupport.shouldIgnore(processedLine); + } + + /** + * Apply the new indentation and return whether the indentation level should increase on the line after the given line number + */ + public shouldIndentNextLine(lineNumber: number, newIndentation?: string): boolean { + const processedLine = this._indentationLineProcessor.getProcessedLine(lineNumber, newIndentation); + return this._indentRulesSupport.shouldIndentNextLine(processedLine); + } + +} + +/** + * This class fetches the processed text around a range which can be used for indentation evaluation. + * It returns: + * - The processed text before the given range and on the same start line + * - The processed text after the given range and on the same end line + * - The processed text on the previous line + */ +export class IndentationContextProcessor { + + private readonly model: ITextModel; + private readonly indentationLineProcessor: IndentationLineProcessor; + + constructor( + model: ITextModel, + languageConfigurationService: ILanguageConfigurationService + ) { + this.model = model; + this.indentationLineProcessor = new IndentationLineProcessor(model, languageConfigurationService); + } + + /** + * Returns the processed text, stripped from the language configuration brackets within the string, comment and regex tokens, around the given range + */ + getProcessedTokenContextAroundRange(range: Range): { + beforeRangeProcessedTokens: IViewLineTokens; + afterRangeProcessedTokens: IViewLineTokens; + previousLineProcessedTokens: IViewLineTokens; + } { + const beforeRangeProcessedTokens = this._getProcessedTokensBeforeRange(range); + const afterRangeProcessedTokens = this._getProcessedTokensAfterRange(range); + const previousLineProcessedTokens = this._getProcessedPreviousLineTokens(range); + return { beforeRangeProcessedTokens, afterRangeProcessedTokens, previousLineProcessedTokens }; + } + + private _getProcessedTokensBeforeRange(range: Range): IViewLineTokens { + this.model.tokenization.forceTokenization(range.startLineNumber); + const lineTokens = this.model.tokenization.getLineTokens(range.startLineNumber); + const scopedLineTokens = createScopedLineTokens(lineTokens, range.startColumn - 1); + let slicedTokens: IViewLineTokens; + if (isLanguageDifferentFromLineStart(this.model, range.getStartPosition())) { + const columnIndexWithinScope = (range.startColumn - 1) - scopedLineTokens.firstCharOffset; + const firstCharacterOffset = scopedLineTokens.firstCharOffset; + const lastCharacterOffset = firstCharacterOffset + columnIndexWithinScope; + slicedTokens = lineTokens.sliceAndInflate(firstCharacterOffset, lastCharacterOffset, 0); + } else { + const columnWithinLine = range.startColumn - 1; + slicedTokens = lineTokens.sliceAndInflate(0, columnWithinLine, 0); + } + const processedTokens = this.indentationLineProcessor.getProcessedTokens(slicedTokens); + return processedTokens; + } + + private _getProcessedTokensAfterRange(range: Range): IViewLineTokens { + const position: Position = range.isEmpty() ? range.getStartPosition() : range.getEndPosition(); + this.model.tokenization.forceTokenization(position.lineNumber); + const lineTokens = this.model.tokenization.getLineTokens(position.lineNumber); + const scopedLineTokens = createScopedLineTokens(lineTokens, position.column - 1); + const columnIndexWithinScope = position.column - 1 - scopedLineTokens.firstCharOffset; + const firstCharacterOffset = scopedLineTokens.firstCharOffset + columnIndexWithinScope; + const lastCharacterOffset = scopedLineTokens.firstCharOffset + scopedLineTokens.getLineLength(); + const slicedTokens = lineTokens.sliceAndInflate(firstCharacterOffset, lastCharacterOffset, 0); + const processedTokens = this.indentationLineProcessor.getProcessedTokens(slicedTokens); + return processedTokens; + } + + private _getProcessedPreviousLineTokens(range: Range): IViewLineTokens { + const getScopedLineTokensAtEndColumnOfLine = (lineNumber: number): ScopedLineTokens => { + this.model.tokenization.forceTokenization(lineNumber); + const lineTokens = this.model.tokenization.getLineTokens(lineNumber); + const endColumnOfLine = this.model.getLineMaxColumn(lineNumber) - 1; + const scopedLineTokensAtEndColumn = createScopedLineTokens(lineTokens, endColumnOfLine); + return scopedLineTokensAtEndColumn; + }; + + this.model.tokenization.forceTokenization(range.startLineNumber); + const lineTokens = this.model.tokenization.getLineTokens(range.startLineNumber); + const scopedLineTokens = createScopedLineTokens(lineTokens, range.startColumn - 1); + const emptyTokens = LineTokens.createEmpty('', scopedLineTokens.languageIdCodec); + const previousLineNumber = range.startLineNumber - 1; + const isFirstLine = previousLineNumber === 0; + if (isFirstLine) { + return emptyTokens; + } + const canScopeExtendOnPreviousLine = scopedLineTokens.firstCharOffset === 0; + if (!canScopeExtendOnPreviousLine) { + return emptyTokens; + } + const scopedLineTokensAtEndColumnOfPreviousLine = getScopedLineTokensAtEndColumnOfLine(previousLineNumber); + const doesLanguageContinueOnPreviousLine = scopedLineTokens.languageId === scopedLineTokensAtEndColumnOfPreviousLine.languageId; + if (!doesLanguageContinueOnPreviousLine) { + return emptyTokens; + } + const previousSlicedLineTokens = scopedLineTokensAtEndColumnOfPreviousLine.toIViewLineTokens(); + const processedTokens = this.indentationLineProcessor.getProcessedTokens(previousSlicedLineTokens); + return processedTokens; + } +} + +/** + * This class performs the actual processing of the indentation lines. + * The brackets of the language configuration are removed from the regex, string and comment tokens. + */ +class IndentationLineProcessor { + + constructor( + private readonly model: IVirtualModel, + private readonly languageConfigurationService: ILanguageConfigurationService + ) { } + + /** + * Get the processed line for the given line number and potentially adjust the indentation level. + * Remove the language configuration brackets from the regex, string and comment tokens. + */ + getProcessedLine(lineNumber: number, newIndentation?: string): string { + const replaceIndentation = (line: string, newIndentation: string): string => { + const currentIndentation = strings.getLeadingWhitespace(line); + const adjustedLine = newIndentation + line.substring(currentIndentation.length); + return adjustedLine; + }; + + this.model.tokenization.forceTokenization?.(lineNumber); + const tokens = this.model.tokenization.getLineTokens(lineNumber); + let processedLine = this.getProcessedTokens(tokens).getLineContent(); + if (newIndentation !== undefined) { + processedLine = replaceIndentation(processedLine, newIndentation); + } + return processedLine; + } + + /** + * Process the line with the given tokens, remove the language configuration brackets from the regex, string and comment tokens. + */ + getProcessedTokens(tokens: IViewLineTokens): IViewLineTokens { + + const shouldRemoveBracketsFromTokenType = (tokenType: StandardTokenType): boolean => { + return tokenType === StandardTokenType.String + || tokenType === StandardTokenType.RegEx + || tokenType === StandardTokenType.Comment; + }; + + const languageId = tokens.getLanguageId(0); + const bracketsConfiguration = this.languageConfigurationService.getLanguageConfiguration(languageId).bracketsNew; + const bracketsRegExp = bracketsConfiguration.getBracketRegExp({ global: true }); + const textAndMetadata: { text: string; metadata: number }[] = []; + tokens.forEach((tokenIndex: number) => { + const tokenType = tokens.getStandardTokenType(tokenIndex); + let text = tokens.getTokenText(tokenIndex); + if (shouldRemoveBracketsFromTokenType(tokenType)) { + text = text.replace(bracketsRegExp, ''); + } + const metadata = tokens.getMetadata(tokenIndex); + textAndMetadata.push({ text, metadata }); + }); + const processedLineTokens = LineTokens.createFromTextAndMetadata(textAndMetadata, tokens.languageIdCodec); + return processedLineTokens; + } +} + +export function isLanguageDifferentFromLineStart(model: ITextModel, position: Position): boolean { + model.tokenization.forceTokenization(position.lineNumber); + const lineTokens = model.tokenization.getLineTokens(position.lineNumber); + const scopedLineTokens = createScopedLineTokens(lineTokens, position.column - 1); + const doesScopeStartAtOffsetZero = scopedLineTokens.firstCharOffset === 0; + const isScopedLanguageEqualToFirstLanguageOnLine = lineTokens.getLanguageId(0) === scopedLineTokens.languageId; + const languageIsDifferentFromLineStart = !doesScopeStartAtOffsetZero && !isScopedLanguageEqualToFirstLanguageOnLine; + return languageIsDifferentFromLineStart; +} diff --git a/src/vs/editor/common/languages/supports/languageBracketsConfiguration.ts b/src/vs/editor/common/languages/supports/languageBracketsConfiguration.ts index a989e2f35e4..4989395b264 100644 --- a/src/vs/editor/common/languages/supports/languageBracketsConfiguration.ts +++ b/src/vs/editor/common/languages/supports/languageBracketsConfiguration.ts @@ -4,7 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { CachedFunction } from 'vs/base/common/cache'; +import { RegExpOptions } from 'vs/base/common/strings'; import { LanguageConfiguration } from 'vs/editor/common/languages/languageConfiguration'; +import { createBracketOrRegExp } from 'vs/editor/common/languages/supports/richEditBrackets'; /** * Captures all bracket related configurations for a single language. @@ -91,6 +93,11 @@ export class LanguageBracketsConfiguration { public getBracketInfo(bracketText: string): BracketKind | undefined { return this.getOpeningBracketInfo(bracketText) || this.getClosingBracketInfo(bracketText); } + + public getBracketRegExp(options?: RegExpOptions): RegExp { + const brackets = Array.from([...this._openingBrackets.keys(), ...this._closingBrackets.keys()]); + return createBracketOrRegExp(brackets, options); + } } function filterValidBrackets(bracketPairs: [string, string][]): [string, string][] { diff --git a/src/vs/editor/common/languages/supports/richEditBrackets.ts b/src/vs/editor/common/languages/supports/richEditBrackets.ts index c6efd4ee7a7..7733719f049 100644 --- a/src/vs/editor/common/languages/supports/richEditBrackets.ts +++ b/src/vs/editor/common/languages/supports/richEditBrackets.ts @@ -7,6 +7,7 @@ import * as strings from 'vs/base/common/strings'; import * as stringBuilder from 'vs/editor/common/core/stringBuilder'; import { Range } from 'vs/editor/common/core/range'; import { CharacterPair } from 'vs/editor/common/languages/languageConfiguration'; +import { RegExpOptions } from 'vs/base/common/strings'; interface InternalBracket { open: string[]; @@ -408,9 +409,9 @@ function prepareBracketForRegExp(str: string): string { return (insertWordBoundaries ? `\\b${str}\\b` : str); } -function createBracketOrRegExp(pieces: string[]): RegExp { +export function createBracketOrRegExp(pieces: string[], options?: RegExpOptions): RegExp { const regexStr = `(${pieces.map(prepareBracketForRegExp).join(')|(')})`; - return strings.createRegExp(regexStr, true); + return strings.createRegExp(regexStr, true, options); } const toReversedString = (function () { diff --git a/src/vs/editor/common/tokens/lineTokens.ts b/src/vs/editor/common/tokens/lineTokens.ts index bdcda7cb180..67cdf815001 100644 --- a/src/vs/editor/common/tokens/lineTokens.ts +++ b/src/vs/editor/common/tokens/lineTokens.ts @@ -5,10 +5,14 @@ import { ILanguageIdCodec } from 'vs/editor/common/languages'; import { FontStyle, ColorId, StandardTokenType, MetadataConsts, TokenMetadata, ITokenPresentation } from 'vs/editor/common/encodedTokenAttributes'; +import { IPosition } from 'vs/editor/common/core/position'; +import { ITextModel } from 'vs/editor/common/model'; export interface IViewLineTokens { + languageIdCodec: ILanguageIdCodec; equals(other: IViewLineTokens): boolean; getCount(): number; + getStandardTokenType(tokenIndex: number): StandardTokenType; getForeground(tokenIndex: number): ColorId; getEndOffset(tokenIndex: number): number; getClassName(tokenIndex: number): string; @@ -18,6 +22,8 @@ export interface IViewLineTokens { getLineContent(): string; getMetadata(tokenIndex: number): number; getLanguageId(tokenIndex: number): string; + getTokenText(tokenIndex: number): string; + forEach(callback: (tokenIndex: number) => void): void; } export class LineTokens implements IViewLineTokens { @@ -26,7 +32,8 @@ export class LineTokens implements IViewLineTokens { private readonly _tokens: Uint32Array; private readonly _tokensCount: number; private readonly _text: string; - private readonly _languageIdCodec: ILanguageIdCodec; + + public readonly languageIdCodec: ILanguageIdCodec; public static defaultTokenMetadata = ( (FontStyle.None << MetadataConsts.FONT_STYLE_OFFSET) @@ -44,11 +51,23 @@ export class LineTokens implements IViewLineTokens { return new LineTokens(tokens, lineContent, decoder); } + public static createFromTextAndMetadata(data: { text: string; metadata: number }[], decoder: ILanguageIdCodec): LineTokens { + let offset: number = 0; + let fullText: string = ''; + const tokens = new Array(); + for (const { text, metadata } of data) { + tokens.push(offset + text.length, metadata); + offset += text.length; + fullText += text; + } + return new LineTokens(new Uint32Array(tokens), fullText, decoder); + } + constructor(tokens: Uint32Array, text: string, decoder: ILanguageIdCodec) { this._tokens = tokens; this._tokensCount = (this._tokens.length >>> 1); this._text = text; - this._languageIdCodec = decoder; + this.languageIdCodec = decoder; } public equals(other: IViewLineTokens): boolean { @@ -98,7 +117,7 @@ export class LineTokens implements IViewLineTokens { public getLanguageId(tokenIndex: number): string { const metadata = this._tokens[(tokenIndex << 1) + 1]; const languageId = TokenMetadata.getLanguageId(metadata); - return this._languageIdCodec.decodeLanguageId(languageId); + return this.languageIdCodec.decodeLanguageId(languageId); } public getStandardTokenType(tokenIndex: number): StandardTokenType { @@ -225,7 +244,21 @@ export class LineTokens implements IViewLineTokens { } } - return new LineTokens(new Uint32Array(newTokens), text, this._languageIdCodec); + return new LineTokens(new Uint32Array(newTokens), text, this.languageIdCodec); + } + + public getTokenText(tokenIndex: number): string { + const startOffset = this.getStartOffset(tokenIndex); + const endOffset = this.getEndOffset(tokenIndex); + const text = this._text.substring(startOffset, endOffset); + return text; + } + + public forEach(callback: (tokenIndex: number) => void): void { + const tokenCount = this.getCount(); + for (let tokenIndex = 0; tokenIndex < tokenCount; tokenIndex++) { + callback(tokenIndex); + } } } @@ -239,12 +272,15 @@ class SliceLineTokens implements IViewLineTokens { private readonly _firstTokenIndex: number; private readonly _tokensCount: number; + public readonly languageIdCodec: ILanguageIdCodec; + constructor(source: LineTokens, startOffset: number, endOffset: number, deltaOffset: number) { this._source = source; this._startOffset = startOffset; this._endOffset = endOffset; this._deltaOffset = deltaOffset; this._firstTokenIndex = source.findTokenIndexAtOffset(startOffset); + this.languageIdCodec = source.languageIdCodec; this._tokensCount = 0; for (let i = this._firstTokenIndex, len = source.getCount(); i < len; i++) { @@ -284,6 +320,10 @@ class SliceLineTokens implements IViewLineTokens { return this._tokensCount; } + public getStandardTokenType(tokenIndex: number): StandardTokenType { + return this._source.getStandardTokenType(this._firstTokenIndex + tokenIndex); + } + public getForeground(tokenIndex: number): ColorId { return this._source.getForeground(this._firstTokenIndex + tokenIndex); } @@ -308,4 +348,36 @@ class SliceLineTokens implements IViewLineTokens { public findTokenIndexAtOffset(offset: number): number { return this._source.findTokenIndexAtOffset(offset + this._startOffset - this._deltaOffset) - this._firstTokenIndex; } + + public getTokenText(tokenIndex: number): string { + const adjustedTokenIndex = this._firstTokenIndex + tokenIndex; + const tokenStartOffset = this._source.getStartOffset(adjustedTokenIndex); + const tokenEndOffset = this._source.getEndOffset(adjustedTokenIndex); + let text = this._source.getTokenText(adjustedTokenIndex); + if (tokenStartOffset < this._startOffset) { + text = text.substring(this._startOffset - tokenStartOffset); + } + if (tokenEndOffset > this._endOffset) { + text = text.substring(0, text.length - (tokenEndOffset - this._endOffset)); + } + return text; + } + + public forEach(callback: (tokenIndex: number) => void): void { + for (let tokenIndex = 0; tokenIndex < this.getCount(); tokenIndex++) { + callback(tokenIndex); + } + } +} + +export function getStandardTokenTypeAtPosition(model: ITextModel, position: IPosition): StandardTokenType | undefined { + const lineNumber = position.lineNumber; + if (!model.tokenization.isCheapToTokenize(lineNumber)) { + return undefined; + } + model.tokenization.forceTokenization(lineNumber); + const lineTokens = model.tokenization.getLineTokens(lineNumber); + const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1); + const tokenType = lineTokens.getStandardTokenType(tokenIndex); + return tokenType; } diff --git a/src/vs/editor/contrib/find/browser/findDecorations.ts b/src/vs/editor/contrib/find/browser/findDecorations.ts index 62bfb58fb9c..e5e9018464a 100644 --- a/src/vs/editor/contrib/find/browser/findDecorations.ts +++ b/src/vs/editor/contrib/find/browser/findDecorations.ts @@ -288,6 +288,7 @@ export class FindDecorations implements IDisposable { stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, zIndex: 13, className: 'currentFindMatch', + inlineClassName: 'currentFindMatchInline', showIfCollapsed: true, overviewRuler: { color: themeColorFromId(overviewRulerFindMatchForeground), @@ -304,6 +305,7 @@ export class FindDecorations implements IDisposable { stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, zIndex: 10, className: 'findMatch', + inlineClassName: 'findMatchInline', showIfCollapsed: true, overviewRuler: { color: themeColorFromId(overviewRulerFindMatchForeground), diff --git a/src/vs/editor/contrib/find/browser/findWidget.css b/src/vs/editor/contrib/find/browser/findWidget.css index 5d3ef3277d7..d8c479cf1b7 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.css +++ b/src/vs/editor/contrib/find/browser/findWidget.css @@ -232,6 +232,10 @@ background-color: var(--vscode-editor-findMatchHighlightBackground); } +.monaco-editor .findMatchInline { + color: var(--vscode-editor-findMatchHighlightForeground); +} + .monaco-editor .currentFindMatch { background-color: var(--vscode-editor-findMatchBackground); border: 2px solid var(--vscode-editor-findMatchBorder); @@ -239,6 +243,10 @@ box-sizing: border-box; } +.monaco-editor .currentFindMatchInline { + color: var(--vscode-editor-findMatchForeground); +} + .monaco-editor .findScope { background-color: var(--vscode-editor-findRangeHighlightBackground); } diff --git a/src/vs/editor/contrib/find/browser/findWidget.ts b/src/vs/editor/contrib/find/browser/findWidget.ts index d3949c02e72..f536964cb86 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.ts +++ b/src/vs/editor/contrib/find/browser/findWidget.ts @@ -47,10 +47,10 @@ import { createInstantHoverDelegate, getDefaultHoverDelegate } from 'vs/base/bro import { IHoverDelegate } from 'vs/base/browser/ui/hover/hoverDelegate'; import { IHoverService } from 'vs/platform/hover/browser/hover'; -const findSelectionIcon = registerIcon('find-selection', Codicon.selection, nls.localize('findSelectionIcon', 'Icon for \'Find in Selection\' in the editor find widget.')); const findCollapsedIcon = registerIcon('find-collapsed', Codicon.chevronRight, nls.localize('findCollapsedIcon', 'Icon to indicate that the editor find widget is collapsed.')); const findExpandedIcon = registerIcon('find-expanded', Codicon.chevronDown, nls.localize('findExpandedIcon', 'Icon to indicate that the editor find widget is expanded.')); +export const findSelectionIcon = registerIcon('find-selection', Codicon.selection, nls.localize('findSelectionIcon', 'Icon for \'Find in Selection\' in the editor find widget.')); export const findReplaceIcon = registerIcon('find-replace', Codicon.replace, nls.localize('findReplaceIcon', 'Icon for \'Replace\' in the editor find widget.')); export const findReplaceAllIcon = registerIcon('find-replace-all', Codicon.replaceAll, nls.localize('findReplaceAllIcon', 'Icon for \'Replace All\' in the editor find widget.')); export const findPreviousMatchIcon = registerIcon('find-previous-match', Codicon.arrowUp, nls.localize('findPreviousMatchIcon', 'Icon for \'Find Previous\' in the editor find widget.')); diff --git a/src/vs/editor/contrib/hover/browser/contentHoverController.ts b/src/vs/editor/contrib/hover/browser/contentHoverController.ts index 20c441162b5..81ad7b790ed 100644 --- a/src/vs/editor/contrib/hover/browser/contentHoverController.ts +++ b/src/vs/editor/contrib/hover/browser/contentHoverController.ts @@ -23,6 +23,7 @@ import { ContentHoverWidget } from 'vs/editor/contrib/hover/browser/contentHover import { ContentHoverComputer } from 'vs/editor/contrib/hover/browser/contentHoverComputer'; import { ContentHoverVisibleData, HoverResult } from 'vs/editor/contrib/hover/browser/contentHoverTypes'; import { EditorHoverStatusBar } from 'vs/editor/contrib/hover/browser/contentHoverStatusBar'; +import { Emitter } from 'vs/base/common/event'; export class ContentHoverController extends Disposable implements IHoverWidget { @@ -35,6 +36,9 @@ export class ContentHoverController extends Disposable implements IHoverWidget { private readonly _markdownHoverParticipant: MarkdownHoverParticipant | undefined; private readonly _hoverOperation: HoverOperation; + private readonly _onContentsChanged = this._register(new Emitter()); + public readonly onContentsChanged = this._onContentsChanged.event; + constructor( private readonly _editor: ICodeEditor, @IInstantiationService private readonly _instantiationService: IInstantiationService, @@ -214,7 +218,7 @@ export class ContentHoverController extends Disposable implements IHoverWidget { fragment, statusBar, setColorPicker: (widget) => colorPicker = widget, - onContentsChanged: () => this._widget.onContentsChanged(), + onContentsChanged: () => this._doOnContentsChanged(), setMinimumDimensions: (dimensions: dom.Dimension) => this._widget.setMinimumDimensions(dimensions), hide: () => this.hide() }; @@ -261,6 +265,11 @@ export class ContentHoverController extends Disposable implements IHoverWidget { } } + private _doOnContentsChanged(): void { + this._onContentsChanged.fire(); + this._widget.onContentsChanged(); + } + private static readonly _DECORATION_OPTIONS = ModelDecorationOptions.register({ description: 'content-hover-highlight', className: 'hoverHighlight' @@ -351,8 +360,20 @@ export class ContentHoverController extends Disposable implements IHoverWidget { this._startShowingOrUpdateHover(new HoverRangeAnchor(0, range, undefined, undefined), mode, source, focus, null); } - public async updateFocusedMarkdownHoverVerbosityLevel(action: HoverVerbosityAction): Promise { - this._markdownHoverParticipant?.updateFocusedMarkdownHoverPartVerbosityLevel(action); + public async updateMarkdownHoverVerbosityLevel(action: HoverVerbosityAction, index?: number, focus?: boolean): Promise { + this._markdownHoverParticipant?.updateMarkdownHoverVerbosityLevel(action, index, focus); + } + + public focusedMarkdownHoverIndex(): number { + return this._markdownHoverParticipant?.focusedMarkdownHoverIndex() ?? -1; + } + + public markdownHoverContentAtIndex(index: number): string { + return this._markdownHoverParticipant?.markdownHoverContentAtIndex(index) ?? ''; + } + + public doesMarkdownHoverAtIndexSupportVerbosityAction(index: number, action: HoverVerbosityAction): boolean { + return this._markdownHoverParticipant?.doesMarkdownHoverAtIndexSupportVerbosityAction(index, action) ?? false; } public getWidgetContent(): string | undefined { diff --git a/src/vs/editor/contrib/hover/browser/hoverAccessibleViews.ts b/src/vs/editor/contrib/hover/browser/hoverAccessibleViews.ts index 557f1fffa85..5cf65a5b399 100644 --- a/src/vs/editor/contrib/hover/browser/hoverAccessibleViews.ts +++ b/src/vs/editor/contrib/hover/browser/hoverAccessibleViews.ts @@ -2,48 +2,252 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - -import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; +import { localize } from 'vs/nls'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { HoverController } from 'vs/editor/contrib/hover/browser/hoverController'; -import { AccessibleViewType, AccessibleViewProviderId } from 'vs/platform/accessibility/browser/accessibleView'; +import { AccessibleViewType, AccessibleViewProviderId, AdvancedContentProvider, IAccessibleViewContentProvider, IAccessibleViewOptions } from 'vs/platform/accessibility/browser/accessibleView'; import { IAccessibleViewImplentation } from 'vs/platform/accessibility/browser/accessibleViewRegistry'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IHoverService } from 'vs/platform/hover/browser/hover'; -import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { HoverVerbosityAction } from 'vs/editor/common/languages'; +import { DECREASE_HOVER_VERBOSITY_ACCESSIBLE_ACTION_ID, DECREASE_HOVER_VERBOSITY_ACTION_ID, DECREASE_HOVER_VERBOSITY_ACTION_LABEL, INCREASE_HOVER_VERBOSITY_ACCESSIBLE_ACTION_ID, INCREASE_HOVER_VERBOSITY_ACTION_ID, INCREASE_HOVER_VERBOSITY_ACTION_LABEL } from 'vs/editor/contrib/hover/browser/hoverActionIds'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; +import { Action, IAction } from 'vs/base/common/actions'; +import { ThemeIcon } from 'vs/base/common/themables'; +import { Codicon } from 'vs/base/common/codicons'; +import { Emitter, Event } from 'vs/base/common/event'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; + +namespace HoverAccessibilityHelpNLS { + export const intro = localize('intro', "The hover widget is focused. Press the Tab key to cycle through the hover parts."); + export const increaseVerbosity = localize('increaseVerbosity', "- The focused hover part verbosity level can be increased with the Increase Hover Verbosity command.", INCREASE_HOVER_VERBOSITY_ACTION_ID); + export const decreaseVerbosity = localize('decreaseVerbosity', "- The focused hover part verbosity level can be decreased with the Decrease Hover Verbosity command.", DECREASE_HOVER_VERBOSITY_ACTION_ID); + export const hoverContent = localize('contentHover', "The last focused hover content is the following."); +} export class HoverAccessibleView implements IAccessibleViewImplentation { - readonly type = AccessibleViewType.View; - readonly priority = 95; - readonly name = 'hover'; - readonly when = EditorContextKeys.hoverFocused; - getProvider(accessor: ServicesAccessor) { + + public readonly type = AccessibleViewType.View; + public readonly priority = 95; + public readonly name = 'hover'; + public readonly when = EditorContextKeys.hoverFocused; + + private _provider: HoverAccessibleViewProvider | undefined; + + getProvider(accessor: ServicesAccessor): AdvancedContentProvider | undefined { const codeEditorService = accessor.get(ICodeEditorService); - const editor = codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor(); - const editorHoverContent = editor ? HoverController.get(editor)?.getWidgetContent() ?? undefined : undefined; - if (!editor || !editorHoverContent) { + const codeEditor = codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor(); + if (!codeEditor) { + throw new Error('No active or focused code editor'); + } + const hoverController = HoverController.get(codeEditor); + if (!hoverController) { return; } - return { - id: AccessibleViewProviderId.Hover, - verbositySettingKey: 'accessibility.verbosity.hover', - provideContent() { return editorHoverContent; }, - onClose() { - HoverController.get(editor)?.focus(); - }, - options: { - language: editor?.getModel()?.getLanguageId() ?? 'typescript', - type: AccessibleViewType.View - } - }; + this._provider = accessor.get(IInstantiationService).createInstance(HoverAccessibleViewProvider, codeEditor, hoverController); + return this._provider; + } + + dispose(): void { + this._provider?.dispose(); + } +} + +export class HoverAccessibilityHelp implements IAccessibleViewImplentation { + + public readonly priority = 100; + public readonly name = 'hover'; + public readonly type = AccessibleViewType.Help; + public readonly when = EditorContextKeys.hoverVisible; + + private _provider: HoverAccessibleViewProvider | undefined; + + getProvider(accessor: ServicesAccessor): AdvancedContentProvider | undefined { + const codeEditorService = accessor.get(ICodeEditorService); + const codeEditor = codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor(); + if (!codeEditor) { + throw new Error('No active or focused code editor'); + } + const hoverController = HoverController.get(codeEditor); + if (!hoverController) { + return; + } + return accessor.get(IInstantiationService).createInstance(HoverAccessibilityHelpProvider, hoverController); + } + + dispose(): void { + this._provider?.dispose(); + } +} + + +abstract class BaseHoverAccessibleViewProvider extends Disposable implements IAccessibleViewContentProvider { + + abstract provideContent(): string; + abstract options: IAccessibleViewOptions; + + public readonly id = AccessibleViewProviderId.Hover; + public readonly verbositySettingKey = 'accessibility.verbosity.hover'; + + private readonly _onDidChangeContent: Emitter = this._register(new Emitter()); + public readonly onDidChangeContent: Event = this._onDidChangeContent.event; + + protected _markdownHoverFocusedIndex: number = -1; + private _onHoverContentsChanged: IDisposable | undefined; + + constructor( + protected readonly _hoverController: HoverController, + ) { + super(); + } + + public onOpen(): void { + if (!this._hoverController) { + return; + } + this._hoverController.shouldKeepOpenOnEditorMouseMoveOrLeave = true; + this._markdownHoverFocusedIndex = this._hoverController.focusedMarkdownHoverIndex(); + this._onHoverContentsChanged = this._register(this._hoverController.onHoverContentsChanged(() => { + this._onDidChangeContent.fire(); + })); + } + + public onClose(): void { + if (!this._hoverController) { + return; + } + this._markdownHoverFocusedIndex = -1; + this._hoverController.focus(); + this._hoverController.shouldKeepOpenOnEditorMouseMoveOrLeave = false; + this._onHoverContentsChanged?.dispose(); + } +} + + +export class HoverAccessibilityHelpProvider extends BaseHoverAccessibleViewProvider implements IAccessibleViewContentProvider { + + public readonly options: IAccessibleViewOptions = { type: AccessibleViewType.Help }; + + constructor( + hoverController: HoverController, + ) { + super(hoverController); + } + + provideContent(): string { + return this.provideContentAtIndex(this._markdownHoverFocusedIndex); + } + + provideContentAtIndex(index: number): string { + const content: string[] = []; + content.push(HoverAccessibilityHelpNLS.intro); + content.push(...this._descriptionsOfVerbosityActionsForIndex(index)); + content.push(...this._descriptionOfFocusedMarkdownHoverAtIndex(index)); + return content.join('\n'); + } + + private _descriptionsOfVerbosityActionsForIndex(index: number): string[] { + const content: string[] = []; + const descriptionForIncreaseAction = this._descriptionOfVerbosityActionForIndex(HoverVerbosityAction.Increase, index); + if (descriptionForIncreaseAction !== undefined) { + content.push(descriptionForIncreaseAction); + } + const descriptionForDecreaseAction = this._descriptionOfVerbosityActionForIndex(HoverVerbosityAction.Decrease, index); + if (descriptionForDecreaseAction !== undefined) { + content.push(descriptionForDecreaseAction); + } + return content; + } + + private _descriptionOfVerbosityActionForIndex(action: HoverVerbosityAction, index: number): string | undefined { + const isActionSupported = this._hoverController.doesMarkdownHoverAtIndexSupportVerbosityAction(index, action); + if (!isActionSupported) { + return; + } + switch (action) { + case HoverVerbosityAction.Increase: + return HoverAccessibilityHelpNLS.increaseVerbosity; + case HoverVerbosityAction.Decrease: + return HoverAccessibilityHelpNLS.decreaseVerbosity; + } + } + + protected _descriptionOfFocusedMarkdownHoverAtIndex(index: number): string[] { + const content: string[] = []; + const hoverContent = this._hoverController.markdownHoverContentAtIndex(index); + if (hoverContent) { + content.push('\n' + HoverAccessibilityHelpNLS.hoverContent); + content.push('\n' + hoverContent); + } + return content; + } +} + +export class HoverAccessibleViewProvider extends BaseHoverAccessibleViewProvider implements IAccessibleViewContentProvider { + + public readonly options: IAccessibleViewOptions = { type: AccessibleViewType.View }; + + constructor( + private readonly _editor: ICodeEditor, + hoverController: HoverController, + ) { + super(hoverController); + this._initializeOptions(this._editor, hoverController); + } + + public provideContent(): string { + const hoverContent = this._hoverController.markdownHoverContentAtIndex(this._markdownHoverFocusedIndex); + return hoverContent.length > 0 ? hoverContent : HoverAccessibilityHelpNLS.intro; + } + + public get actions(): IAction[] { + const actions: IAction[] = []; + actions.push(this._getActionFor(this._editor, HoverVerbosityAction.Increase)); + actions.push(this._getActionFor(this._editor, HoverVerbosityAction.Decrease)); + return actions; + } + + private _getActionFor(editor: ICodeEditor, action: HoverVerbosityAction): IAction { + let actionId: string; + let accessibleActionId: string; + let actionLabel: string; + let actionCodicon: ThemeIcon; + switch (action) { + case HoverVerbosityAction.Increase: + actionId = INCREASE_HOVER_VERBOSITY_ACTION_ID; + accessibleActionId = INCREASE_HOVER_VERBOSITY_ACCESSIBLE_ACTION_ID; + actionLabel = INCREASE_HOVER_VERBOSITY_ACTION_LABEL; + actionCodicon = Codicon.add; + break; + case HoverVerbosityAction.Decrease: + actionId = DECREASE_HOVER_VERBOSITY_ACTION_ID; + accessibleActionId = DECREASE_HOVER_VERBOSITY_ACCESSIBLE_ACTION_ID; + actionLabel = DECREASE_HOVER_VERBOSITY_ACTION_LABEL; + actionCodicon = Codicon.remove; + break; + } + const actionEnabled = this._hoverController.doesMarkdownHoverAtIndexSupportVerbosityAction(this._markdownHoverFocusedIndex, action); + return new Action(accessibleActionId, actionLabel, ThemeIcon.asClassName(actionCodicon), actionEnabled, () => { + editor.getAction(actionId)?.run({ index: this._markdownHoverFocusedIndex, focus: false }); + }); + } + + private _initializeOptions(editor: ICodeEditor, hoverController: HoverController): void { + const helpProvider = this._register(new HoverAccessibilityHelpProvider(hoverController)); + this.options.language = editor.getModel()?.getLanguageId(); + this.options.customHelp = () => { return helpProvider.provideContentAtIndex(this._markdownHoverFocusedIndex); }; } } export class ExtHoverAccessibleView implements IAccessibleViewImplentation { - readonly type = AccessibleViewType.View; - readonly priority = 90; - readonly name = 'extension-hover'; - getProvider(accessor: ServicesAccessor) { + + public readonly type = AccessibleViewType.View; + public readonly priority = 90; + public readonly name = 'extension-hover'; + + getProvider(accessor: ServicesAccessor): AdvancedContentProvider | undefined { const contextViewService = accessor.get(IContextViewService); const contextViewElement = contextViewService.getContextViewElement(); const extensionHoverContent = contextViewElement?.textContent ?? undefined; @@ -63,4 +267,6 @@ export class ExtHoverAccessibleView implements IAccessibleViewImplentation { options: { language: 'typescript', type: AccessibleViewType.View } }; } + + dispose() { } } diff --git a/src/vs/editor/contrib/hover/browser/hoverActionIds.ts b/src/vs/editor/contrib/hover/browser/hoverActionIds.ts index 5cc42e1aa50..2ade6360ac1 100644 --- a/src/vs/editor/contrib/hover/browser/hoverActionIds.ts +++ b/src/vs/editor/contrib/hover/browser/hoverActionIds.ts @@ -2,6 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as nls from 'vs/nls'; export const SHOW_OR_FOCUS_HOVER_ACTION_ID = 'editor.action.showHover'; export const SHOW_DEFINITION_PREVIEW_HOVER_ACTION_ID = 'editor.action.showDefinitionPreviewHover'; @@ -14,4 +15,8 @@ export const PAGE_DOWN_HOVER_ACTION_ID = 'editor.action.pageDownHover'; export const GO_TO_TOP_HOVER_ACTION_ID = 'editor.action.goToTopHover'; export const GO_TO_BOTTOM_HOVER_ACTION_ID = 'editor.action.goToBottomHover'; export const INCREASE_HOVER_VERBOSITY_ACTION_ID = 'editor.action.increaseHoverVerbosityLevel'; +export const INCREASE_HOVER_VERBOSITY_ACCESSIBLE_ACTION_ID = 'editor.action.increaseHoverVerbosityLevelFromAccessibleView'; +export const INCREASE_HOVER_VERBOSITY_ACTION_LABEL = nls.localize({ key: 'increaseHoverVerbosityLevel', comment: ['Label for action that will increase the hover verbosity level.'] }, "Increase Hover Verbosity Level"); export const DECREASE_HOVER_VERBOSITY_ACTION_ID = 'editor.action.decreaseHoverVerbosityLevel'; +export const DECREASE_HOVER_VERBOSITY_ACCESSIBLE_ACTION_ID = 'editor.action.decreaseHoverVerbosityLevelFromAccessibleView'; +export const DECREASE_HOVER_VERBOSITY_ACTION_LABEL = nls.localize({ key: 'decreaseHoverVerbosityLevel', comment: ['Label for action that will decrease the hover verbosity level.'] }, "Decrease Hover Verbosity Level"); diff --git a/src/vs/editor/contrib/hover/browser/hoverActions.ts b/src/vs/editor/contrib/hover/browser/hoverActions.ts index 9654e7c3d09..20a5148fd74 100644 --- a/src/vs/editor/contrib/hover/browser/hoverActions.ts +++ b/src/vs/editor/contrib/hover/browser/hoverActions.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DECREASE_HOVER_VERBOSITY_ACTION_ID, GO_TO_BOTTOM_HOVER_ACTION_ID, GO_TO_TOP_HOVER_ACTION_ID, INCREASE_HOVER_VERBOSITY_ACTION_ID, PAGE_DOWN_HOVER_ACTION_ID, PAGE_UP_HOVER_ACTION_ID, SCROLL_DOWN_HOVER_ACTION_ID, SCROLL_LEFT_HOVER_ACTION_ID, SCROLL_RIGHT_HOVER_ACTION_ID, SCROLL_UP_HOVER_ACTION_ID, SHOW_DEFINITION_PREVIEW_HOVER_ACTION_ID, SHOW_OR_FOCUS_HOVER_ACTION_ID } from 'vs/editor/contrib/hover/browser/hoverActionIds'; +import { DECREASE_HOVER_VERBOSITY_ACTION_ID, DECREASE_HOVER_VERBOSITY_ACTION_LABEL, GO_TO_BOTTOM_HOVER_ACTION_ID, GO_TO_TOP_HOVER_ACTION_ID, INCREASE_HOVER_VERBOSITY_ACTION_ID, INCREASE_HOVER_VERBOSITY_ACTION_LABEL, PAGE_DOWN_HOVER_ACTION_ID, PAGE_UP_HOVER_ACTION_ID, SCROLL_DOWN_HOVER_ACTION_ID, SCROLL_LEFT_HOVER_ACTION_ID, SCROLL_RIGHT_HOVER_ACTION_ID, SCROLL_UP_HOVER_ACTION_ID, SHOW_DEFINITION_PREVIEW_HOVER_ACTION_ID, SHOW_OR_FOCUS_HOVER_ACTION_ID } from 'vs/editor/contrib/hover/browser/hoverActionIds'; import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; @@ -425,17 +425,14 @@ export class IncreaseHoverVerbosityLevel extends EditorAction { constructor() { super({ id: INCREASE_HOVER_VERBOSITY_ACTION_ID, - label: nls.localize({ - key: 'increaseHoverVerbosityLevel', - comment: ['Label for action that will increase the hover verbosity level.'] - }, "Increase Hover Verbosity Level"), + label: INCREASE_HOVER_VERBOSITY_ACTION_LABEL, alias: 'Increase Hover Verbosity Level', - precondition: EditorContextKeys.hoverFocused + precondition: EditorContextKeys.hoverVisible }); } - public run(accessor: ServicesAccessor, editor: ICodeEditor): void { - HoverController.get(editor)?.updateFocusedMarkdownHoverVerbosityLevel(HoverVerbosityAction.Increase); + public run(accessor: ServicesAccessor, editor: ICodeEditor, args?: { index: number; focus: boolean }): void { + HoverController.get(editor)?.updateMarkdownHoverVerbosityLevel(HoverVerbosityAction.Increase, args?.index, args?.focus); } } @@ -444,16 +441,13 @@ export class DecreaseHoverVerbosityLevel extends EditorAction { constructor() { super({ id: DECREASE_HOVER_VERBOSITY_ACTION_ID, - label: nls.localize({ - key: 'decreaseHoverVerbosityLevel', - comment: ['Label for action that will decrease the hover verbosity level.'] - }, "Decrease Hover Verbosity Level"), + label: DECREASE_HOVER_VERBOSITY_ACTION_LABEL, alias: 'Decrease Hover Verbosity Level', - precondition: EditorContextKeys.hoverFocused + precondition: EditorContextKeys.hoverVisible }); } - public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void { - HoverController.get(editor)?.updateFocusedMarkdownHoverVerbosityLevel(HoverVerbosityAction.Decrease); + public run(accessor: ServicesAccessor, editor: ICodeEditor, args?: { index: number; focus: boolean }): void { + HoverController.get(editor)?.updateMarkdownHoverVerbosityLevel(HoverVerbosityAction.Decrease, args?.index, args?.focus); } } diff --git a/src/vs/editor/contrib/hover/browser/hoverContribution.ts b/src/vs/editor/contrib/hover/browser/hoverContribution.ts index 629b189f2db..bf24cdc1c69 100644 --- a/src/vs/editor/contrib/hover/browser/hoverContribution.ts +++ b/src/vs/editor/contrib/hover/browser/hoverContribution.ts @@ -13,7 +13,7 @@ import { MarkerHoverParticipant } from 'vs/editor/contrib/hover/browser/markerHo import { HoverController } from 'vs/editor/contrib/hover/browser/hoverController'; import 'vs/css!./hover'; import { AccessibleViewRegistry } from 'vs/platform/accessibility/browser/accessibleViewRegistry'; -import { ExtHoverAccessibleView, HoverAccessibleView } from 'vs/editor/contrib/hover/browser/hoverAccessibleViews'; +import { ExtHoverAccessibleView, HoverAccessibilityHelp, HoverAccessibleView } from 'vs/editor/contrib/hover/browser/hoverAccessibleViews'; registerEditorContribution(HoverController.ID, HoverController, EditorContributionInstantiation.BeforeFirstInteraction); registerEditorAction(ShowOrFocusHoverAction); @@ -41,4 +41,5 @@ registerThemingParticipant((theme, collector) => { } }); AccessibleViewRegistry.register(new HoverAccessibleView()); +AccessibleViewRegistry.register(new HoverAccessibilityHelp()); AccessibleViewRegistry.register(new ExtHoverAccessibleView()); diff --git a/src/vs/editor/contrib/hover/browser/hoverController.ts b/src/vs/editor/contrib/hover/browser/hoverController.ts index 5d71cd64144..293902db46d 100644 --- a/src/vs/editor/contrib/hover/browser/hoverController.ts +++ b/src/vs/editor/contrib/hover/browser/hoverController.ts @@ -23,6 +23,7 @@ import { ContentHoverWidget } from 'vs/editor/contrib/hover/browser/contentHover import { ContentHoverController } from 'vs/editor/contrib/hover/browser/contentHoverController'; import 'vs/css!./hover'; import { MarginHoverWidget } from 'vs/editor/contrib/hover/browser/marginHoverWidget'; +import { Emitter } from 'vs/base/common/event'; // sticky hover widget which doesn't disappear on focus out and such const _sticky = false @@ -47,8 +48,13 @@ const enum HoverWidgetType { export class HoverController extends Disposable implements IEditorContribution { + private readonly _onHoverContentsChanged = this._register(new Emitter()); + public readonly onHoverContentsChanged = this._onHoverContentsChanged.event; + public static readonly ID = 'editor.contrib.hover'; + public shouldKeepOpenOnEditorMouseMoveOrLeave: boolean = false; + private readonly _listenersStore = new DisposableStore(); private _glyphWidget: MarginHoverWidget | undefined; @@ -174,6 +180,9 @@ export class HoverController extends Disposable implements IEditorContribution { } private _onEditorMouseLeave(mouseEvent: IPartialEditorMouseEvent): void { + if (this.shouldKeepOpenOnEditorMouseMoveOrLeave) { + return; + } this._cancelScheduler(); @@ -223,6 +232,9 @@ export class HoverController extends Disposable implements IEditorContribution { } private _onEditorMouseMove(mouseEvent: IEditorMouseEvent): void { + if (this.shouldKeepOpenOnEditorMouseMoveOrLeave) { + return; + } this._mouseMoveEvent = mouseEvent; if (this._contentWidget?.isFocused || this._contentWidget?.isResizing) { @@ -374,6 +386,7 @@ export class HoverController extends Disposable implements IEditorContribution { private _getOrCreateContentWidget(): ContentHoverController { if (!this._contentWidget) { this._contentWidget = this._instantiationService.createInstance(ContentHoverController, this._editor); + this._listenersStore.add(this._contentWidget.onContentsChanged(() => this._onHoverContentsChanged.fire())); } return this._contentWidget; } @@ -404,8 +417,20 @@ export class HoverController extends Disposable implements IEditorContribution { return this._contentWidget?.widget.isResizing || false; } - public updateFocusedMarkdownHoverVerbosityLevel(action: HoverVerbosityAction): void { - this._getOrCreateContentWidget().updateFocusedMarkdownHoverVerbosityLevel(action); + public focusedMarkdownHoverIndex(): number { + return this._getOrCreateContentWidget().focusedMarkdownHoverIndex(); + } + + public markdownHoverContentAtIndex(index: number): string { + return this._getOrCreateContentWidget().markdownHoverContentAtIndex(index); + } + + public doesMarkdownHoverAtIndexSupportVerbosityAction(index: number, action: HoverVerbosityAction): boolean { + return this._getOrCreateContentWidget().doesMarkdownHoverAtIndexSupportVerbosityAction(index, action); + } + + public updateMarkdownHoverVerbosityLevel(action: HoverVerbosityAction, index?: number, focus?: boolean): void { + this._getOrCreateContentWidget().updateMarkdownHoverVerbosityLevel(action, index, focus); } public focus(): void { diff --git a/src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts b/src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts index 3c11bee0849..af02ec96e93 100644 --- a/src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts +++ b/src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts @@ -191,8 +191,20 @@ export class MarkdownHoverParticipant implements IEditorHoverParticipant = new Map(); constructor( @@ -281,18 +287,13 @@ class MarkdownRenderedHoverParts extends Disposable { disposables.add(this._renderHoverExpansionAction(actionsContainer, HoverVerbosityAction.Increase, canIncreaseVerbosity)); disposables.add(this._renderHoverExpansionAction(actionsContainer, HoverVerbosityAction.Decrease, canDecreaseVerbosity)); - const focusTracker = disposables.add(dom.trackFocus(renderedMarkdown)); - disposables.add(focusTracker.onDidFocus(() => { - this._hoverFocusInfo = { - hoverPartIndex, - focusRemains: true - }; + this._register(dom.addDisposableListener(renderedMarkdown, dom.EventType.FOCUS_IN, (event: Event) => { + event.stopPropagation(); + this._focusedHoverPartIndex = hoverPartIndex; })); - disposables.add(focusTracker.onDidBlur(() => { - if (this._hoverFocusInfo?.focusRemains) { - this._hoverFocusInfo.focusRemains = false; - return; - } + this._register(dom.addDisposableListener(renderedMarkdown, dom.EventType.FOCUS_OUT, (event: Event) => { + event.stopPropagation(); + this._focusedHoverPartIndex = -1; })); return { renderedMarkdown, disposables, hoverSource }; } @@ -339,19 +340,19 @@ class MarkdownRenderedHoverParts extends Disposable { return store; } actionElement.classList.add('enabled'); - const actionFunction = () => this.updateFocusedHoverPartVerbosityLevel(action); + const actionFunction = () => this.updateMarkdownHoverPartVerbosityLevel(action); store.add(new ClickAction(actionElement, actionFunction)); store.add(new KeyDownAction(actionElement, actionFunction, [KeyCode.Enter, KeyCode.Space])); return store; } - public async updateFocusedHoverPartVerbosityLevel(action: HoverVerbosityAction): Promise { + public async updateMarkdownHoverPartVerbosityLevel(action: HoverVerbosityAction, index: number = -1, focus: boolean = true): Promise { const model = this._editor.getModel(); if (!model) { return; } - const hoverFocusedPartIndex = this._hoverFocusInfo.hoverPartIndex; - const hoverRenderedPart = this._getRenderedHoverPartAtIndex(hoverFocusedPartIndex); + const indexOfInterest = index !== -1 ? index : this._focusedHoverPartIndex; + const hoverRenderedPart = this._getRenderedHoverPartAtIndex(indexOfInterest); if (!hoverRenderedPart || !hoverRenderedPart.hoverSource?.supportsVerbosityAction(action)) { return; } @@ -362,16 +363,35 @@ class MarkdownRenderedHoverParts extends Disposable { } const newHoverSource = new HoverSource(newHover, hoverSource.hoverProvider, hoverSource.hoverPosition); const newHoverRenderedPart = this._renderHoverPart( - hoverFocusedPartIndex, + indexOfInterest, newHover.contents, newHoverSource, this._onFinishedRendering ); - this._replaceRenderedHoverPartAtIndex(hoverFocusedPartIndex, newHoverRenderedPart); - this._focusOnHoverPartWithIndex(hoverFocusedPartIndex); + this._replaceRenderedHoverPartAtIndex(indexOfInterest, newHoverRenderedPart); + if (focus) { + this._focusOnHoverPartWithIndex(indexOfInterest); + } this._onFinishedRendering(); } + public markdownHoverContentAtIndex(index: number): string { + const hoverRenderedPart = this._getRenderedHoverPartAtIndex(index); + return hoverRenderedPart?.renderedMarkdown.innerText ?? ''; + } + + public focusedMarkdownHoverIndex(): number { + return this._focusedHoverPartIndex; + } + + public doesMarkdownHoverAtIndexSupportVerbosityAction(index: number, action: HoverVerbosityAction): boolean { + const hoverRenderedPart = this._getRenderedHoverPartAtIndex(index); + if (!hoverRenderedPart || !hoverRenderedPart.hoverSource?.supportsVerbosityAction(action)) { + return false; + } + return true; + } + private async _fetchHover(hoverSource: HoverSource, model: ITextModel, action: HoverVerbosityAction): Promise { let verbosityDelta = action === HoverVerbosityAction.Increase ? 1 : -1; const provider = hoverSource.hoverProvider; @@ -407,7 +427,6 @@ class MarkdownRenderedHoverParts extends Disposable { private _focusOnHoverPartWithIndex(index: number): void { this._renderedHoverParts[index].renderedMarkdown.focus(); - this._hoverFocusInfo.focusRemains = true; } private _getRenderedHoverPartAtIndex(index: number): RenderedHoverPart | undefined { diff --git a/src/vs/editor/contrib/indentation/browser/indentation.ts b/src/vs/editor/contrib/indentation/browser/indentation.ts index 9860a3b677e..f7d859c5d5a 100644 --- a/src/vs/editor/contrib/indentation/browser/indentation.ts +++ b/src/vs/editor/contrib/indentation/browser/indentation.ts @@ -25,6 +25,8 @@ import * as nls from 'vs/nls'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { getGoodIndentForLine, getIndentMetadata } from 'vs/editor/common/languages/autoIndent'; import { getReindentEditOperations } from '../common/indentation'; +import { getStandardTokenTypeAtPosition } from 'vs/editor/common/tokens/lineTokens'; +import { Position } from 'vs/editor/common/core/position'; export class IndentationToSpacesAction extends EditorAction { public static readonly ID = 'editor.action.indentationToSpaces'; @@ -416,7 +418,9 @@ export class AutoIndentOnPaste implements IEditorContribution { if (!model) { return; } - + if (isStartOrEndInString(model, range)) { + return; + } if (!model.tokenization.isCheapToTokenize(range.getStartPosition().lineNumber)) { return; } @@ -565,6 +569,14 @@ export class AutoIndentOnPaste implements IEditorContribution { } } +function isStartOrEndInString(model: ITextModel, range: Range): boolean { + const isPositionInString = (position: Position): boolean => { + const tokenType = getStandardTokenTypeAtPosition(model, position); + return tokenType === StandardTokenType.String; + }; + return isPositionInString(range.getStartPosition()) || isPositionInString(range.getEndPosition()); +} + function getIndentationEditOperations(model: ITextModel, builder: IEditOperationBuilder, tabSize: number, tabsToSpaces: boolean): void { if (model.getLineCount() === 1 && model.getLineMaxColumn(1) === 1) { // Model is empty diff --git a/src/vs/editor/contrib/indentation/common/indentation.ts b/src/vs/editor/contrib/indentation/common/indentation.ts index 760a14919fb..599d8012e0f 100644 --- a/src/vs/editor/contrib/indentation/common/indentation.ts +++ b/src/vs/editor/contrib/indentation/common/indentation.ts @@ -8,30 +8,28 @@ import { ShiftCommand } from 'vs/editor/common/commands/shiftCommand'; import { EditOperation, ISingleEditOperation } from 'vs/editor/common/core/editOperation'; import { normalizeIndentation } from 'vs/editor/common/core/indentation'; import { Selection } from 'vs/editor/common/core/selection'; +import { StandardTokenType } from 'vs/editor/common/encodedTokenAttributes'; import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry'; +import { ProcessedIndentRulesSupport } from 'vs/editor/common/languages/supports/indentationLineProcessor'; import { ITextModel } from 'vs/editor/common/model'; -export function getReindentEditOperations(model: ITextModel, languageConfigurationService: ILanguageConfigurationService, startLineNumber: number, endLineNumber: number, inheritedIndent?: string): ISingleEditOperation[] { +export function getReindentEditOperations(model: ITextModel, languageConfigurationService: ILanguageConfigurationService, startLineNumber: number, endLineNumber: number): ISingleEditOperation[] { if (model.getLineCount() === 1 && model.getLineMaxColumn(1) === 1) { // Model is empty return []; } - const indentationRules = languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).indentationRules; - if (!indentationRules) { + const indentationRulesSupport = languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).indentRulesSupport; + if (!indentationRulesSupport) { return []; } + const processedIndentRulesSupport = new ProcessedIndentRulesSupport(model, indentationRulesSupport, languageConfigurationService); endLineNumber = Math.min(endLineNumber, model.getLineCount()); // Skip `unIndentedLinePattern` lines while (startLineNumber <= endLineNumber) { - if (!indentationRules.unIndentedLinePattern) { - break; - } - - const text = model.getLineContent(startLineNumber); - if (!indentationRules.unIndentedLinePattern.test(text)) { + if (!processedIndentRulesSupport.shouldIgnore(startLineNumber)) { break; } @@ -54,37 +52,19 @@ export function getReindentEditOperations(model: ITextModel, languageConfigurati const indentEdits: ISingleEditOperation[] = []; // indentation being passed to lines below - let globalIndent: string; // Calculate indentation for the first line // If there is no passed-in indentation, we use the indentation of the first line as base. const currentLineText = model.getLineContent(startLineNumber); - let adjustedLineContent = currentLineText; - if (inheritedIndent !== undefined && inheritedIndent !== null) { - globalIndent = inheritedIndent; - const oldIndentation = strings.getLeadingWhitespace(currentLineText); - - adjustedLineContent = globalIndent + currentLineText.substring(oldIndentation.length); - if (indentationRules.decreaseIndentPattern && indentationRules.decreaseIndentPattern.test(adjustedLineContent)) { - globalIndent = unshiftIndent(globalIndent); - adjustedLineContent = globalIndent + currentLineText.substring(oldIndentation.length); - - } - if (currentLineText !== adjustedLineContent) { - indentEdits.push(EditOperation.replaceMove(new Selection(startLineNumber, 1, startLineNumber, oldIndentation.length + 1), normalizeIndentation(globalIndent, indentSize, insertSpaces))); - } - } else { - globalIndent = strings.getLeadingWhitespace(currentLineText); - } - + let globalIndent = strings.getLeadingWhitespace(currentLineText); // idealIndentForNextLine doesn't equal globalIndent when there is a line matching `indentNextLinePattern`. let idealIndentForNextLine: string = globalIndent; - if (indentationRules.increaseIndentPattern && indentationRules.increaseIndentPattern.test(adjustedLineContent)) { + if (processedIndentRulesSupport.shouldIncrease(startLineNumber)) { idealIndentForNextLine = shiftIndent(idealIndentForNextLine); globalIndent = shiftIndent(globalIndent); } - else if (indentationRules.indentNextLinePattern && indentationRules.indentNextLinePattern.test(adjustedLineContent)) { + else if (processedIndentRulesSupport.shouldIndentNextLine(startLineNumber)) { idealIndentForNextLine = shiftIndent(idealIndentForNextLine); } @@ -92,11 +72,14 @@ export function getReindentEditOperations(model: ITextModel, languageConfigurati // Calculate indentation adjustment for all following lines for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) { + if (doesLineStartWithString(model, lineNumber)) { + continue; + } const text = model.getLineContent(lineNumber); const oldIndentation = strings.getLeadingWhitespace(text); - const adjustedLineContent = idealIndentForNextLine + text.substring(oldIndentation.length); + const currentIdealIndent = idealIndentForNextLine; - if (indentationRules.decreaseIndentPattern && indentationRules.decreaseIndentPattern.test(adjustedLineContent)) { + if (processedIndentRulesSupport.shouldDecrease(lineNumber, currentIdealIndent)) { idealIndentForNextLine = unshiftIndent(idealIndentForNextLine); globalIndent = unshiftIndent(globalIndent); } @@ -106,14 +89,14 @@ export function getReindentEditOperations(model: ITextModel, languageConfigurati } // calculate idealIndentForNextLine - if (indentationRules.unIndentedLinePattern && indentationRules.unIndentedLinePattern.test(text)) { + if (processedIndentRulesSupport.shouldIgnore(lineNumber)) { // In reindent phase, if the line matches `unIndentedLinePattern` we inherit indentation from above lines // but don't change globalIndent and idealIndentForNextLine. continue; - } else if (indentationRules.increaseIndentPattern && indentationRules.increaseIndentPattern.test(adjustedLineContent)) { + } else if (processedIndentRulesSupport.shouldIncrease(lineNumber, currentIdealIndent)) { globalIndent = shiftIndent(globalIndent); idealIndentForNextLine = globalIndent; - } else if (indentationRules.indentNextLinePattern && indentationRules.indentNextLinePattern.test(adjustedLineContent)) { + } else if (processedIndentRulesSupport.shouldIndentNextLine(lineNumber, currentIdealIndent)) { idealIndentForNextLine = shiftIndent(idealIndentForNextLine); } else { idealIndentForNextLine = globalIndent; @@ -122,3 +105,11 @@ export function getReindentEditOperations(model: ITextModel, languageConfigurati return indentEdits; } + +function doesLineStartWithString(model: ITextModel, lineNumber: number): boolean { + if (!model.tokenization.isCheapToTokenize(lineNumber)) { + return false; + } + const lineTokens = model.tokenization.getLineTokens(lineNumber); + return lineTokens.getStandardTokenType(0) === StandardTokenType.String; +} diff --git a/src/vs/editor/contrib/indentation/test/browser/indentation.test.ts b/src/vs/editor/contrib/indentation/test/browser/indentation.test.ts index 72350c3ed69..d6adda566d8 100644 --- a/src/vs/editor/contrib/indentation/test/browser/indentation.test.ts +++ b/src/vs/editor/contrib/indentation/test/browser/indentation.test.ts @@ -24,7 +24,7 @@ import { TypeOperations } from 'vs/editor/common/cursor/cursorTypeOperations'; import { cppBracketRules, goBracketRules, htmlBracketRules, latexBracketRules, luaBracketRules, phpBracketRules, rubyBracketRules, typescriptBracketRules, vbBracketRules } from 'vs/editor/test/common/modes/supports/bracketRules'; import { latexAutoClosingPairsRules } from 'vs/editor/test/common/modes/supports/autoClosingPairsRules'; -enum Language { +export enum Language { TypeScript = 'ts-test', Ruby = 'ruby-test', PHP = 'php-test', @@ -44,7 +44,7 @@ function testIndentationToTabsCommand(lines: string[], selection: Selection, tab testCommand(lines, null, selection, (accessor, sel) => new IndentationToTabsCommand(sel, tabSize), expectedLines, expectedSelection); } -function registerLanguage(instantiationService: TestInstantiationService, language: Language): IDisposable { +export function registerLanguage(instantiationService: TestInstantiationService, language: Language): IDisposable { const disposables = new DisposableStore(); const languageService = instantiationService.get(ILanguageService); disposables.add(registerLanguageConfiguration(instantiationService, language)); @@ -52,7 +52,7 @@ function registerLanguage(instantiationService: TestInstantiationService, langua return disposables; } -function registerLanguageConfiguration(instantiationService: TestInstantiationService, language: Language): IDisposable { +export function registerLanguageConfiguration(instantiationService: TestInstantiationService, language: Language): IDisposable { const languageConfigurationService = instantiationService.get(ILanguageConfigurationService); switch (language) { case Language.TypeScript: @@ -110,12 +110,12 @@ function registerLanguageConfiguration(instantiationService: TestInstantiationSe } } -interface StandardTokenTypeData { +export interface StandardTokenTypeData { startIndex: number; standardTokenType: StandardTokenType; } -function registerTokenizationSupport(instantiationService: TestInstantiationService, tokens: StandardTokenTypeData[][], languageId: string): IDisposable { +export function registerTokenizationSupport(instantiationService: TestInstantiationService, tokens: StandardTokenTypeData[][], languageId: Language): IDisposable { let lineIndex = 0; const languageService = instantiationService.get(ILanguageService); const tokenizationSupport: ITokenizationSupport = { @@ -556,6 +556,43 @@ suite('Auto Indent On Paste - TypeScript/JavaScript', () => { }); }); + test('issue #209859: do not do change indentation when pasted inside of a string', () => { + + // issue: https://github.com/microsoft/vscode/issues/209859 + // issue: https://github.com/microsoft/vscode/issues/209418 + + const initialText = [ + 'const foo = "some text', + ' which is strangely', + ' indented"' + ].join('\n'); + const model = createTextModel(initialText, languageId, {}); + disposables.add(model); + + withTestCodeEditor(model, { autoIndent: 'full' }, (editor, viewModel, instantiationService) => { + const tokens: StandardTokenTypeData[][] = [ + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 12, standardTokenType: StandardTokenType.String }, + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.String }, + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.String }, + ] + ]; + disposables.add(registerLanguage(instantiationService, languageId)); + disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); + + editor.setSelection(new Selection(2, 10, 2, 15)); + viewModel.paste('which', true, undefined, 'keyboard'); + const autoIndentOnPasteController = editor.registerAndInstantiateContribution(AutoIndentOnPaste.ID, AutoIndentOnPaste); + autoIndentOnPasteController.trigger(new Range(2, 1, 2, 28)); + assert.strictEqual(model.getValue(), initialText); + }); + }); + // Failing tests found in issues... test.skip('issue #181065: Incorrect paste of object within comment', () => { @@ -1007,9 +1044,7 @@ suite('Auto Indent On Type - TypeScript/JavaScript', () => { }); }); - // Failing tests... - - test.skip('issue #208232: incorrect indentation inside of comments', () => { + test('issue #208232: incorrect indentation inside of comments', () => { // https://github.com/microsoft/vscode/issues/208232 @@ -1023,6 +1058,12 @@ suite('Auto Indent On Type - TypeScript/JavaScript', () => { withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => { disposables.add(registerLanguage(instantiationService, languageId)); + const tokens: StandardTokenTypeData[][] = [ + [{ startIndex: 0, standardTokenType: StandardTokenType.Comment }], + [{ startIndex: 0, standardTokenType: StandardTokenType.Comment }], + [{ startIndex: 0, standardTokenType: StandardTokenType.Comment }] + ]; + disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); editor.setSelection(new Selection(2, 23, 2, 23)); viewModel.type("\n", 'keyboard'); assert.strictEqual(model.getValue(), [ @@ -1034,6 +1075,8 @@ suite('Auto Indent On Type - TypeScript/JavaScript', () => { }); }); + // Failing tests... + test.skip('issue #43244: indent after equal sign is detected', () => { // https://github.com/microsoft/vscode/issues/43244 @@ -1398,24 +1441,28 @@ suite('Auto Indent On Type - PHP', () => { ensureNoDisposablesAreLeakedInTestSuite(); - test('temp issue because there should be at least one passing test in a suite', () => { - assert.ok(true); - }); - - test.skip('issue #199050: should not indent after { detected in a string', () => { + test('issue #199050: should not indent after { detected in a string', () => { // https://github.com/microsoft/vscode/issues/199050 - const model = createTextModel("$phrase = preg_replace('#(\{1|%s).*#su', '', $phrase);", languageId, {}); + const model = createTextModel("preg_replace('{');", languageId, {}); disposables.add(model); withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => { disposables.add(registerLanguage(instantiationService, languageId)); + const tokens: StandardTokenTypeData[][] = [ + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 13, standardTokenType: StandardTokenType.String }, + { startIndex: 16, standardTokenType: StandardTokenType.Other }, + ] + ]; + disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); editor.setSelection(new Selection(1, 54, 1, 54)); viewModel.type("\n", 'keyboard'); assert.strictEqual(model.getValue(), [ - "$phrase = preg_replace('#(\{1|%s).*#su', '', $phrase);", + "preg_replace('{');", "" ].join('\n')); }); diff --git a/src/vs/editor/contrib/indentation/test/browser/indentationLineProcessor.test.ts b/src/vs/editor/contrib/indentation/test/browser/indentationLineProcessor.test.ts new file mode 100644 index 00000000000..77afbe5c76d --- /dev/null +++ b/src/vs/editor/contrib/indentation/test/browser/indentationLineProcessor.test.ts @@ -0,0 +1,236 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as assert from 'assert'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; +import { StandardTokenType } from 'vs/editor/common/encodedTokenAttributes'; +import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry'; +import { IndentationContextProcessor, ProcessedIndentRulesSupport } from 'vs/editor/common/languages/supports/indentationLineProcessor'; +import { Language, registerLanguage, registerTokenizationSupport, StandardTokenTypeData } from 'vs/editor/contrib/indentation/test/browser/indentation.test'; +import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; +import { createTextModel } from 'vs/editor/test/common/testTextModel'; +import { Range } from 'vs/editor/common/core/range'; + +suite('Indentation Context Processor - TypeScript/JavaScript', () => { + + const languageId = Language.TypeScript; + let disposables: DisposableStore; + + setup(() => { + disposables = new DisposableStore(); + }); + + teardown(() => { + disposables.dispose(); + }); + + ensureNoDisposablesAreLeakedInTestSuite(); + + test('brackets inside of string', () => { + + const model = createTextModel([ + 'const someVar = "{some text}"', + ].join('\n'), languageId, {}); + disposables.add(model); + + withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => { + const tokens: StandardTokenTypeData[][] = [[ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 16, standardTokenType: StandardTokenType.String }, + { startIndex: 28, standardTokenType: StandardTokenType.String } + ]]; + disposables.add(registerLanguage(instantiationService, languageId)); + disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); + const languageConfigurationService = instantiationService.get(ILanguageConfigurationService); + const indentationContextProcessor = new IndentationContextProcessor(model, languageConfigurationService); + const processedContext = indentationContextProcessor.getProcessedTokenContextAroundRange(new Range(1, 23, 1, 23)); + assert.strictEqual(processedContext.beforeRangeProcessedTokens.getLineContent(), 'const someVar = "some'); + assert.strictEqual(processedContext.afterRangeProcessedTokens.getLineContent(), ' text"'); + assert.strictEqual(processedContext.previousLineProcessedTokens.getLineContent(), ''); + }); + }); + + test('brackets inside of comment', () => { + + const model = createTextModel([ + 'const someVar2 = /*(a])*/', + 'const someVar = /* [()] some other t{e}xt() */ "some text"', + ].join('\n'), languageId, {}); + disposables.add(model); + + withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => { + const tokens: StandardTokenTypeData[][] = [ + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 17, standardTokenType: StandardTokenType.Comment }, + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 16, standardTokenType: StandardTokenType.Comment }, + { startIndex: 46, standardTokenType: StandardTokenType.Other }, + { startIndex: 47, standardTokenType: StandardTokenType.String } + ]]; + disposables.add(registerLanguage(instantiationService, languageId)); + disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); + const languageConfigurationService = instantiationService.get(ILanguageConfigurationService); + const indentationContextProcessor = new IndentationContextProcessor(model, languageConfigurationService); + const processedContext = indentationContextProcessor.getProcessedTokenContextAroundRange(new Range(2, 29, 2, 35)); + assert.strictEqual(processedContext.beforeRangeProcessedTokens.getLineContent(), 'const someVar = /* some'); + assert.strictEqual(processedContext.afterRangeProcessedTokens.getLineContent(), ' text */ "some text"'); + assert.strictEqual(processedContext.previousLineProcessedTokens.getLineContent(), 'const someVar2 = /*a*/'); + }); + }); + + test('brackets inside of regex', () => { + + const model = createTextModel([ + 'const someRegex2 = /(()))]/;', + 'const someRegex = /()a{h}{s}[(a}87(9a9()))]/;', + ].join('\n'), languageId, {}); + disposables.add(model); + + withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => { + const tokens: StandardTokenTypeData[][] = [ + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 19, standardTokenType: StandardTokenType.RegEx }, + { startIndex: 27, standardTokenType: StandardTokenType.Other }, + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 18, standardTokenType: StandardTokenType.RegEx }, + { startIndex: 44, standardTokenType: StandardTokenType.Other }, + ] + ]; + disposables.add(registerLanguage(instantiationService, languageId)); + disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); + const languageConfigurationService = instantiationService.get(ILanguageConfigurationService); + const indentationContextProcessor = new IndentationContextProcessor(model, languageConfigurationService); + const processedContext = indentationContextProcessor.getProcessedTokenContextAroundRange(new Range(1, 25, 2, 33)); + assert.strictEqual(processedContext.beforeRangeProcessedTokens.getLineContent(), 'const someRegex2 = /'); + assert.strictEqual(processedContext.afterRangeProcessedTokens.getLineContent(), '879a9/;'); + assert.strictEqual(processedContext.previousLineProcessedTokens.getLineContent(), ''); + }); + }); +}); + +suite('Processed Indent Rules Support - TypeScript/JavaScript', () => { + + const languageId = Language.TypeScript; + let disposables: DisposableStore; + + setup(() => { + disposables = new DisposableStore(); + }); + + teardown(() => { + disposables.dispose(); + }); + + ensureNoDisposablesAreLeakedInTestSuite(); + + test('should increase', () => { + + const model = createTextModel([ + 'const someVar = {', + 'const someVar2 = "{"', + 'const someVar3 = /*{*/' + ].join('\n'), languageId, {}); + disposables.add(model); + + withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => { + const tokens: StandardTokenTypeData[][] = [ + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other } + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 17, standardTokenType: StandardTokenType.String }, + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 17, standardTokenType: StandardTokenType.Comment }, + ] + ]; + disposables.add(registerLanguage(instantiationService, languageId)); + disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); + const languageConfigurationService = instantiationService.get(ILanguageConfigurationService); + const indentationRulesSupport = languageConfigurationService.getLanguageConfiguration(languageId).indentRulesSupport; + if (!indentationRulesSupport) { + assert.fail('indentationRulesSupport should be defined'); + } + const processedIndentRulesSupport = new ProcessedIndentRulesSupport(model, indentationRulesSupport, languageConfigurationService); + assert.strictEqual(processedIndentRulesSupport.shouldIncrease(1), true); + assert.strictEqual(processedIndentRulesSupport.shouldIncrease(2), false); + assert.strictEqual(processedIndentRulesSupport.shouldIncrease(3), false); + }); + }); + + test('should decrease', () => { + + const model = createTextModel([ + '}', + '"])some text}"', + '])*/' + ].join('\n'), languageId, {}); + disposables.add(model); + + withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => { + const tokens: StandardTokenTypeData[][] = [ + [{ startIndex: 0, standardTokenType: StandardTokenType.Other }], + [{ startIndex: 0, standardTokenType: StandardTokenType.String }], + [{ startIndex: 0, standardTokenType: StandardTokenType.Comment }] + ]; + disposables.add(registerLanguage(instantiationService, languageId)); + disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); + const languageConfigurationService = instantiationService.get(ILanguageConfigurationService); + const indentationRulesSupport = languageConfigurationService.getLanguageConfiguration(languageId).indentRulesSupport; + if (!indentationRulesSupport) { + assert.fail('indentationRulesSupport should be defined'); + } + const processedIndentRulesSupport = new ProcessedIndentRulesSupport(model, indentationRulesSupport, languageConfigurationService); + assert.strictEqual(processedIndentRulesSupport.shouldDecrease(1), true); + assert.strictEqual(processedIndentRulesSupport.shouldDecrease(2), false); + assert.strictEqual(processedIndentRulesSupport.shouldDecrease(3), false); + }); + }); + + test('should increase next line', () => { + + const model = createTextModel([ + 'if()', + 'const someString = "if()"', + 'const someRegex = /if()/' + ].join('\n'), languageId, {}); + disposables.add(model); + + withTestCodeEditor(model, { autoIndent: "full" }, (editor, viewModel, instantiationService) => { + const tokens: StandardTokenTypeData[][] = [ + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other } + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 19, standardTokenType: StandardTokenType.String } + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 18, standardTokenType: StandardTokenType.RegEx } + ] + ]; + disposables.add(registerLanguage(instantiationService, languageId)); + disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); + const languageConfigurationService = instantiationService.get(ILanguageConfigurationService); + const indentationRulesSupport = languageConfigurationService.getLanguageConfiguration(languageId).indentRulesSupport; + if (!indentationRulesSupport) { + assert.fail('indentationRulesSupport should be defined'); + } + const processedIndentRulesSupport = new ProcessedIndentRulesSupport(model, indentationRulesSupport, languageConfigurationService); + assert.strictEqual(processedIndentRulesSupport.shouldIndentNextLine(1), true); + assert.strictEqual(processedIndentRulesSupport.shouldIndentNextLine(2), false); + assert.strictEqual(processedIndentRulesSupport.shouldIndentNextLine(3), false); + }); + }); +}); diff --git a/src/vs/editor/contrib/inlayHints/browser/inlayHintsController.ts b/src/vs/editor/contrib/inlayHints/browser/inlayHintsController.ts index b2b665a7edd..accb88043ff 100644 --- a/src/vs/editor/contrib/inlayHints/browser/inlayHintsController.ts +++ b/src/vs/editor/contrib/inlayHints/browser/inlayHintsController.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ModifierKeyEmitter } from 'vs/base/browser/dom'; +import { isHTMLElement, ModifierKeyEmitter } from 'vs/base/browser/dom'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { RunOnceScheduler } from 'vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; @@ -358,7 +358,7 @@ export class InlayHintsController implements IEditorContribution { private _installContextMenu(): IDisposable { return this._editor.onContextMenu(async e => { - if (!(e.event.target instanceof HTMLElement)) { + if (!(isHTMLElement(e.event.target))) { return; } const part = this._getInlayHintLabelPart(e); diff --git a/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsModel.ts b/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsModel.ts index 7cb849da9db..bc10c23e491 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsModel.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsModel.ts @@ -18,6 +18,7 @@ import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { SingleTextEdit, TextEdit } from 'vs/editor/common/core/textEdit'; import { TextLength } from 'vs/editor/common/core/textLength'; +import { ScrollType } from 'vs/editor/common/editorCommon'; import { Command, InlineCompletionContext, InlineCompletionTriggerKind, PartialAcceptTriggerKind } from 'vs/editor/common/languages'; import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry'; import { EndOfLinePreference, ITextModel } from 'vs/editor/common/model'; @@ -444,6 +445,7 @@ export class InlineCompletionsModel extends Disposable { const selections = getEndPositionsAfterApplying(edits).map(p => Selection.fromPositions(p)); editor.executeEdits('inlineSuggestion.accept', edits.map(edit => EditOperation.replace(edit.range, edit.text))); editor.setSelections(selections, 'inlineCompletionPartialAccept'); + editor.revealPositionInCenterIfOutsideViewport(editor.getPosition()!, ScrollType.Immediate); } finally { this._isAcceptingPartially = false; } diff --git a/src/vs/editor/test/browser/config/editorLayoutProvider.test.ts b/src/vs/editor/test/browser/config/editorLayoutProvider.test.ts index 4f644203ef4..d44cc97a7f4 100644 --- a/src/vs/editor/test/browser/config/editorLayoutProvider.test.ts +++ b/src/vs/editor/test/browser/config/editorLayoutProvider.test.ts @@ -60,7 +60,8 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scale: 1, showRegionSectionHeaders: true, showMarkSectionHeaders: true, - sectionHeaderFontSize: 9 + sectionHeaderFontSize: 9, + sectionHeaderLetterSpacing: 1, }; options._write(EditorOption.minimap, minimapOptions); const scrollbarOptions: InternalEditorScrollbarOptions = { diff --git a/src/vs/editor/test/common/core/testLineToken.ts b/src/vs/editor/test/common/core/testLineToken.ts index 8217c2042fb..f3c49807941 100644 --- a/src/vs/editor/test/common/core/testLineToken.ts +++ b/src/vs/editor/test/common/core/testLineToken.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { IViewLineTokens } from 'vs/editor/common/tokens/lineTokens'; -import { ColorId, TokenMetadata, ITokenPresentation } from 'vs/editor/common/encodedTokenAttributes'; +import { ColorId, TokenMetadata, ITokenPresentation, StandardTokenType } from 'vs/editor/common/encodedTokenAttributes'; +import { ILanguageIdCodec } from 'vs/editor/common/languages'; /** * A token on a line. @@ -22,6 +23,10 @@ export class TestLineToken { this._metadata = metadata; } + public getStandardTokenType(): StandardTokenType { + return TokenMetadata.getTokenType(this._metadata); + } + public getForeground(): ColorId { return TokenMetadata.getForeground(this._metadata); } @@ -79,6 +84,10 @@ export class TestLineTokens implements IViewLineTokens { return this._actual.length; } + public getStandardTokenType(tokenIndex: number): StandardTokenType { + return this._actual[tokenIndex].getStandardTokenType(); + } + public getForeground(tokenIndex: number): ColorId { return this._actual[tokenIndex].getForeground(); } @@ -114,6 +123,18 @@ export class TestLineTokens implements IViewLineTokens { public getLanguageId(tokenIndex: number): string { throw new Error('Method not implemented.'); } + + public getTokenText(tokenIndex: number): string { + throw new Error('Method not implemented.'); + } + + public forEach(callback: (tokenIndex: number) => void): void { + throw new Error('Not implemented'); + } + + public get languageIdCodec(): ILanguageIdCodec { + throw new Error('Not implemented'); + } } export class TestLineTokenFactory { diff --git a/src/vs/editor/test/common/services/languageService.test.ts b/src/vs/editor/test/common/services/languageService.test.ts index 26a99380e75..b0b54a96746 100644 --- a/src/vs/editor/test/common/services/languageService.test.ts +++ b/src/vs/editor/test/common/services/languageService.test.ts @@ -4,26 +4,23 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { throwIfDisposablesAreLeaked } from 'vs/base/test/common/utils'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry'; import { LanguageService } from 'vs/editor/common/services/languageService'; suite('LanguageService', () => { + ensureNoDisposablesAreLeakedInTestSuite(); + test('LanguageSelection does not leak a disposable', () => { const languageService = new LanguageService(); - throwIfDisposablesAreLeaked(() => { - const languageSelection = languageService.createById(PLAINTEXT_LANGUAGE_ID); - assert.strictEqual(languageSelection.languageId, PLAINTEXT_LANGUAGE_ID); - }); - throwIfDisposablesAreLeaked(() => { - const languageSelection = languageService.createById(PLAINTEXT_LANGUAGE_ID); - const listener = languageSelection.onDidChange(() => { }); - assert.strictEqual(languageSelection.languageId, PLAINTEXT_LANGUAGE_ID); - listener.dispose(); - }); + const languageSelection1 = languageService.createById(PLAINTEXT_LANGUAGE_ID); + assert.strictEqual(languageSelection1.languageId, PLAINTEXT_LANGUAGE_ID); + const languageSelection2 = languageService.createById(PLAINTEXT_LANGUAGE_ID); + const listener = languageSelection2.onDidChange(() => { }); + assert.strictEqual(languageSelection2.languageId, PLAINTEXT_LANGUAGE_ID); + listener.dispose(); languageService.dispose(); - }); }); diff --git a/src/vs/editor/test/node/classification/typescript.test.ts b/src/vs/editor/test/node/classification/typescript.test.ts index e99cfa28d94..e9e8d3fec1a 100644 --- a/src/vs/editor/test/node/classification/typescript.test.ts +++ b/src/vs/editor/test/node/classification/typescript.test.ts @@ -9,6 +9,7 @@ import * as fs from 'fs'; // import { getPathFromAmdModule } from 'vs/base/test/node/testUtils'; // import { parse } from 'vs/editor/common/modes/tokenization/typescript'; import { toStandardTokenType } from 'vs/editor/common/languages/supports/tokenization'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; interface IParseFunc { (text: string): number[]; @@ -135,6 +136,9 @@ function executeTest(fileName: string, parseFunc: IParseFunc): void { } suite('Classification', () => { + + ensureNoDisposablesAreLeakedInTestSuite(); + test('TypeScript', () => { // executeTest(getPathFromAmdModule(require, 'vs/editor/test/node/classification/typescript-test.ts').replace(/\bout\b/, 'src'), parse); }); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index bb29ed01d98..72709da6d10 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -4318,6 +4318,10 @@ declare namespace monaco.editor { * Font size of section headers. Defaults to 9. */ sectionHeaderFontSize?: number; + /** + * Spacing between the section header characters (in CSS px). Defaults to 1. + */ + sectionHeaderLetterSpacing?: number; } /** diff --git a/src/vs/platform/accessibility/browser/accessibleView.ts b/src/vs/platform/accessibility/browser/accessibleView.ts index d2fedcb8661..d71a5871195 100644 --- a/src/vs/platform/accessibility/browser/accessibleView.ts +++ b/src/vs/platform/accessibility/browser/accessibleView.ts @@ -141,9 +141,11 @@ export class AdvancedContentProvider implements IAccessibleViewContentProvider { public provideContent: () => string, public onClose: () => void, public verbositySettingKey: string, + public onOpen?: () => void, public actions?: IAction[], public next?: () => void, public previous?: () => void, + public onDidChangeContent?: Event, public onKeyDown?: (e: IKeyboardEvent) => void, public getSymbols?: () => IAccessibleViewSymbol[], public onDidRequestClearLastProvider?: Event, @@ -157,9 +159,11 @@ export class ExtensionContentProvider implements IBasicContentProvider { public options: IAccessibleViewOptions, public provideContent: () => string, public onClose: () => void, + public onOpen?: () => void, public next?: () => void, public previous?: () => void, public actions?: IAction[], + public onDidChangeContent?: Event, ) { } } @@ -168,7 +172,9 @@ export interface IBasicContentProvider { options: IAccessibleViewOptions; onClose(): void; provideContent(): string; + onOpen?(): void; actions?: IAction[]; previous?(): void; next?(): void; + onDidChangeContent?: Event; } diff --git a/src/vs/platform/accessibility/browser/accessibleViewRegistry.ts b/src/vs/platform/accessibility/browser/accessibleViewRegistry.ts index 13679e64781..0a6369565bb 100644 --- a/src/vs/platform/accessibility/browser/accessibleViewRegistry.ts +++ b/src/vs/platform/accessibility/browser/accessibleViewRegistry.ts @@ -9,7 +9,7 @@ import { ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { alert } from 'vs/base/browser/ui/aria/aria'; -export interface IAccessibleViewImplentation { +export interface IAccessibleViewImplentation extends IDisposable { type: AccessibleViewType; priority: number; name: string; @@ -31,6 +31,7 @@ export const AccessibleViewRegistry = new class AccessibleViewRegistry { if (idx !== -1) { this._implementations.splice(idx, 1); } + implementation.dispose(); } }; } diff --git a/src/vs/platform/clipboard/browser/clipboardService.ts b/src/vs/platform/clipboard/browser/clipboardService.ts index 7af565a3b34..ed5490e783f 100644 --- a/src/vs/platform/clipboard/browser/clipboardService.ts +++ b/src/vs/platform/clipboard/browser/clipboardService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { isSafari, isWebkitWebView } from 'vs/base/browser/browser'; -import { $, addDisposableListener, getActiveDocument, getActiveWindow, onDidRegisterWindow } from 'vs/base/browser/dom'; +import { $, addDisposableListener, getActiveDocument, getActiveWindow, isHTMLElement, onDidRegisterWindow } from 'vs/base/browser/dom'; import { mainWindow } from 'vs/base/browser/window'; import { DeferredPromise } from 'vs/base/common/async'; import { Event } from 'vs/base/common/event'; @@ -130,7 +130,7 @@ export class BrowserClipboardService extends Disposable implements IClipboardSer activeDocument.execCommand('copy'); - if (activeElement instanceof HTMLElement) { + if (isHTMLElement(activeElement)) { activeElement.focus(); } diff --git a/src/vs/platform/contextview/browser/contextMenuHandler.ts b/src/vs/platform/contextview/browser/contextMenuHandler.ts index 55e0d50422d..abc08f92252 100644 --- a/src/vs/platform/contextview/browser/contextMenuHandler.ts +++ b/src/vs/platform/contextview/browser/contextMenuHandler.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IContextMenuDelegate } from 'vs/base/browser/contextmenu'; -import { $, addDisposableListener, EventType, getActiveElement, getWindow, isAncestor } from 'vs/base/browser/dom'; +import { $, addDisposableListener, EventType, getActiveElement, getWindow, isAncestor, isHTMLElement } from 'vs/base/browser/dom'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { Menu } from 'vs/base/browser/ui/menu/menu'; import { ActionRunner, IRunEvent, WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions'; @@ -49,7 +49,7 @@ export class ContextMenuHandler { let menu: Menu | undefined; - const shadowRootElement = delegate.domForShadowRoot instanceof HTMLElement ? delegate.domForShadowRoot : undefined; + const shadowRootElement = isHTMLElement(delegate.domForShadowRoot) ? delegate.domForShadowRoot : undefined; this.contextViewService.showContextView({ getAnchor: () => delegate.getAnchor(), canRelayout: false, diff --git a/src/vs/platform/dnd/browser/dnd.ts b/src/vs/platform/dnd/browser/dnd.ts index 1bd55afefaf..b742b3ae448 100644 --- a/src/vs/platform/dnd/browser/dnd.ts +++ b/src/vs/platform/dnd/browser/dnd.ts @@ -201,6 +201,7 @@ async function extractFilesDropData(accessor: ServicesAccessor, event: DragEvent async function extractFileTransferData(accessor: ServicesAccessor, items: DataTransferItemList): Promise { const fileSystemProvider = accessor.get(IFileService).getProvider(Schemas.file); + // eslint-disable-next-line no-restricted-syntax if (!(fileSystemProvider instanceof HTMLFileSystemProvider)) { return []; // only supported when running in web } diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts index cc587b5770e..5548b8eefb9 100644 --- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts @@ -957,7 +957,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi }; const stopWatch = new StopWatch(); - let context: IRequestContext | undefined, error: ExtensionGalleryError | undefined, total: number = 0; + let context: IRequestContext | undefined, errorCode: ExtensionGalleryErrorCode | undefined, total: number = 0; try { context = await this.requestService.request({ @@ -989,9 +989,14 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi return { galleryExtensions: [], total }; } catch (e) { - const errorCode = isCancellationError(e) ? ExtensionGalleryErrorCode.Cancelled : getErrorMessage(e).startsWith('XHR timeout') ? ExtensionGalleryErrorCode.Timeout : ExtensionGalleryErrorCode.Failed; - error = new ExtensionGalleryError(getErrorMessage(e), errorCode); - throw error; + if (isCancellationError(e)) { + errorCode = ExtensionGalleryErrorCode.Cancelled; + throw e; + } else { + const errorMessage = getErrorMessage(e); + errorCode = errorMessage.startsWith('XHR timeout') ? ExtensionGalleryErrorCode.Timeout : ExtensionGalleryErrorCode.Failed; + throw new ExtensionGalleryError(errorMessage, errorCode); + } } finally { this.telemetryService.publicLog2('galleryService:query', { ...query.telemetryData, @@ -1000,7 +1005,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi success: !!context && isSuccess(context), responseBodySize: context?.res.headers['Content-Length'], statusCode: context ? String(context.res.statusCode) : undefined, - errorCode: error?.code, + errorCode, count: String(total) }); } diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 38757db3a67..2bcc19c90b1 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -602,6 +602,7 @@ export class ExtensionsScanner extends Disposable { } catch (error) { if (error.code === 'ENOTEMPTY') { this.logService.info(`Rename failed because extension was installed by another source. So ignoring renaming.`, extensionKey.id); + try { await this.fileService.del(tempLocation, { recursive: true }); } catch (e) { /* ignore */ } } else { this.logService.info(`Rename failed because of ${getErrorMessage(error)}. Deleted from extracted location`, tempLocation); throw error; diff --git a/src/vs/platform/extensions/test/common/extensionValidator.test.ts b/src/vs/platform/extensions/test/common/extensionValidator.test.ts index 9885ec4e29a..9060783778a 100644 --- a/src/vs/platform/extensions/test/common/extensionValidator.test.ts +++ b/src/vs/platform/extensions/test/common/extensionValidator.test.ts @@ -3,10 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; import { IExtensionManifest } from 'vs/platform/extensions/common/extensions'; import { INormalizedVersion, IParsedVersion, isValidExtensionVersion, isValidVersion, isValidVersionStr, normalizeVersion, parseVersion } from 'vs/platform/extensions/common/extensionValidator'; suite('Extension Version Validator', () => { + + ensureNoDisposablesAreLeakedInTestSuite(); + const productVersion = '2021-05-11T21:54:30.577Z'; test('isValidVersionStr', () => { diff --git a/src/vs/platform/hover/browser/hover.ts b/src/vs/platform/hover/browser/hover.ts index b856f528c5b..51ead712fcb 100644 --- a/src/vs/platform/hover/browser/hover.ts +++ b/src/vs/platform/hover/browser/hover.ts @@ -7,7 +7,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IHoverDelegate, IHoverDelegateOptions } from 'vs/base/browser/ui/hover/hoverDelegate'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { addStandardDisposableListener } from 'vs/base/browser/dom'; +import { addStandardDisposableListener, isHTMLElement } from 'vs/base/browser/dom'; import { KeyCode } from 'vs/base/common/keyCodes'; import type { IHoverDelegate2, IHoverOptions, IHoverWidget } from 'vs/base/browser/ui/hover/hover'; @@ -54,7 +54,7 @@ export class WorkbenchHoverDelegate extends Disposable implements IHoverDelegate // close hover on escape this.hoverDisposables.clear(); - const targets = options.target instanceof HTMLElement ? [options.target] : options.target.targetElements; + const targets = isHTMLElement(options.target) ? [options.target] : options.target.targetElements; for (const target of targets) { this.hoverDisposables.add(addStandardDisposableListener(target, 'keydown', (e) => { if (e.equals(KeyCode.Escape)) { @@ -63,7 +63,7 @@ export class WorkbenchHoverDelegate extends Disposable implements IHoverDelegate })); } - const id = options.content instanceof HTMLElement ? undefined : options.content.toString(); + const id = isHTMLElement(options.content) ? undefined : options.content.toString(); return this.hoverService.showHover({ ...options, diff --git a/src/vs/platform/quickinput/browser/quickInput.ts b/src/vs/platform/quickinput/browser/quickInput.ts index 7b43505fb64..4c6dfbe6b7d 100644 --- a/src/vs/platform/quickinput/browser/quickInput.ts +++ b/src/vs/platform/quickinput/browser/quickInput.ts @@ -206,7 +206,7 @@ abstract class QuickInput extends Disposable implements IQuickInput { } set widget(widget: unknown | undefined) { - if (!(widget instanceof HTMLElement)) { + if (!(dom.isHTMLElement(widget))) { return; } if (this._widget !== widget) { @@ -1271,7 +1271,7 @@ export class QuickInputHoverDelegate extends WorkbenchHoverDelegate { private getOverrideOptions(options: IHoverDelegateOptions): Partial { // Only show the hover hint if the content is of a decent size const showHoverHint = ( - options.content instanceof HTMLElement + dom.isHTMLElement(options.content) ? options.content.textContent ?? '' : typeof options.content === 'string' ? options.content diff --git a/src/vs/platform/quickinput/browser/quickInputActions.ts b/src/vs/platform/quickinput/browser/quickInputActions.ts index 14f4a49b539..5efaf793645 100644 --- a/src/vs/platform/quickinput/browser/quickInputActions.ts +++ b/src/vs/platform/quickinput/browser/quickInputActions.ts @@ -27,12 +27,13 @@ function registerQuickPickCommandAndKeybindingRule(rule: PartialExcept { if (!this.getUI().ignoreFocusOut && !this.options.ignoreFocusOut()) { diff --git a/src/vs/platform/quickinput/browser/quickInputTree.ts b/src/vs/platform/quickinput/browser/quickInputTree.ts index 3a492f78a1e..6fa28c37170 100644 --- a/src/vs/platform/quickinput/browser/quickInputTree.ts +++ b/src/vs/platform/quickinput/browser/quickInputTree.ts @@ -903,13 +903,13 @@ export class QuickInputTree extends Disposable { this._register(this._tree.onMouseOver(async e => { // If we hover over an anchor element, we don't want to show the hover because // the anchor may have a tooltip that we want to show instead. - if (e.browserEvent.target instanceof HTMLAnchorElement) { + if (dom.isHTMLAnchorElement(e.browserEvent.target)) { delayer.cancel(); return; } if ( // anchors are an exception as called out above so we skip them here - !(e.browserEvent.relatedTarget instanceof HTMLAnchorElement) && + !(dom.isHTMLAnchorElement(e.browserEvent.relatedTarget)) && // check if the mouse is still over the same element dom.isAncestor(e.browserEvent.relatedTarget as Node, e.element?.element as Node) ) { diff --git a/src/vs/platform/remote/test/common/remoteHosts.test.ts b/src/vs/platform/remote/test/common/remoteHosts.test.ts index 0f2254b8b87..cfbc105f465 100644 --- a/src/vs/platform/remote/test/common/remoteHosts.test.ts +++ b/src/vs/platform/remote/test/common/remoteHosts.test.ts @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; import { parseAuthorityWithOptionalPort, parseAuthorityWithPort } from 'vs/platform/remote/common/remoteHosts'; suite('remoteHosts', () => { + ensureNoDisposablesAreLeakedInTestSuite(); + test('parseAuthority hostname', () => { assert.deepStrictEqual(parseAuthorityWithPort('localhost:8080'), { host: 'localhost', port: 8080 }); }); diff --git a/src/vs/platform/theme/common/colors/baseColors.ts b/src/vs/platform/theme/common/colors/baseColors.ts index 1d19b3adc1f..9a02e218db8 100644 --- a/src/vs/platform/theme/common/colors/baseColors.ts +++ b/src/vs/platform/theme/common/colors/baseColors.ts @@ -65,7 +65,7 @@ export const textSeparatorForeground = registerColor('textSeparator.foreground', // ------ text preformat export const textPreformatForeground = registerColor('textPreformat.foreground', - { light: '#A31515', dark: '#D7BA7D', hcDark: '#000000', hcLight: '#FFFFFF' }, + { light: '#A31515', dark: '#D7BA7D', hcDark: '#FFFFFF', hcLight: '#000000' }, nls.localize('textPreformatForeground', "Foreground color for preformatted text segments.")); export const textPreformatBackground = registerColor('textPreformat.background', diff --git a/src/vs/platform/theme/common/colors/editorColors.ts b/src/vs/platform/theme/common/colors/editorColors.ts index 4116f5ec141..a57b85e2c29 100644 --- a/src/vs/platform/theme/common/colors/editorColors.ts +++ b/src/vs/platform/theme/common/colors/editorColors.ts @@ -141,10 +141,18 @@ export const editorFindMatch = registerColor('editor.findMatchBackground', { light: '#A8AC94', dark: '#515C6A', hcDark: null, hcLight: null }, nls.localize('editorFindMatch', "Color of the current search match.")); +export const editorFindMatchForeground = registerColor('editor.findMatchForeground', + { light: null, dark: null, hcDark: null, hcLight: null }, + nls.localize('editorFindMatchForeground', "Text color of the current search match.")); + export const editorFindMatchHighlight = registerColor('editor.findMatchHighlightBackground', { light: '#EA5C0055', dark: '#EA5C0055', hcDark: null, hcLight: null }, nls.localize('findMatchHighlight', "Color of the other search matches. The color must not be opaque so as not to hide underlying decorations."), true); +export const editorFindMatchHighlightForeground = registerColor('editor.findMatchHighlightForeground', + { light: null, dark: null, hcDark: null, hcLight: null }, + nls.localize('findMatchHighlightForeground', "Foreground color of the other search matches."), true); + export const editorFindRangeHighlight = registerColor('editor.findRangeHighlightBackground', { dark: '#3a3d4166', light: '#b4b4b44d', hcDark: null, hcLight: null }, nls.localize('findRangeHighlight', "Color of the range limiting the search. The color must not be opaque so as not to hide underlying decorations."), true); diff --git a/src/vs/platform/utilityProcess/electron-main/utilityProcessWorkerMainService.ts b/src/vs/platform/utilityProcess/electron-main/utilityProcessWorkerMainService.ts index 70be47e3b27..4888e76a2fe 100644 --- a/src/vs/platform/utilityProcess/electron-main/utilityProcessWorkerMainService.ts +++ b/src/vs/platform/utilityProcess/electron-main/utilityProcessWorkerMainService.ts @@ -89,6 +89,7 @@ export class UtilityProcessWorkerMainService extends Disposable implements IUtil this.logService.trace(`[UtilityProcessWorker]: disposeWorker(window: ${configuration.reply.windowId}, moduleId: ${configuration.process.moduleId})`); worker.kill(); + worker.dispose(); this.workers.delete(workerId); } } @@ -98,7 +99,7 @@ class UtilityProcessWorker extends Disposable { private readonly _onDidTerminate = this._register(new Emitter()); readonly onDidTerminate = this._onDidTerminate.event; - private readonly utilityProcess = new WindowUtilityProcess(this.logService, this.windowsMainService, this.telemetryService, this.lifecycleMainService); + private readonly utilityProcess = this._register(new WindowUtilityProcess(this.logService, this.windowsMainService, this.telemetryService, this.lifecycleMainService)); constructor( @ILogService private readonly logService: ILogService, diff --git a/src/vs/server/node/remoteExtensionsScanner.ts b/src/vs/server/node/remoteExtensionsScanner.ts index 54418aebfc2..19a50f7b067 100644 --- a/src/vs/server/node/remoteExtensionsScanner.ts +++ b/src/vs/server/node/remoteExtensionsScanner.ts @@ -133,7 +133,7 @@ export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerS this._scanDevelopedExtensions(language, extensionDevelopmentPath) ]); - return dedupExtensions(builtinExtensions, [...installedExtensions, ...workspaceInstalledExtensions], developedExtensions, this._logService); + return dedupExtensions(builtinExtensions, installedExtensions, workspaceInstalledExtensions, developedExtensions, this._logService); } private async _scanDevelopedExtensions(language: string, extensionDevelopmentPaths?: string[]): Promise { diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index a75f2154c9d..1781e73af7a 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -67,7 +67,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread } this._proxy.$setWordDefinitions(wordDefinitionDtos); }; - this._languageConfigurationService.onDidChange((e) => { + this._register(this._languageConfigurationService.onDidChange((e) => { if (!e.languageId) { updateAllWordDefinitions(); } else { @@ -78,7 +78,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread regexFlags: wordDefinition.flags }]); } - }); + })); updateAllWordDefinitions(); } } diff --git a/src/vs/workbench/api/common/extHostChatAgents2.ts b/src/vs/workbench/api/common/extHostChatAgents2.ts index ffe51e0aaae..70b6421c799 100644 --- a/src/vs/workbench/api/common/extHostChatAgents2.ts +++ b/src/vs/workbench/api/common/extHostChatAgents2.ts @@ -344,6 +344,11 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS }), token); } catch (e) { this._logService.error(e, agent.extension); + + if (e instanceof extHostTypes.LanguageModelError && e.cause) { + e = e.cause; + } + return { errorDetails: { message: toErrorMessage(e), responseIsIncomplete: true } }; } finally { diff --git a/src/vs/workbench/api/common/extHostLanguageModels.ts b/src/vs/workbench/api/common/extHostLanguageModels.ts index 97ee59fa601..fdc93731554 100644 --- a/src/vs/workbench/api/common/extHostLanguageModels.ts +++ b/src/vs/workbench/api/common/extHostLanguageModels.ts @@ -253,6 +253,11 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape { continue; } + // make sure auth information is correct + if (this._isUsingAuth(extension.identifier, data.metadata)) { + await this._fakeAuthPopulate(data.metadata); + } + let apiObject = data.apiObjects.get(extension.identifier); if (!apiObject) { @@ -403,6 +408,10 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape { private async _fakeAuthPopulate(metadata: ILanguageModelChatMetadata): Promise { + if (!metadata.auth) { + return; + } + for (const from of this._languageAccessInformationExtensions) { try { await this._getAuthAccess(from, { identifier: metadata.extension, displayName: '' }, undefined, true); diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index c746b79ed35..c63a3afd172 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -9,7 +9,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import { debounce } from 'vs/base/common/decorators'; import { DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; -import { asPromise } from 'vs/base/common/async'; +import { asPromise, Sequencer } from 'vs/base/common/async'; import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto, MainThreadTelemetryShape, SCMGroupFeatures, SCMHistoryItemDto, SCMHistoryItemChangeDto } from './extHost.protocol'; import { sortedDiff, equals } from 'vs/base/common/arrays'; @@ -259,7 +259,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { set value(value: string) { value = value ?? ''; - this.#proxy.$setInputBoxValue(this._sourceControlHandle, value); + this._sequencer.queue(async () => this.#proxy.$setInputBoxValue(this._sourceControlHandle, value)); this.updateValue(value); } @@ -276,7 +276,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { } set placeholder(placeholder: string) { - this.#proxy.$setInputBoxPlaceholder(this._sourceControlHandle, placeholder); + this._sequencer.queue(async () => this.#proxy.$setInputBoxPlaceholder(this._sourceControlHandle, placeholder)); this._placeholder = placeholder; } @@ -296,7 +296,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { } this._validateInput = fn; - this.#proxy.$setValidationProviderIsEnabled(this._sourceControlHandle, !!fn); + this._sequencer.queue(async () => this.#proxy.$setValidationProviderIsEnabled(this._sourceControlHandle, !!fn)); } private _enabled: boolean = true; @@ -313,7 +313,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { } this._enabled = enabled; - this.#proxy.$setInputBoxEnablement(this._sourceControlHandle, enabled); + this._sequencer.queue(async () => this.#proxy.$setInputBoxEnablement(this._sourceControlHandle, enabled)); } private _visible: boolean = true; @@ -330,7 +330,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { } this._visible = visible; - this.#proxy.$setInputBoxVisibility(this._sourceControlHandle, visible); + this._sequencer.queue(async () => this.#proxy.$setInputBoxVisibility(this._sourceControlHandle, visible)); } get document(): vscode.TextDocument { @@ -339,7 +339,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { return this.#extHostDocuments.getDocument(this._documentUri); } - constructor(private _extension: IExtensionDescription, _extHostDocuments: ExtHostDocuments, proxy: MainThreadSCMShape, private _sourceControlHandle: number, private _documentUri: URI) { + constructor(private _extension: IExtensionDescription, _extHostDocuments: ExtHostDocuments, proxy: MainThreadSCMShape, private _sequencer: Sequencer, private _sourceControlHandle: number, private _documentUri: URI) { this.#extHostDocuments = _extHostDocuments; this.#proxy = proxy; } @@ -347,7 +347,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { showValidationMessage(message: string | vscode.MarkdownString, type: vscode.SourceControlInputBoxValidationType) { checkProposedApiEnabled(this._extension, 'scmValidation'); - this.#proxy.$showValidationMessage(this._sourceControlHandle, message, type as any); + this._sequencer.queue(async () => this.#proxy.$showValidationMessage(this._sourceControlHandle, message, type as any)); } $onInputBoxValueChange(value: string): void { @@ -386,14 +386,14 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG get label(): string { return this._label; } set label(label: string) { this._label = label; - this._proxy.$updateGroupLabel(this._sourceControlHandle, this.handle, label); + this._sequencer.queue(async () => this._proxy.$updateGroupLabel(this._sourceControlHandle, this.handle, label)); } private _hideWhenEmpty: boolean | undefined = undefined; get hideWhenEmpty(): boolean | undefined { return this._hideWhenEmpty; } set hideWhenEmpty(hideWhenEmpty: boolean | undefined) { this._hideWhenEmpty = hideWhenEmpty; - this._proxy.$updateGroup(this._sourceControlHandle, this.handle, this.features); + this._sequencer.queue(async () => this._proxy.$updateGroup(this._sourceControlHandle, this.handle, this.features)); } get features(): SCMGroupFeatures { @@ -413,6 +413,7 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG constructor( private _proxy: MainThreadSCMShape, private _commands: ExtHostCommands, + private _sequencer: Sequencer, private _sourceControlHandle: number, private _id: string, private _label: string, @@ -511,6 +512,7 @@ class ExtHostSourceControl implements vscode.SourceControl { #proxy: MainThreadSCMShape; + private readonly _sequencer = new Sequencer(); private _groups: Map = new Map(); get id(): string { @@ -540,7 +542,7 @@ class ExtHostSourceControl implements vscode.SourceControl { } this._count = count; - this.#proxy.$updateSourceControl(this.handle, { count }); + this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { count })); } private _quickDiffProvider: vscode.QuickDiffProvider | undefined = undefined; @@ -555,7 +557,7 @@ class ExtHostSourceControl implements vscode.SourceControl { if (isProposedApiEnabled(this._extension, 'quickDiffProvider')) { quickDiffLabel = quickDiffProvider?.label; } - this.#proxy.$updateSourceControl(this.handle, { hasQuickDiffProvider: !!quickDiffProvider, quickDiffLabel }); + this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { hasQuickDiffProvider: !!quickDiffProvider, quickDiffLabel })); } private _historyProvider: vscode.SourceControlHistoryProvider | undefined; @@ -573,12 +575,12 @@ class ExtHostSourceControl implements vscode.SourceControl { this._historyProvider = historyProvider; this._historyProviderDisposable.value = new DisposableStore(); - this.#proxy.$updateSourceControl(this.handle, { hasHistoryProvider: !!historyProvider }); + this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { hasHistoryProvider: !!historyProvider })); if (historyProvider) { this._historyProviderDisposable.value.add(historyProvider.onDidChangeCurrentHistoryItemGroup(() => { this._historyProviderCurrentHistoryItemGroup = historyProvider?.currentHistoryItemGroup; - this.#proxy.$onDidChangeHistoryProviderCurrentHistoryItemGroup(this.handle, this._historyProviderCurrentHistoryItemGroup); + this._sequencer.queue(async () => this.#proxy.$onDidChangeHistoryProviderCurrentHistoryItemGroup(this.handle, this._historyProviderCurrentHistoryItemGroup)); })); } } @@ -595,7 +597,7 @@ class ExtHostSourceControl implements vscode.SourceControl { } this._commitTemplate = commitTemplate; - this.#proxy.$updateSourceControl(this.handle, { commitTemplate }); + this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { commitTemplate })); } private readonly _acceptInputDisposables = new MutableDisposable(); @@ -611,7 +613,7 @@ class ExtHostSourceControl implements vscode.SourceControl { this._acceptInputCommand = acceptInputCommand; const internal = this._commands.converter.toInternal(acceptInputCommand, this._acceptInputDisposables.value); - this.#proxy.$updateSourceControl(this.handle, { acceptInputCommand: internal }); + this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { acceptInputCommand: internal })); } private readonly _actionButtonDisposables = new MutableDisposable(); @@ -635,7 +637,7 @@ class ExtHostSourceControl implements vscode.SourceControl { description: actionButton.description, enabled: actionButton.enabled } : undefined; - this.#proxy.$updateSourceControl(this.handle, { actionButton: internal ?? null }); + this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { actionButton: internal ?? null })); } @@ -656,7 +658,7 @@ class ExtHostSourceControl implements vscode.SourceControl { this._statusBarCommands = statusBarCommands; const internal = (statusBarCommands || []).map(c => this._commands.converter.toInternal(c, this._statusBarDisposables.value!)) as ICommandDto[]; - this.#proxy.$updateSourceControl(this.handle, { statusBarCommands: internal }); + this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { statusBarCommands: internal })); } private _selected: boolean = false; @@ -687,8 +689,8 @@ class ExtHostSourceControl implements vscode.SourceControl { query: _rootUri ? `rootUri=${encodeURIComponent(_rootUri.toString())}` : undefined }); - this._inputBox = new ExtHostSCMInputBox(_extension, _extHostDocuments, this.#proxy, this.handle, inputBoxDocumentUri); - this.#proxy.$registerSourceControl(this.handle, _id, _label, _rootUri, inputBoxDocumentUri); + this._sequencer.queue(() => this.#proxy.$registerSourceControl(this.handle, _id, _label, _rootUri, inputBoxDocumentUri)); + this._inputBox = new ExtHostSCMInputBox(_extension, _extHostDocuments, this.#proxy, this._sequencer, this.handle, inputBoxDocumentUri); } private createdResourceGroups = new Map(); @@ -696,7 +698,7 @@ class ExtHostSourceControl implements vscode.SourceControl { createResourceGroup(id: string, label: string, options?: { multiDiffEditorEnableViewChanges?: boolean }): ExtHostSourceControlResourceGroup { const multiDiffEditorEnableViewChanges = isProposedApiEnabled(this._extension, 'scmMultiDiffEditor') && options?.multiDiffEditorEnableViewChanges === true; - const group = new ExtHostSourceControlResourceGroup(this.#proxy, this._commands, this.handle, id, label, multiDiffEditorEnableViewChanges, this._extension); + const group = new ExtHostSourceControlResourceGroup(this.#proxy, this._commands, this._sequencer, this.handle, id, label, multiDiffEditorEnableViewChanges, this._extension); const disposable = Event.once(group.onDidDispose)(() => this.createdResourceGroups.delete(group)); this.createdResourceGroups.set(group, disposable); this.eventuallyAddResourceGroups(); @@ -720,7 +722,7 @@ class ExtHostSourceControl implements vscode.SourceControl { this.updatedResourceGroups.delete(group); updateListener.dispose(); this._groups.delete(group.handle); - this.#proxy.$unregisterGroup(this.handle, group.handle); + this._sequencer.queue(async () => this.#proxy.$unregisterGroup(this.handle, group.handle)); }); groups.push([group.handle, group.id, group.label, group.features, group.multiDiffEditorEnableViewChanges]); @@ -734,7 +736,7 @@ class ExtHostSourceControl implements vscode.SourceControl { this._groups.set(group.handle, group); } - this.#proxy.$registerGroups(this.handle, groups, splices); + this._sequencer.queue(async () => this.#proxy.$registerGroups(this.handle, groups, splices)); this.createdResourceGroups.clear(); } @@ -753,7 +755,7 @@ class ExtHostSourceControl implements vscode.SourceControl { }); if (splices.length > 0) { - this.#proxy.$spliceResourceStates(this.handle, splices); + this._sequencer.queue(async () => this.#proxy.$spliceResourceStates(this.handle, splices)); } this.updatedResourceGroups.clear(); @@ -774,7 +776,7 @@ class ExtHostSourceControl implements vscode.SourceControl { this._statusBarDisposables.dispose(); this._groups.forEach(group => group.dispose()); - this.#proxy.$unregisterSourceControl(this.handle); + this._sequencer.queue(async () => this.#proxy.$unregisterSourceControl(this.handle)); } } diff --git a/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts b/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts index 6f37db49441..3a56656608b 100644 --- a/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts +++ b/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts @@ -6,6 +6,7 @@ import * as assert from 'assert'; import { promiseWithResolvers, timeout } from 'vs/base/common/async'; import { URI } from 'vs/base/common/uri'; +import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; import { ExtensionIdentifier, IExtensionDescription, IRelaxedExtensionDescription, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { NullLogService } from 'vs/platform/log/common/log'; import { ActivatedExtension, EmptyExtension, ExtensionActivationTimes, ExtensionsActivator, IExtensionsActivatorHost } from 'vs/workbench/api/common/extHostExtensionActivator'; @@ -14,6 +15,8 @@ import { ExtensionActivationReason, MissingExtensionDependency } from 'vs/workbe suite('ExtensionsActivator', () => { + ensureNoDisposablesAreLeakedInTestSuite(); + const idA = new ExtensionIdentifier(`a`); const idB = new ExtensionIdentifier(`b`); const idC = new ExtensionIdentifier(`c`); diff --git a/src/vs/workbench/browser/actions/textInputActions.ts b/src/vs/workbench/browser/actions/textInputActions.ts index dae9d15bd89..c06fb52ca30 100644 --- a/src/vs/workbench/browser/actions/textInputActions.ts +++ b/src/vs/workbench/browser/actions/textInputActions.ts @@ -8,7 +8,7 @@ import { localize } from 'vs/nls'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Disposable } from 'vs/base/common/lifecycle'; -import { EventHelper, addDisposableListener, getActiveDocument, getWindow } from 'vs/base/browser/dom'; +import { EventHelper, addDisposableListener, getActiveDocument, getWindow, isHTMLElement, isHTMLInputElement, isHTMLTextAreaElement } from 'vs/base/browser/dom'; import { IWorkbenchContribution, WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; import { isNative } from 'vs/base/common/platform'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; @@ -54,8 +54,8 @@ export class TextInputActionsProvider extends Disposable implements IWorkbenchCo else { const clipboardText = await this.clipboardService.readText(); if ( - element instanceof HTMLTextAreaElement || - element instanceof HTMLInputElement + isHTMLTextAreaElement(element) || + isHTMLInputElement(element) ) { const selectionStart = element.selectionStart || 0; const selectionEnd = element.selectionEnd || 0; @@ -88,7 +88,7 @@ export class TextInputActionsProvider extends Disposable implements IWorkbenchCo } const target = e.target; - if (!(target instanceof HTMLElement) || (target.nodeName.toLowerCase() !== 'input' && target.nodeName.toLowerCase() !== 'textarea')) { + if (!(isHTMLElement(target)) || (target.nodeName.toLowerCase() !== 'input' && target.nodeName.toLowerCase() !== 'textarea')) { return; // only for inputs or textareas } diff --git a/src/vs/workbench/browser/actions/windowActions.ts b/src/vs/workbench/browser/actions/windowActions.ts index 4020ac2b0e6..26c0b61d3d1 100644 --- a/src/vs/workbench/browser/actions/windowActions.ts +++ b/src/vs/workbench/browser/actions/windowActions.ts @@ -34,7 +34,7 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { isFolderBackupInfo, isWorkspaceBackupInfo } from 'vs/platform/backup/common/backup'; -import { getActiveElement, getActiveWindow } from 'vs/base/browser/dom'; +import { getActiveElement, getActiveWindow, isHTMLElement } from 'vs/base/browser/dom'; export const inRecentFilesPickerContextKey = 'inRecentFilesPicker'; @@ -404,7 +404,7 @@ class BlurAction extends Action2 { run(): void { const activeElement = getActiveElement(); - if (activeElement instanceof HTMLElement) { + if (isHTMLElement(activeElement)) { activeElement.blur(); } } diff --git a/src/vs/workbench/browser/parts/banner/bannerPart.ts b/src/vs/workbench/browser/parts/banner/bannerPart.ts index dda7c882d5e..e8957eae627 100644 --- a/src/vs/workbench/browser/parts/banner/bannerPart.ts +++ b/src/vs/workbench/browser/parts/banner/bannerPart.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/bannerpart'; import { localize2 } from 'vs/nls'; -import { $, addDisposableListener, append, asCSSUrl, clearNode, EventType } from 'vs/base/browser/dom'; +import { $, addDisposableListener, append, asCSSUrl, clearNode, EventType, isHTMLElement } from 'vs/base/browser/dom'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -112,7 +112,7 @@ export class BannerPart extends Part implements IBannerService { if (this.focusedActionIndex < length) { const actionLink = this.messageActionsContainer?.children[this.focusedActionIndex]; - if (actionLink instanceof HTMLElement) { + if (isHTMLElement(actionLink)) { this.actionBar?.setFocusable(false); actionLink.focus(); } diff --git a/src/vs/workbench/browser/parts/editor/editor.ts b/src/vs/workbench/browser/parts/editor/editor.ts index 138541a6ecf..066385368f8 100644 --- a/src/vs/workbench/browser/parts/editor/editor.ts +++ b/src/vs/workbench/browser/parts/editor/editor.ts @@ -242,6 +242,15 @@ export interface IEditorGroupTitleHeight { readonly offset: number; } +export interface IEditorGroupViewOptions { + + /** + * Whether the editor group should receive keyboard focus + * after creation or not. + */ + readonly preserveFocus?: boolean; +} + /** * A helper to access and mutate an editor group within an editor part. */ diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index b4665e6d8b2..67d4b7173d4 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -437,7 +437,7 @@ export class UnpinEditorAction extends Action { } } -export class CloseOneEditorAction extends Action { +export class CloseEditorTabAction extends Action { static readonly ID = 'workbench.action.closeActiveEditor'; static readonly LABEL = localize('closeOneEditor', "Close"); @@ -451,33 +451,28 @@ export class CloseOneEditorAction extends Action { } override async run(context?: IEditorCommandsContext): Promise { - let group: IEditorGroup | undefined; - let editorIndex: number | undefined; - if (context) { - group = this.editorGroupService.getGroup(context.groupId); - - if (group) { - editorIndex = context.editorIndex; // only allow editor at index if group is valid - } + const group = context ? this.editorGroupService.getGroup(context.groupId) : this.editorGroupService.activeGroup; + if (!group) { + // group mentioned in context does not exist + return; } - if (!group) { - group = this.editorGroupService.activeGroup; + const targetEditor = context?.editorIndex !== undefined ? group.getEditorByIndex(context.editorIndex) : group.activeEditor; + if (!targetEditor) { + // No editor open or editor at index does not exist + return; } - // Close specific editor in group - if (typeof editorIndex === 'number') { - const editorAtIndex = group.getEditorByIndex(editorIndex); - if (editorAtIndex) { - await group.closeEditor(editorAtIndex, { preserveFocus: context?.preserveFocus }); - return; - } + const editors: EditorInput[] = []; + if (group.isSelected(targetEditor)) { + editors.push(...group.selectedEditors); + } else { + editors.push(targetEditor); } - // Otherwise close active editor in group - if (group.activeEditor) { - await group.closeEditor(group.activeEditor, { preserveFocus: context?.preserveFocus }); - return; + // Close specific editors in group + for (const editor of editors) { + await group.closeEditor(editor, { preserveFocus: context?.preserveFocus }); } } } diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index d88cd673186..6c8c42ec330 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -28,7 +28,7 @@ import { DisposableStore, MutableDisposable, toDisposable } from 'vs/base/common import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { DeferredPromise, Promises, RunOnceWorker } from 'vs/base/common/async'; import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch'; -import { IEditorGroupsView, IEditorGroupView, fillActiveEditorViewState, EditorServiceImpl, IEditorGroupTitleHeight, IInternalEditorOpenOptions, IInternalMoveCopyOptions, IInternalEditorCloseOptions, IInternalEditorTitleControlOptions, IEditorPartsView } from 'vs/workbench/browser/parts/editor/editor'; +import { IEditorGroupsView, IEditorGroupView, fillActiveEditorViewState, EditorServiceImpl, IEditorGroupTitleHeight, IInternalEditorOpenOptions, IInternalMoveCopyOptions, IInternalEditorCloseOptions, IInternalEditorTitleControlOptions, IEditorPartsView, IEditorGroupViewOptions } from 'vs/workbench/browser/parts/editor/editor'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IAction, SubmenuAction } from 'vs/base/common/actions'; @@ -63,16 +63,16 @@ export class EditorGroupView extends Themable implements IEditorGroupView { //#region factory - static createNew(editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService): IEditorGroupView { - return instantiationService.createInstance(EditorGroupView, null, editorPartsView, groupsView, groupsLabel, groupIndex); + static createNew(editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService, options?: IEditorGroupViewOptions): IEditorGroupView { + return instantiationService.createInstance(EditorGroupView, null, editorPartsView, groupsView, groupsLabel, groupIndex, options); } - static createFromSerialized(serialized: ISerializedEditorGroupModel, editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService): IEditorGroupView { - return instantiationService.createInstance(EditorGroupView, serialized, editorPartsView, groupsView, groupsLabel, groupIndex); + static createFromSerialized(serialized: ISerializedEditorGroupModel, editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService, options?: IEditorGroupViewOptions): IEditorGroupView { + return instantiationService.createInstance(EditorGroupView, serialized, editorPartsView, groupsView, groupsLabel, groupIndex, options); } - static createCopy(copyFrom: IEditorGroupView, editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService): IEditorGroupView { - return instantiationService.createInstance(EditorGroupView, copyFrom, editorPartsView, groupsView, groupsLabel, groupIndex); + static createCopy(copyFrom: IEditorGroupView, editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService, options?: IEditorGroupViewOptions): IEditorGroupView { + return instantiationService.createInstance(EditorGroupView, copyFrom, editorPartsView, groupsView, groupsLabel, groupIndex, options); } //#endregion @@ -145,6 +145,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { readonly groupsView: IEditorGroupsView, private groupsLabel: string, private _index: number, + options: IEditorGroupViewOptions | undefined, @IInstantiationService private readonly instantiationService: IInstantiationService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @IThemeService themeService: IThemeService, @@ -236,7 +237,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { //#endregion // Restore editors if provided - const restoreEditorsPromise = this.restoreEditors(from) ?? Promise.resolve(); + const restoreEditorsPromise = this.restoreEditors(from, options) ?? Promise.resolve(); // Signal restored once editors have restored restoreEditorsPromise.finally(() => { @@ -534,7 +535,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { this.titleContainer.classList.toggle('show-file-icons', this.groupsView.partOptions.showIcons); } - private restoreEditors(from: IEditorGroupView | ISerializedEditorGroupModel | null): Promise | undefined { + private restoreEditors(from: IEditorGroupView | ISerializedEditorGroupModel | null, groupViewOptions?: IEditorGroupViewOptions): Promise | undefined { if (this.count === 0) { return; // nothing to show } @@ -571,7 +572,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // stolen accidentally on startup when the user already // clicked somewhere. - if (this.groupsView.activeGroup === this && activeElement && isActiveElement(activeElement)) { + if (this.groupsView.activeGroup === this && activeElement && isActiveElement(activeElement) && !groupViewOptions?.preserveFocus) { this.focus(); } }); diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index e467ab0270e..d785a513798 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -5,7 +5,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Part } from 'vs/workbench/browser/part'; -import { Dimension, $, EventHelper, addDisposableGenericMouseDownListener, getWindow, isAncestorOfActiveElement, getActiveElement } from 'vs/base/browser/dom'; +import { Dimension, $, EventHelper, addDisposableGenericMouseDownListener, getWindow, isAncestorOfActiveElement, getActiveElement, isHTMLElement } from 'vs/base/browser/dom'; import { Event, Emitter, Relay, PauseableEmitter } from 'vs/base/common/event'; import { contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry'; import { GroupDirection, GroupsArrangement, GroupOrientation, IMergeGroupOptions, MergeGroupMode, GroupsOrder, GroupLocation, IFindGroupScope, EditorGroupLayout, GroupLayoutArgument, IEditorSideGroup, IEditorDropTargetDelegate, IEditorPart } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -14,7 +14,7 @@ import { IView, orthogonal, LayoutPriority, IViewSize, Direction, SerializableGr import { GroupIdentifier, EditorInputWithOptions, IEditorPartOptions, IEditorPartOptionsChangeEvent, GroupModelChangeKind } from 'vs/workbench/common/editor'; import { EDITOR_GROUP_BORDER, EDITOR_PANE_BACKGROUND } from 'vs/workbench/common/theme'; import { distinct, coalesce } from 'vs/base/common/arrays'; -import { IEditorGroupView, getEditorPartOptions, impactsEditorPartOptions, IEditorPartCreationOptions, IEditorPartsView, IEditorGroupsView } from 'vs/workbench/browser/parts/editor/editor'; +import { IEditorGroupView, getEditorPartOptions, impactsEditorPartOptions, IEditorPartCreationOptions, IEditorPartsView, IEditorGroupsView, IEditorGroupViewOptions } from 'vs/workbench/browser/parts/editor/editor'; import { EditorGroupView } from 'vs/workbench/browser/parts/editor/editorGroupView'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IDisposable, dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; @@ -615,16 +615,16 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView { } } - private doCreateGroupView(from?: IEditorGroupView | ISerializedEditorGroupModel | null): IEditorGroupView { + private doCreateGroupView(from?: IEditorGroupView | ISerializedEditorGroupModel | null, options?: IEditorGroupViewOptions): IEditorGroupView { // Create group view let groupView: IEditorGroupView; if (from instanceof EditorGroupView) { - groupView = EditorGroupView.createCopy(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService,); + groupView = EditorGroupView.createCopy(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService, options); } else if (isSerializedEditorGroupModel(from)) { - groupView = EditorGroupView.createFromSerialized(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService); + groupView = EditorGroupView.createFromSerialized(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService, options); } else { - groupView = EditorGroupView.createNew(this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService); + groupView = EditorGroupView.createNew(this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService, options); } // Keep in map @@ -934,7 +934,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView { } createEditorDropTarget(container: unknown, delegate: IEditorDropTargetDelegate): IDisposable { - assertType(container instanceof HTMLElement); + assertType(isHTMLElement(container)); return this.scopedInstantiationService.createInstance(EditorDropTarget, container, delegate); } @@ -1192,7 +1192,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView { return true; // success } - private doCreateGridControlWithState(serializedGrid: ISerializedGrid, activeGroupId: GroupIdentifier, editorGroupViewsToReuse?: IEditorGroupView[]): void { + private doCreateGridControlWithState(serializedGrid: ISerializedGrid, activeGroupId: GroupIdentifier, editorGroupViewsToReuse?: IEditorGroupView[], options?: IEditorGroupViewOptions): void { // Determine group views to reuse if any let reuseGroupViews: IEditorGroupView[]; @@ -1210,7 +1210,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView { if (reuseGroupViews.length > 0) { groupView = reuseGroupViews.shift()!; } else { - groupView = this.doCreateGroupView(serializedEditorGroup); + groupView = this.doCreateGroupView(serializedEditorGroup, options); } groupViews.push(groupView); @@ -1342,15 +1342,15 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView { }; } - applyState(state: IEditorPartUIState | 'empty'): Promise { + applyState(state: IEditorPartUIState | 'empty', options?: IEditorGroupViewOptions): Promise { if (state === 'empty') { return this.doApplyEmptyState(); } else { - return this.doApplyState(state); + return this.doApplyState(state, options); } } - private async doApplyState(state: IEditorPartUIState): Promise { + private async doApplyState(state: IEditorPartUIState, options?: IEditorGroupViewOptions): Promise { const groups = await this.doPrepareApplyState(); const resumeEvents = this.disposeGroups(true /* suspress events for the duration of applying state */); @@ -1359,7 +1359,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView { // Grid Widget try { - this.doApplyGridState(state.serializedGrid, state.activeGroup); + this.doApplyGridState(state.serializedGrid, state.activeGroup, undefined, options); } finally { resumeEvents(); } @@ -1396,10 +1396,10 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView { return groups; } - private doApplyGridState(gridState: ISerializedGrid, activeGroupId: GroupIdentifier, editorGroupViewsToReuse?: IEditorGroupView[]): void { + private doApplyGridState(gridState: ISerializedGrid, activeGroupId: GroupIdentifier, editorGroupViewsToReuse?: IEditorGroupView[], options?: IEditorGroupViewOptions): void { // Recreate grid widget from state - this.doCreateGridControlWithState(gridState, activeGroupId, editorGroupViewsToReuse); + this.doCreateGridControlWithState(gridState, activeGroupId, editorGroupViewsToReuse, options); // Layout this.doLayout(this._contentDimension); diff --git a/src/vs/workbench/browser/parts/editor/editorParts.ts b/src/vs/workbench/browser/parts/editor/editorParts.ts index 574c97e4153..e505a3fd466 100644 --- a/src/vs/workbench/browser/parts/editor/editorParts.ts +++ b/src/vs/workbench/browser/parts/editor/editorParts.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { EditorGroupLayout, GroupDirection, GroupLocation, GroupOrientation, GroupsArrangement, GroupsOrder, IAuxiliaryEditorPart, IAuxiliaryEditorPartCreateEvent, IEditorGroupContextKeyProvider, IEditorDropTargetDelegate, IEditorGroupsService, IEditorSideGroup, IEditorWorkingSet, IFindGroupScope, IMergeGroupOptions } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { EditorGroupLayout, GroupDirection, GroupLocation, GroupOrientation, GroupsArrangement, GroupsOrder, IAuxiliaryEditorPart, IAuxiliaryEditorPartCreateEvent, IEditorGroupContextKeyProvider, IEditorDropTargetDelegate, IEditorGroupsService, IEditorSideGroup, IEditorWorkingSet, IFindGroupScope, IMergeGroupOptions, IEditorWorkingSetOptions } from 'vs/workbench/services/editor/common/editorGroupsService'; import { Emitter } from 'vs/base/common/event'; import { DisposableMap, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { GroupIdentifier } from 'vs/workbench/common/editor'; @@ -21,6 +21,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IAuxiliaryWindowOpenOptions, IAuxiliaryWindowService } from 'vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService'; import { generateUuid } from 'vs/base/common/uuid'; import { ContextKeyValue, IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { isHTMLElement } from 'vs/base/browser/dom'; interface IEditorPartsUIState { readonly auxiliary: IAuxiliaryEditorPartState[]; @@ -161,7 +162,7 @@ export class EditorParts extends MultiWindowParts implements IEditor override getPart(element: HTMLElement): EditorPart; override getPart(groupOrElement: IEditorGroupView | GroupIdentifier | HTMLElement): EditorPart { if (this._parts.size > 1) { - if (groupOrElement instanceof HTMLElement) { + if (isHTMLElement(groupOrElement)) { const element = groupOrElement; return this.getPartByDocument(element.ownerDocument); @@ -375,7 +376,7 @@ export class EditorParts extends MultiWindowParts implements IEditor } } - async applyWorkingSet(workingSet: IEditorWorkingSet | 'empty'): Promise { + async applyWorkingSet(workingSet: IEditorWorkingSet | 'empty', options?: IEditorWorkingSetOptions): Promise { let workingSetState: IEditorWorkingSetState | 'empty' | undefined; if (workingSet === 'empty') { workingSetState = 'empty'; @@ -395,13 +396,15 @@ export class EditorParts extends MultiWindowParts implements IEditor if (!applied) { return false; } - await this.mainPart.applyState(workingSetState === 'empty' ? workingSetState : workingSetState.main); - - // Restore Focus - const mostRecentActivePart = firstOrDefault(this.mostRecentActiveParts); - if (mostRecentActivePart) { - await mostRecentActivePart.whenReady; - mostRecentActivePart.activeGroup.focus(); + await this.mainPart.applyState(workingSetState === 'empty' ? workingSetState : workingSetState.main, options); + + // Restore Focus unless instructed otherwise + if (!options?.preserveFocus) { + const mostRecentActivePart = firstOrDefault(this.mostRecentActiveParts); + if (mostRecentActivePart) { + await mostRecentActivePart.whenReady; + mostRecentActivePart.activeGroup.focus(); + } } return true; diff --git a/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts b/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts index 395c83aa7a1..588c334451a 100644 --- a/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts +++ b/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts @@ -35,7 +35,7 @@ import { MergeGroupMode, IMergeGroupOptions } from 'vs/workbench/services/editor import { addDisposableListener, EventType, EventHelper, Dimension, scheduleAtNextAnimationFrame, findParentWithClass, clearNode, DragAndDropObserver, isMouseEvent, getWindow } from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; import { IEditorGroupsView, EditorServiceImpl, IEditorGroupView, IInternalEditorOpenOptions, IEditorPartsView } from 'vs/workbench/browser/parts/editor/editor'; -import { CloseOneEditorAction, UnpinEditorAction } from 'vs/workbench/browser/parts/editor/editorActions'; +import { CloseEditorTabAction, UnpinEditorAction } from 'vs/workbench/browser/parts/editor/editorActions'; import { assertAllDefined, assertIsDefined } from 'vs/base/common/types'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { basenameOrAuthority } from 'vs/base/common/resources'; @@ -111,7 +111,7 @@ export class MultiEditorTabsControl extends EditorTabsControl { private tabsScrollbar: ScrollableElement | undefined; private tabSizingFixedDisposables: DisposableStore | undefined; - private readonly closeEditorAction = this._register(this.instantiationService.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL)); + private readonly closeEditorAction = this._register(this.instantiationService.createInstance(CloseEditorTabAction, CloseEditorTabAction.ID, CloseEditorTabAction.LABEL)); private readonly unpinEditorAction = this._register(this.instantiationService.createInstance(UnpinEditorAction, UnpinEditorAction.ID, UnpinEditorAction.LABEL)); private readonly tabResourceLabels = this._register(this.instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER)); diff --git a/src/vs/workbench/browser/parts/editor/singleEditorTabsControl.ts b/src/vs/workbench/browser/parts/editor/singleEditorTabsControl.ts index b6b3dd436ac..cfbf35f736a 100644 --- a/src/vs/workbench/browser/parts/editor/singleEditorTabsControl.ts +++ b/src/vs/workbench/browser/parts/editor/singleEditorTabsControl.ts @@ -10,7 +10,7 @@ import { EditorTabsControl } from 'vs/workbench/browser/parts/editor/editorTabsC import { ResourceLabel, IResourceLabel } from 'vs/workbench/browser/labels'; import { TAB_ACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND } from 'vs/workbench/common/theme'; import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch'; -import { addDisposableListener, EventType, EventHelper, Dimension, isAncestor, DragAndDropObserver } from 'vs/base/browser/dom'; +import { addDisposableListener, EventType, EventHelper, Dimension, isAncestor, DragAndDropObserver, isHTMLElement } from 'vs/base/browser/dom'; import { CLOSE_EDITOR_COMMAND_ID, UNLOCK_GROUP_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands'; import { Color } from 'vs/base/common/color'; import { assertIsDefined, assertAllDefined } from 'vs/base/common/types'; @@ -130,7 +130,7 @@ export class SingleEditorTabsControl extends EditorTabsControl { // to check on the target // (https://github.com/microsoft/vscode/issues/107543) const target = e.initialTarget; - if (!(target instanceof HTMLElement) || !this.editorLabel || !isAncestor(target, this.editorLabel.element)) { + if (!(isHTMLElement(target)) || !this.editorLabel || !isAncestor(target, this.editorLabel.element)) { return; } diff --git a/src/vs/workbench/browser/parts/notifications/notificationAccessibleView.ts b/src/vs/workbench/browser/parts/notifications/notificationAccessibleView.ts index 066afd7adda..15a240f9150 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationAccessibleView.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationAccessibleView.ts @@ -92,6 +92,7 @@ export class NotificationAccessibleView implements IAccessibleViewImplentation { } return getProvider(); } + dispose() { } } diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 0bee377dce9..80c99f1557d 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -19,7 +19,7 @@ import { ThemeIcon } from 'vs/base/common/themables'; import { TITLE_BAR_ACTIVE_BACKGROUND, TITLE_BAR_ACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_BACKGROUND, TITLE_BAR_BORDER, WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme'; import { isMacintosh, isWindows, isLinux, isWeb, isNative, platformLocale } from 'vs/base/common/platform'; import { Color } from 'vs/base/common/color'; -import { EventType, EventHelper, Dimension, append, $, addDisposableListener, prepend, reset, getWindow, getWindowId, isAncestor, getActiveDocument } from 'vs/base/browser/dom'; +import { EventType, EventHelper, Dimension, append, $, addDisposableListener, prepend, reset, getWindow, getWindowId, isAncestor, getActiveDocument, isHTMLElement } from 'vs/base/browser/dom'; import { CustomMenubarControl } from 'vs/workbench/browser/parts/titlebar/menubarControl'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Emitter, Event } from 'vs/base/common/event'; @@ -474,7 +474,7 @@ export class BrowserTitlebarPart extends Part implements ITitlebarPart { EventHelper.stop(e); let targetMenu: MenuId; - if (isMacintosh && e.target instanceof HTMLElement && isAncestor(e.target, this.title)) { + if (isMacintosh && isHTMLElement(e.target) && isAncestor(e.target, this.title)) { targetMenu = MenuId.TitleBarTitleContext; } else { targetMenu = MenuId.TitleBarContext; diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index becd185fd60..db78e940c5d 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -877,7 +877,7 @@ abstract class AbstractTreeView extends Disposable implements ITreeView { const container = document.createElement('div'); container.classList.add('rendered-message'); for (const child of result) { - if (child instanceof HTMLElement) { + if (DOM.isHTMLElement(child)) { container.appendChild(child); } else { container.appendChild(child.element); diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index d1a40cc9446..d4bd1f893e8 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -73,6 +73,7 @@ export class AccessibleView extends Disposable { private _accessibleViewInCodeBlock: IContextKey; private _accessibleViewContainsCodeBlocks: IContextKey; private _codeBlocks?: ICodeBlock[]; + private _inQuickPick: boolean = false; get editorWidget() { return this._editorWidget; } private _container: HTMLElement; @@ -245,10 +246,13 @@ export class AccessibleView extends Disposable { if (!provider) { return; } + provider.onOpen?.(); + let viewContainer: HTMLElement | undefined; const delegate: IContextViewDelegate = { getAnchor: () => { return { x: (getActiveWindow().innerWidth / 2) - ((Math.min(this._layoutService.activeContainerDimension.width * 0.62 /* golden cut */, DIMENSIONS.MAX_WIDTH)) / 2), y: this._layoutService.activeContainerOffset.quickPickTop }; }, render: (container) => { - container.classList.add('accessible-view-container'); + viewContainer = container; + viewContainer.classList.add('accessible-view-container'); return this._render(provider, container, showAccessibleViewHelp); }, onHide: () => { @@ -289,6 +293,11 @@ export class AccessibleView extends Disposable { if (provider instanceof ExtensionContentProvider) { this._storageService.store(`${ACCESSIBLE_VIEW_SHOWN_STORAGE_PREFIX}${provider.id}`, true, StorageScope.APPLICATION, StorageTarget.USER); } + if (provider.onDidChangeContent) { + this._register(provider.onDidChangeContent(() => { + if (viewContainer) { this._render(provider, viewContainer, showAccessibleViewHelp); } + })); + } } previous(): void { @@ -371,8 +380,9 @@ export class AccessibleView extends Disposable { } configureKeybindings(): void { - const items = this._currentProvider?.options?.configureKeybindingItems; - const provider = this._currentProvider; + this._inQuickPick = true; + const provider = this._updateLastProvider(); + const items = provider?.options?.configureKeybindingItems; if (!items) { return; } @@ -394,6 +404,7 @@ export class AccessibleView extends Disposable { this.show(provider); } quickPick.dispose(); + this._inQuickPick = false; }); } @@ -559,9 +570,11 @@ export class AccessibleView extends Disposable { }); this._updateToolbar(this._currentProvider.actions, provider.options.type); - const hide = (e: KeyboardEvent | IKeyboardEvent): void => { - provider.onClose(); - e.stopPropagation(); + const hide = (e?: KeyboardEvent | IKeyboardEvent): void => { + if (!this._inQuickPick) { + provider.onClose(); + } + e?.stopPropagation(); this._contextViewService.hideContextView(); this._updateContextKeys(provider, false); this._lastProvider = undefined; @@ -592,7 +605,7 @@ export class AccessibleView extends Disposable { })); disposableStore.add(this._editorWidget.onDidBlurEditorWidget(() => { if (!isActiveElement(this._toolbar.getElement())) { - this._contextViewService.hideContextView(); + hide(); } })); disposableStore.add(this._editorWidget.onDidContentSizeChange(() => this._layout())); @@ -648,21 +661,25 @@ export class AccessibleView extends Disposable { provider.id, provider.options, provider.provideContent.bind(provider), - provider.onClose, + provider.onClose.bind(provider), provider.verbositySettingKey, + provider.onOpen?.bind(provider), provider.actions, - provider.next, - provider.previous, - provider.onKeyDown, - provider.getSymbols, + provider.next?.bind(provider), + provider.previous?.bind(provider), + provider.onDidChangeContent?.bind(provider), + provider.onKeyDown?.bind(provider), + provider.getSymbols?.bind(provider), ) : new ExtensionContentProvider( provider.id, provider.options, provider.provideContent.bind(provider), - provider.onClose, - provider.next, - provider.previous, - provider.actions + provider.onClose.bind(provider), + provider.onOpen?.bind(provider), + provider.next?.bind(provider), + provider.previous?.bind(provider), + provider.actions, + provider.onDidChangeContent?.bind(provider), ); return lastProvider; } diff --git a/src/vs/workbench/contrib/accessibility/browser/extensionAccesibilityHelp.contribution.ts b/src/vs/workbench/contrib/accessibility/browser/extensionAccesibilityHelp.contribution.ts index 46ea96cf1f0..f8381417bd8 100644 --- a/src/vs/workbench/contrib/accessibility/browser/extensionAccesibilityHelp.contribution.ts +++ b/src/vs/workbench/contrib/accessibility/browser/extensionAccesibilityHelp.contribution.ts @@ -56,7 +56,8 @@ function registerAccessibilityHelpAction(keybindingService: IKeybindingService, () => content, () => viewsService.openView(viewDescriptor.id, true), ); - } + }, + dispose: () => { }, })); disposableStore.add(keybindingService.onDidUpdateKeybindings(() => { diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index d7ec863b045..e7374ecb565 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -25,6 +25,7 @@ export class ChatAccessibilityHelp implements IAccessibleViewImplentation { const codeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor() || accessor.get(ICodeEditorService).getFocusedCodeEditor(); return getChatAccessibilityHelpProvider(accessor, codeEditor ?? undefined, 'panelChat'); } + dispose() { } } export function getAccessibilityHelpText(type: 'panelChat' | 'inlineChat'): string { diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts index fa695e9d757..bf426bec1b8 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts @@ -5,6 +5,7 @@ import { Codicon } from 'vs/base/common/codicons'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { ThemeIcon } from 'vs/base/common/themables'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorAction2, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; @@ -13,7 +14,7 @@ import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/act import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IsLinuxContext, IsWindowsContext } from 'vs/platform/contextkey/common/contextkeys'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; +import { IQuickInputButton, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { ViewAction } from 'vs/workbench/browser/parts/views/viewPane'; import { CHAT_VIEW_ID, IChatWidgetService, showChatView } from 'vs/workbench/contrib/chat/browser/chat'; import { IChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatEditor'; @@ -24,7 +25,7 @@ import { CONTEXT_CHAT_INPUT_CURSOR_AT_TOP, CONTEXT_CHAT_LOCATION, CONTEXT_IN_CHA import { IChatDetail, IChatService } from 'vs/workbench/contrib/chat/common/chatService'; import { IChatRequestViewModel, IChatResponseViewModel, isRequestVM } from 'vs/workbench/contrib/chat/common/chatViewModel'; import { IChatWidgetHistoryService } from 'vs/workbench/contrib/chat/common/chatWidgetHistoryService'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { ACTIVE_GROUP, IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; export interface IChatViewTitleActionContext { @@ -124,28 +125,55 @@ class ChatHistoryAction extends ViewAction { const chatService = accessor.get(IChatService); const quickInputService = accessor.get(IQuickInputService); const viewsService = accessor.get(IViewsService); + const editorService = accessor.get(IEditorService); const items = chatService.getHistory(); - const picks = items.map(i => ({ + + const openInEditorButton: IQuickInputButton = { + iconClass: ThemeIcon.asClassName(Codicon.file), + tooltip: localize('interactiveSession.history.editor', "Open in Editor"), + }; + const deleteButton: IQuickInputButton = { + iconClass: ThemeIcon.asClassName(Codicon.x), + tooltip: localize('interactiveSession.history.delete', "Delete"), + }; + + interface IChatPickerItem extends IQuickPickItem { + chat: IChatDetail; + } + const picks: IChatPickerItem[] = items.map((i): IChatPickerItem => ({ label: i.title, chat: i, - buttons: [{ - iconClass: ThemeIcon.asClassName(Codicon.x), - tooltip: localize('interactiveSession.history.delete', "Delete"), - }] + buttons: [ + openInEditorButton, + deleteButton + ] })); - const selection = await quickInputService.pick(picks, - { - placeHolder: localize('interactiveSession.history.pick', "Switch to chat"), - onDidTriggerItemButton: context => { - chatService.removeHistoryEntry(context.item.chat.sessionId); - context.removeItem(); - } - }); - if (selection) { - const sessionId = selection.chat.sessionId; - const view = await viewsService.openView(CHAT_VIEW_ID) as ChatViewPane; - view.loadSession(sessionId); - } + const store = new DisposableStore(); + const picker = store.add(quickInputService.createQuickPick()); + picker.placeholder = localize('interactiveSession.history.pick', "Switch to chat"); + picker.items = picks; + store.add(picker.onDidTriggerItemButton(context => { + if (context.button === openInEditorButton) { + editorService.openEditor({ resource: ChatEditorInput.getNewEditorUri(), options: { target: { sessionId: context.item.chat.sessionId }, pinned: true } }, ACTIVE_GROUP); + picker.hide(); + } else if (context.button === deleteButton) { + chatService.removeHistoryEntry(context.item.chat.sessionId); + picker.items = picks.filter(i => i !== context.item); + } + })); + store.add(picker.onDidAccept(async () => { + try { + const item = picker.selectedItems[0]; + const sessionId = item.chat.sessionId; + const view = await viewsService.openView(CHAT_VIEW_ID) as ChatViewPane; + view.loadSession(sessionId); + } finally { + picker.hide(); + } + })); + store.add(picker.onDidHide(() => store.dispose())); + + picker.show(); } } diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.ts index 031a4661624..c6354580571 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.ts @@ -24,7 +24,7 @@ import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatAct import { IChatWidget, IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; import { ChatContextAttachments } from 'vs/workbench/contrib/chat/browser/contrib/chatContextAttachments'; import { ChatAgentLocation, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents'; -import { CONTEXT_CHAT_LOCATION, CONTEXT_IN_AIDE_CHAT_SESSION, CONTEXT_IN_CHAT_INPUT } from 'vs/workbench/contrib/chat/common/chatContextKeys'; +import { CONTEXT_CHAT_LOCATION, CONTEXT_IN_AIDE_CHAT_SESSION, CONTEXT_IN_CHAT_INPUT, CONTEXT_IN_QUICK_CHAT } from 'vs/workbench/contrib/chat/common/chatContextKeys'; import { IChatRequestVariableEntry } from 'vs/workbench/contrib/chat/common/chatModel'; import { ChatRequestAgentPart } from 'vs/workbench/contrib/chat/common/chatParserTypes'; import { IChatVariablesService } from 'vs/workbench/contrib/chat/common/chatVariables'; @@ -94,12 +94,7 @@ class AttachContextAction extends Action2 { }, menu: [ { - when: ContextKeyExpr.and(CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Panel), CONTEXT_IN_AIDE_CHAT_SESSION.negate()), - id: MenuId.ChatExecuteSecondary, - group: 'group_1', - }, - { - when: ContextKeyExpr.and(CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Panel), CONTEXT_IN_AIDE_CHAT_SESSION.negate()), + when: ContextKeyExpr.and(CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Panel), CONTEXT_IN_QUICK_CHAT.isEqualTo(false), CONTEXT_IN_AIDE_CHAT_SESSION.negate()), id: MenuId.ChatExecute, group: 'navigation', }, diff --git a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts index 11c2e4ebeac..a8f75e8035b 100644 --- a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts @@ -62,6 +62,7 @@ import { IChatHistoryEntry, IChatWidgetHistoryService } from 'vs/workbench/contr import { getSimpleCodeEditorWidgetOptions, getSimpleEditorOptions } from 'vs/workbench/contrib/codeEditor/browser/simpleEditorOptions'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; +import { basename, dirname } from 'vs/base/common/path'; const $ = dom.$; @@ -529,14 +530,26 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge const widget = dom.append(container, $('.chat-attached-context-attachment.show-file-icons')); const label = this._contextResourceLabels.create(widget, { supportIcons: true }); const file = URI.isUri(attachment.value) ? attachment.value : attachment.value && typeof attachment.value === 'object' && 'uri' in attachment.value && URI.isUri(attachment.value.uri) ? attachment.value.uri : undefined; + const range = attachment.value && typeof attachment.value === 'object' && 'range' in attachment.value && Range.isIRange(attachment.value.range) ? attachment.value.range : undefined; if (file && attachment.isFile) { + const fileBasename = basename(file.path); + const fileDirname = dirname(file.path); + const friendlyName = `${fileBasename} ${fileDirname}`; + const ariaLabel = range ? localize('chat.fileAttachmentWithRange', "Attached file, {0}, line {1} to line {2}", friendlyName, range.startLineNumber, range.endLineNumber) : localize('chat.fileAttachment', "Attached file, {0}", friendlyName); + label.setFile(file, { fileKind: FileKind.FILE, hidePath: true, - range: attachment.value && typeof attachment.value === 'object' && 'range' in attachment.value && Range.isIRange(attachment.value.range) ? attachment.value.range : undefined, + range, }); + widget.ariaLabel = ariaLabel; + widget.tabIndex = 0; } else { - label.setLabel(attachment.fullName ?? attachment.name); + const attachmentLabel = attachment.fullName ?? attachment.name; + label.setLabel(attachmentLabel, undefined); + + widget.ariaLabel = localize('chat.attachment', "Attached context, {0}", attachment.name); + widget.tabIndex = 0; } const clearButton = new Button(widget, { supportIcons: true }); diff --git a/src/vs/workbench/contrib/chat/browser/chatResponseAccessibleView.ts b/src/vs/workbench/contrib/chat/browser/chatResponseAccessibleView.ts index d97ecba4f42..009d9f4c3b1 100644 --- a/src/vs/workbench/contrib/chat/browser/chatResponseAccessibleView.ts +++ b/src/vs/workbench/contrib/chat/browser/chatResponseAccessibleView.ts @@ -95,4 +95,5 @@ export class ChatResponseAccessibleView implements IAccessibleViewImplentation { }; } } + dispose() { } } diff --git a/src/vs/workbench/contrib/chat/browser/chatVariables.ts b/src/vs/workbench/contrib/chat/browser/chatVariables.ts index acde7f02757..8794a881e15 100644 --- a/src/vs/workbench/contrib/chat/browser/chatVariables.ts +++ b/src/vs/workbench/contrib/chat/browser/chatVariables.ts @@ -164,7 +164,7 @@ export class ChatVariablesService implements IChatVariablesService { if (key === 'file' && typeof value !== 'string') { const uri = URI.isUri(value) ? value : value.uri; const range = 'range' in value ? value.range : undefined; - widget.getContrib(ChatContextAttachments.ID)?.setContext(false, { value, id: uri.toString() + (range?.toString() ?? ''), name: basename(uri.path), isDynamic: true }); + widget.getContrib(ChatContextAttachments.ID)?.setContext(false, { value, id: uri.toString() + (range?.toString() ?? ''), name: basename(uri.path), isFile: true, isDynamic: true }); return; } diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index fe7647e7da5..955f3df0900 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -33,7 +33,7 @@ import { ChatInputPart } from 'vs/workbench/contrib/chat/browser/chatInputPart'; import { ChatListDelegate, ChatListItemRenderer, IChatRendererDelegate } from 'vs/workbench/contrib/chat/browser/chatListRenderer'; import { ChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatOptions'; import { ChatAgentLocation, IChatAgentCommand, IChatAgentData, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents'; -import { CONTEXT_CHAT_HAS_REQUESTS, CONTEXT_CHAT_INPUT_HAS_AGENT, CONTEXT_CHAT_LOCATION, CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_IN_AIDE_CHAT_SESSION, CONTEXT_IN_CHAT_SESSION, CONTEXT_RESPONSE_FILTERED } from 'vs/workbench/contrib/chat/common/chatContextKeys'; +import { CONTEXT_CHAT_HAS_REQUESTS, CONTEXT_CHAT_INPUT_HAS_AGENT, CONTEXT_CHAT_LOCATION, CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_IN_AIDE_CHAT_SESSION, CONTEXT_IN_CHAT_SESSION, CONTEXT_IN_QUICK_CHAT, CONTEXT_RESPONSE_FILTERED } from 'vs/workbench/contrib/chat/common/chatContextKeys'; import { ChatModelInitState, IChatModel, IChatRequestVariableEntry, IChatResponseModel } from 'vs/workbench/contrib/chat/common/chatModel'; import { ChatRequestAgentPart, IParsedChatRequest, chatAgentLeader, chatSubcommandLeader } from 'vs/workbench/contrib/chat/common/chatParserTypes'; import { ChatRequestParser } from 'vs/workbench/contrib/chat/common/chatRequestParser'; @@ -195,6 +195,7 @@ export class ChatWidget extends Disposable implements IChatWidget { super(); CONTEXT_IN_CHAT_SESSION.bindTo(contextKeyService).set(true); CONTEXT_CHAT_LOCATION.bindTo(contextKeyService).set(location); + CONTEXT_IN_QUICK_CHAT.bindTo(contextKeyService).set('resource' in viewContext); this.agentInInput = CONTEXT_CHAT_INPUT_HAS_AGENT.bindTo(contextKeyService); this.isAideAgent = CONTEXT_IN_AIDE_CHAT_SESSION.bindTo(contextKeyService); this.requestInProgress = CONTEXT_CHAT_REQUEST_IN_PROGRESS.bindTo(contextKeyService); diff --git a/src/vs/workbench/contrib/chat/browser/codeBlockPart.css b/src/vs/workbench/contrib/chat/browser/codeBlockPart.css index c1829e6caae..a4d0e162fd1 100644 --- a/src/vs/workbench/contrib/chat/browser/codeBlockPart.css +++ b/src/vs/workbench/contrib/chat/browser/codeBlockPart.css @@ -157,3 +157,7 @@ color: var(--vscode-textLink-foreground); cursor: pointer; } + +.interactive-result-code-block.compare .message A > CODE { + color: var(--vscode-textLink-foreground); +} diff --git a/src/vs/workbench/contrib/chat/browser/codeBlockPart.ts b/src/vs/workbench/contrib/chat/browser/codeBlockPart.ts index e8895a28189..57c1dfac9b1 100644 --- a/src/vs/workbench/contrib/chat/browser/codeBlockPart.ts +++ b/src/vs/workbench/contrib/chat/browser/codeBlockPart.ts @@ -616,6 +616,7 @@ export class CodeCompareBlockPart extends Disposable { isInEmbeddedEditor: true, useInlineViewWhenSpaceIsLimited: false, hideUnchangedRegions: { enabled: true, contextLineCount: 1 }, + renderGutterMenu: false, ...options }, { originalEditor: widgetOptions, modifiedEditor: widgetOptions })); } @@ -731,11 +732,12 @@ export class CodeCompareBlockPart extends Disposable { const uriLabel = this.labelService.getUriLabel(data.edit.uri, { relative: true, noPrefix: true }); const template = data.edit.state.applied > 1 - ? localize('chat.edits.N', "Made {0} changes in [[{1}]]", data.edit.state.applied, uriLabel) - : localize('chat.edits.1', "Made 1 change in [[{0}]]", uriLabel); + ? localize('chat.edits.N', "Made {0} changes in [[``{1}``]]", data.edit.state.applied, uriLabel) + : localize('chat.edits.1', "Made 1 change in [[``{0}``]]", uriLabel); const message = renderFormattedText(template, { + renderCodeSegments: true, actionHandler: { callback: () => { this.openerService.open(data.edit.uri, { fromUserGesture: true, allowCommands: false }); diff --git a/src/vs/workbench/contrib/chat/common/chatContextKeys.ts b/src/vs/workbench/contrib/chat/common/chatContextKeys.ts index e54474f5c14..346a7a75491 100644 --- a/src/vs/workbench/contrib/chat/common/chatContextKeys.ts +++ b/src/vs/workbench/contrib/chat/common/chatContextKeys.ts @@ -29,3 +29,4 @@ export const CONTEXT_CHAT_ENABLED = new RawContextKey('chatIsEnabled', export const CONTEXT_CHAT_INPUT_CURSOR_AT_TOP = new RawContextKey('chatCursorAtTop', false); export const CONTEXT_CHAT_INPUT_HAS_AGENT = new RawContextKey('chatInputHasAgent', false); export const CONTEXT_CHAT_LOCATION = new RawContextKey('chatLocation', undefined); +export const CONTEXT_IN_QUICK_CHAT = new RawContextKey('quickChatHasFocus', false, { type: 'boolean', description: localize('inQuickChat', "True when the quick chat UI has focus, false otherwise.") }); diff --git a/src/vs/workbench/contrib/chat/common/chatModel.ts b/src/vs/workbench/contrib/chat/common/chatModel.ts index 1855c0d7020..728c21bb4c7 100644 --- a/src/vs/workbench/contrib/chat/common/chatModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatModel.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { localize } from 'vs/nls'; import { asArray, firstOrDefault } from 'vs/base/common/arrays'; import { DeferredPromise } from 'vs/base/common/async'; import { Emitter, Event } from 'vs/base/common/event'; @@ -252,7 +253,7 @@ export class Response implements IResponse { } else if (part.kind === 'command') { return part.command.title; } else if (part.kind === 'textEditGroup') { - return ''; + return localize('editsSummary', "Made changes."); } else if (part.kind === 'progressMessage') { return ''; } else if (part.kind === 'confirmation') { diff --git a/src/vs/workbench/contrib/chat/common/voiceChatService.ts b/src/vs/workbench/contrib/chat/common/voiceChatService.ts index ac140ad3c6b..88ec821567b 100644 --- a/src/vs/workbench/contrib/chat/common/voiceChatService.ts +++ b/src/vs/workbench/contrib/chat/common/voiceChatService.ts @@ -152,7 +152,8 @@ export class VoiceChatService extends Disposable implements IVoiceChatService { disposables.add(session.onDidChange(e => { switch (e.status) { case SpeechToTextStatus.Recognizing: - case SpeechToTextStatus.Recognized: + case SpeechToTextStatus.Recognized: { + let massagedEvent: IVoiceChatTextEvent = e; if (e.text) { const startsWithAgent = e.text.startsWith(VoiceChatService.PHRASES_UPPER[VoiceChatService.AGENT_PREFIX]) || e.text.startsWith(VoiceChatService.PHRASES_LOWER[VoiceChatService.AGENT_PREFIX]); const startsWithSlashCommand = e.text.startsWith(VoiceChatService.PHRASES_UPPER[VoiceChatService.COMMAND_PREFIX]) || e.text.startsWith(VoiceChatService.PHRASES_LOWER[VoiceChatService.COMMAND_PREFIX]); @@ -208,15 +209,16 @@ export class VoiceChatService extends Disposable implements IVoiceChatService { } } - emitter.fire({ + massagedEvent = { status: e.status, text: (transformedWords ?? originalWords).join(' '), waitingForInput - }); - - break; + }; } } + emitter.fire(massagedEvent); + break; + } case SpeechToTextStatus.Started: this.activeVoiceChatSessions++; this.voiceChatInProgress.set(true); @@ -226,7 +228,7 @@ export class VoiceChatService extends Disposable implements IVoiceChatService { onSessionStoppedOrCanceled(false); emitter.fire(e); break; - default: + case SpeechToTextStatus.Error: emitter.fire(e); break; } diff --git a/src/vs/workbench/contrib/codeEditor/browser/dictation/editorDictation.ts b/src/vs/workbench/contrib/codeEditor/browser/dictation/editorDictation.ts index 705308f8619..bfef8956ae8 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/dictation/editorDictation.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/dictation/editorDictation.ts @@ -29,6 +29,7 @@ import { assertIsDefined } from 'vs/base/common/types'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { toAction } from 'vs/base/common/actions'; import { ThemeIcon } from 'vs/base/common/themables'; +import { isWindows } from 'vs/base/common/platform'; const EDITOR_DICTATION_IN_PROGRESS = new RawContextKey('editorDictation.inProgress', false); const VOICE_CATEGORY = localize2('voiceCategory', "Voice"); @@ -48,7 +49,10 @@ export class EditorDictationStartAction extends EditorAction2 { f1: true, keybinding: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyV, - weight: KeybindingWeight.WorkbenchContrib + weight: KeybindingWeight.WorkbenchContrib, + secondary: isWindows ? [ + KeyMod.Alt | KeyCode.Backquote + ] : undefined } }); } diff --git a/src/vs/workbench/contrib/codeEditor/browser/diffEditorAccessibilityHelp.ts b/src/vs/workbench/contrib/codeEditor/browser/diffEditorAccessibilityHelp.ts index 6ca47252ca5..ef4ce7693a1 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/diffEditorAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/diffEditorAccessibilityHelp.ts @@ -61,4 +61,5 @@ export class DiffEditorAccessibilityHelp implements IAccessibleViewImplentation options: { type: AccessibleViewType.Help } }; } + dispose() { } } diff --git a/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts b/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts index e4d481e7fe1..8b2fa1d6632 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts @@ -326,7 +326,7 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget { if (semanticTokenInfo.metadata[property] !== undefined) { const definition = semanticTokenInfo.definitions[property]; const defValue = this._renderTokenStyleDefinition(definition, property); - const defValueStr = defValue.map(el => el instanceof HTMLElement ? el.outerHTML : el).join(); + const defValueStr = defValue.map(el => dom.isHTMLElement(el) ? el.outerHTML : el).join(); let properties = propertiesByDefValue[defValueStr]; if (!properties) { propertiesByDefValue[defValueStr] = properties = []; diff --git a/src/vs/workbench/contrib/codeEditor/test/node/autoindent.test.ts b/src/vs/workbench/contrib/codeEditor/test/node/autoindent.test.ts index 9344f1a46a6..10b9058bfb9 100644 --- a/src/vs/workbench/contrib/codeEditor/test/node/autoindent.test.ts +++ b/src/vs/workbench/contrib/codeEditor/test/node/autoindent.test.ts @@ -22,6 +22,7 @@ import { ILanguageService } from 'vs/editor/common/languages/language'; import { EncodedTokenizationResult, IState, ITokenizationSupport, TokenizationRegistry } from 'vs/editor/common/languages'; import { NullState } from 'vs/editor/common/languages/nullTokenize'; import { MetadataConsts, StandardTokenType } from 'vs/editor/common/encodedTokenAttributes'; +import { ITextModel } from 'vs/editor/common/model'; function getIRange(range: IRange): IRange { return { @@ -36,12 +37,22 @@ const enum LanguageId { TypeScript = 'ts-test' } +function forceTokenizationFromLineToLine(model: ITextModel, startLine: number, endLine: number): void { + for (let line = startLine; line <= endLine; line++) { + model.tokenization.forceTokenization(line); + } +} + function registerLanguage(instantiationService: TestInstantiationService, languageId: LanguageId): IDisposable { - const languageService = instantiationService.get(ILanguageService) - return languageService.registerLanguage({ id: languageId }); + const disposables = new DisposableStore(); + const languageService = instantiationService.get(ILanguageService); + disposables.add(registerLanguageConfiguration(instantiationService, languageId)); + disposables.add(languageService.registerLanguage({ id: languageId })); + return disposables; } -function registerLanguageConfiguration(languageConfigurationService: ILanguageConfigurationService, languageId: LanguageId): IDisposable { +function registerLanguageConfiguration(instantiationService: TestInstantiationService, languageId: LanguageId): IDisposable { + const languageConfigurationService = instantiationService.get(ILanguageConfigurationService); let configPath: string; switch (languageId) { case LanguageId.TypeScript: @@ -61,7 +72,7 @@ interface StandardTokenTypeData { standardTokenType: StandardTokenType; } -function registerTokenizationSupport(instantiationService: TestInstantiationService, tokens: StandardTokenTypeData[][], languageId: string): IDisposable { +function registerTokenizationSupport(instantiationService: TestInstantiationService, tokens: StandardTokenTypeData[][], languageId: LanguageId): IDisposable { let lineIndex = 0; const languageService = instantiationService.get(ILanguageService); const tokenizationSupport: ITokenizationSupport = { @@ -97,7 +108,7 @@ suite('Auto-Reindentation - TypeScript/JavaScript', () => { languageConfigurationService = instantiationService.get(ILanguageConfigurationService); disposables.add(instantiationService); disposables.add(registerLanguage(instantiationService, languageId)); - disposables.add(registerLanguageConfiguration(languageConfigurationService, languageId)); + disposables.add(registerLanguageConfiguration(instantiationService, languageId)); }); teardown(() => { @@ -218,8 +229,7 @@ suite('Auto-Reindentation - TypeScript/JavaScript', () => { ]; disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); const model = disposables.add(instantiateTextModel(instantiationService, fileContents, languageId, options)); - model.tokenization.forceTokenization(1); - model.tokenization.forceTokenization(2); + forceTokenizationFromLineToLine(model, 1, 2); const editOperations = getReindentEditOperations(model, languageConfigurationService, 1, model.getLineCount()); assert.deepStrictEqual(editOperations.length, 1); const operation = editOperations[0]; @@ -338,8 +348,7 @@ suite('Auto-Reindentation - TypeScript/JavaScript', () => { ]; disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); const model = disposables.add(instantiateTextModel(instantiationService, fileContents, languageId, options)); - model.tokenization.forceTokenization(1); - model.tokenization.forceTokenization(2); + forceTokenizationFromLineToLine(model, 1, 2); const editOperations = getReindentEditOperations(model, languageConfigurationService, 1, model.getLineCount()); assert.deepStrictEqual(editOperations.length, 1); const operation = editOperations[0]; @@ -373,6 +382,38 @@ suite('Auto-Reindentation - TypeScript/JavaScript', () => { assert.deepStrictEqual(editOperations.length, 0); }); + test('Issue #209859: do not do reindentation for tokens inside of a string', () => { + + // issue: https://github.com/microsoft/vscode/issues/209859 + + const tokens: StandardTokenTypeData[][] = [ + [ + { startIndex: 0, standardTokenType: StandardTokenType.Other }, + { startIndex: 12, standardTokenType: StandardTokenType.String }, + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.String }, + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.String }, + ], + [ + { startIndex: 0, standardTokenType: StandardTokenType.String }, + ] + ]; + disposables.add(registerTokenizationSupport(instantiationService, tokens, languageId)); + const fileContents = [ + 'const foo = `some text', + ' which is strangely', + ' indented. It should', + ' not be reindented.`' + ].join('\n'); + const model = disposables.add(instantiateTextModel(instantiationService, fileContents, languageId, options)); + forceTokenizationFromLineToLine(model, 1, 4); + const editOperations = getReindentEditOperations(model, languageConfigurationService, 1, model.getLineCount()); + assert.deepStrictEqual(editOperations.length, 0); + }); + // Failing tests inferred from the current regexes... test.skip('Incorrect deindentation after `*/}` string', () => { diff --git a/src/vs/workbench/contrib/comments/browser/commentReply.ts b/src/vs/workbench/contrib/comments/browser/commentReply.ts index 3580e96799b..9c9c8e24e50 100644 --- a/src/vs/workbench/contrib/comments/browser/commentReply.ts +++ b/src/vs/workbench/contrib/comments/browser/commentReply.ts @@ -117,9 +117,11 @@ export class CommentReply extends Disposable { this.setCommentEditorDecorations(); // Only add the additional step of clicking a reply button to expand the textarea when there are existing comments - if (hasExistingComments) { + if (this._pendingComment) { + this.expandReplyArea(); + } else if (hasExistingComments) { this.createReplyButton(this.commentEditor, this.form); - } else if (focus && ((this._commentThread.comments && this._commentThread.comments.length === 0) || this._pendingComment)) { + } else if (focus && (this._commentThread.comments && this._commentThread.comments.length === 0)) { this.expandReplyArea(); } this._error = dom.append(this.form, dom.$('.validation-error.hidden')); diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadHeader.ts b/src/vs/workbench/contrib/comments/browser/commentThreadHeader.ts index 9784625cd2f..2849c9afd76 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadHeader.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadHeader.ts @@ -65,6 +65,7 @@ export class CommentThreadHeader extends Disposable { this._collapseAction = new Action('review.expand', nls.localize('label.collapse', "Collapse"), COLLAPSE_ACTION_CLASS, true, () => this._delegate.collapse()); const menu = this._commentMenus.getCommentThreadTitleActions(this._contextKeyService); + this._register(menu); this.setActionBarActions(menu); this._register(menu); diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts index 3c61b8bc26f..a919fe262a9 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts @@ -88,7 +88,7 @@ export class CommentThreadWidget extends this._commentMenus = this.commentService.getCommentMenus(this._owner); - this._header = new CommentThreadHeader( + this._register(this._header = new CommentThreadHeader( container, { collapse: this.collapse.bind(this) @@ -98,7 +98,7 @@ export class CommentThreadWidget extends this._contextKeyService, this._scopedInstantiationService, contextMenuService - ); + )); this._header.updateCommentThread(this._commentThread); diff --git a/src/vs/workbench/contrib/comments/browser/commentsAccessibility.ts b/src/vs/workbench/contrib/comments/browser/commentsAccessibility.ts index 5ce9ac9a0ba..1c247dec349 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsAccessibility.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsAccessibility.ts @@ -48,4 +48,5 @@ export class CommentsAccessibilityHelp implements IAccessibleViewImplentation { getProvider(accessor: ServicesAccessor) { return accessor.get(IInstantiationService).createInstance(CommentsAccessibilityHelpProvider); } + dispose() { } } diff --git a/src/vs/workbench/contrib/comments/browser/commentsController.ts b/src/vs/workbench/contrib/comments/browser/commentsController.ts index 5ba6ca59e04..d679c223423 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsController.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsController.ts @@ -1128,7 +1128,7 @@ export class CommentController implements IEditorContribution { if (!newCommentInfos.length || !this.editor?.hasModel()) { this._addInProgress = false; if (!newCommentInfos.length) { - throw new Error('There are no commenting ranges at the current position.'); + throw new Error(`There are no commenting ranges at the current position (${range ? 'with range' : 'without range'}).`); } return Promise.resolve(); } diff --git a/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts b/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts index 075791be12a..a5ba220e380 100644 --- a/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts @@ -42,7 +42,7 @@ suite('Debug - Base Debug View', () => { assert.strictEqual(treeContainer.className, 'debug-view-content'); assert.strictEqual(container.childElementCount, 1); assert.strictEqual(container.firstChild, treeContainer); - assert.strictEqual(treeContainer instanceof HTMLDivElement, true); + assert.strictEqual(dom.isHTMLDivElement(treeContainer), true); }); test('render expression value', () => { diff --git a/src/vs/workbench/contrib/debug/test/browser/debugANSIHandling.test.ts b/src/vs/workbench/contrib/debug/test/browser/debugANSIHandling.test.ts index c6901f77f85..c92a240a220 100644 --- a/src/vs/workbench/contrib/debug/test/browser/debugANSIHandling.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/debugANSIHandling.test.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; +import { isHTMLSpanElement } from 'vs/base/browser/dom'; import { Color, RGBA } from 'vs/base/common/color'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { generateUuid } from 'vs/base/common/uuid'; @@ -66,7 +67,7 @@ suite('Debug - ANSI Handling', () => { assert.strictEqual(2, root.children.length); child = root.firstChild!; - if (child instanceof HTMLSpanElement) { + if (isHTMLSpanElement(child)) { assert.strictEqual('content1', child.textContent); assert(child.classList.contains('class1')); assert(child.classList.contains('class2')); @@ -75,7 +76,7 @@ suite('Debug - ANSI Handling', () => { } child = root.lastChild!; - if (child instanceof HTMLSpanElement) { + if (isHTMLSpanElement(child)) { assert.strictEqual('content2', child.textContent); assert(child.classList.contains('class2')); assert(child.classList.contains('class3')); @@ -94,7 +95,7 @@ suite('Debug - ANSI Handling', () => { const root: HTMLSpanElement = handleANSIOutput(sequence, linkDetector, themeService, session.root); assert.strictEqual(1, root.children.length); const child: Node = root.lastChild!; - if (child instanceof HTMLSpanElement) { + if (isHTMLSpanElement(child)) { return child; } else { assert.fail('Unexpected assertion error'); @@ -408,7 +409,7 @@ suite('Debug - ANSI Handling', () => { assert.strictEqual(elementsExpected, root.children.length); for (let i = 0; i < elementsExpected; i++) { const child: Node = root.children[i]; - if (child instanceof HTMLSpanElement) { + if (isHTMLSpanElement(child)) { assertions[i](child); } else { assert.fail('Unexpected assertion error'); diff --git a/src/vs/workbench/contrib/debug/test/browser/linkDetector.test.ts b/src/vs/workbench/contrib/debug/test/browser/linkDetector.test.ts index e389f76ae26..6a38dac9fdc 100644 --- a/src/vs/workbench/contrib/debug/test/browser/linkDetector.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/linkDetector.test.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; +import { isHTMLAnchorElement } from 'vs/base/browser/dom'; import { isWindows } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; @@ -33,7 +34,7 @@ suite('Debug - Link Detector', () => { * @param element The Element to verify. */ function assertElementIsLink(element: Element) { - assert(element instanceof HTMLAnchorElement); + assert(isHTMLAnchorElement(element)); } test('noLinks', () => { diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 92a43009c52..0ff4dca2f71 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -13,7 +13,7 @@ import { EnablementState, IExtensionManagementServerService, IWorkbenchExtension import { IExtensionIgnoredRecommendationsService, IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { VIEWLET_ID, IExtensionsWorkbenchService, IExtensionsViewPaneContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, WORKSPACE_RECOMMENDATIONS_VIEW_ID, IWorkspaceRecommendedExtensionsView, AutoUpdateConfigurationKey, HasOutdatedExtensionsContext, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, ExtensionEditorTab, THEME_ACTIONS_GROUP, INSTALL_ACTIONS_GROUP, OUTDATED_EXTENSIONS_VIEW_ID, CONTEXT_HAS_GALLERY, IExtension, extensionsSearchActionsMenu, UPDATE_ACTIONS_GROUP } from 'vs/workbench/contrib/extensions/common/extensions'; +import { VIEWLET_ID, IExtensionsWorkbenchService, IExtensionsViewPaneContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, WORKSPACE_RECOMMENDATIONS_VIEW_ID, IWorkspaceRecommendedExtensionsView, AutoUpdateConfigurationKey, HasOutdatedExtensionsContext, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, ExtensionEditorTab, THEME_ACTIONS_GROUP, INSTALL_ACTIONS_GROUP, OUTDATED_EXTENSIONS_VIEW_ID, CONTEXT_HAS_GALLERY, IExtension, extensionsSearchActionsMenu, UPDATE_ACTIONS_GROUP, IExtensionArg } from 'vs/workbench/contrib/extensions/common/extensions'; import { ReinstallAction, InstallSpecificVersionOfExtensionAction, ConfigureWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, PromptExtensionInstallFailureAction, SearchExtensionsAction, SetColorThemeAction, SetFileIconThemeAction, SetProductIconThemeAction, ClearLanguageAction, ToggleAutoUpdateForExtensionAction, ToggleAutoUpdatesForPublisherAction, TogglePreReleaseExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput'; import { ExtensionEditor } from 'vs/workbench/contrib/extensions/browser/extensionEditor'; @@ -80,6 +80,7 @@ import { IStringDictionary } from 'vs/base/common/collections'; import { CONTEXT_KEYBINDINGS_EDITOR } from 'vs/workbench/contrib/preferences/common/preferences'; import { DeprecatedExtensionsChecker } from 'vs/workbench/contrib/extensions/browser/deprecatedExtensionsChecker'; import { ProgressLocation } from 'vs/platform/progress/common/progress'; +import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; // Singletons registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService, InstantiationType.Eager /* Auto updates extensions */); @@ -1534,8 +1535,9 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('isDefaultApplicationScopedExtension').negate(), ContextKeyExpr.has('isBuiltinExtension').negate(), ContextKeyExpr.equals('isWorkspaceScopedExtension', false)), order: 3 }, - run: async (accessor: ServicesAccessor, id: string) => { - const extension = this.extensionsWorkbenchService.local.find(e => areSameExtensions({ id }, e.identifier)); + run: async (accessor: ServicesAccessor, _: string, extensionArg: IExtensionArg) => { + const uriIdentityService = accessor.get(IUriIdentityService); + const extension = extensionArg.location ? this.extensionsWorkbenchService.installed.find(e => uriIdentityService.extUri.isEqual(e.local?.location, extensionArg.location)) : undefined; if (extension) { return this.extensionsWorkbenchService.toggleApplyExtensionToAllProfiles(extension); } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index a2f80109939..fc174208ee6 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -12,7 +12,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import * as json from 'vs/base/common/json'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { disposeIfDisposable } from 'vs/base/common/lifecycle'; -import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewPaneContainer, IExtensionContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID, THEME_ACTIONS_GROUP, INSTALL_ACTIONS_GROUP, UPDATE_ACTIONS_GROUP, AutoUpdateConfigurationKey, AutoUpdateConfigurationValue, ExtensionEditorTab, ExtensionRuntimeActionType } from 'vs/workbench/contrib/extensions/common/extensions'; +import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewPaneContainer, IExtensionContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID, THEME_ACTIONS_GROUP, INSTALL_ACTIONS_GROUP, UPDATE_ACTIONS_GROUP, AutoUpdateConfigurationKey, AutoUpdateConfigurationValue, ExtensionEditorTab, ExtensionRuntimeActionType, IExtensionArg } from 'vs/workbench/contrib/extensions/common/extensions'; import { ExtensionsConfigurationInitialContent } from 'vs/workbench/contrib/extensions/common/extensionsFileTemplate'; import { IGalleryExtension, IExtensionGalleryService, ILocalExtension, InstallOptions, InstallOperation, TargetPlatformToString, ExtensionManagementErrorCode } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; @@ -1272,9 +1272,15 @@ export class MenuItemExtensionAction extends ExtensionAction { override async run(): Promise { if (this.extension) { - await this.action.run(this.extension.local ? getExtensionId(this.extension.local.manifest.publisher, this.extension.local.manifest.name) + const id = this.extension.local ? getExtensionId(this.extension.local.manifest.publisher, this.extension.local.manifest.name) : this.extension.gallery ? getExtensionId(this.extension.gallery.publisher, this.extension.gallery.name) - : this.extension.identifier.id); + : this.extension.identifier.id; + const extensionArg: IExtensionArg = { + id: this.extension.identifier.id, + version: this.extension.version, + location: this.extension.local?.location + }; + await this.action.run(id, extensionArg); } } } @@ -2571,7 +2577,6 @@ export class ExtensionStatusAction extends ExtensionAction { } } if (this.extension.enablementState === EnablementState.EnabledGlobally) { - this.updateStatus({ message: new MarkdownString(localize('globally enabled', "This extension is enabled globally.")) }, true); return; } } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index ff6e3ac39d7..3eb8c7ee130 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -690,11 +690,28 @@ class Extensions extends Disposable { all.push(...await this.workbenchExtensionManagementService.getInstalledWorkspaceExtensions(true)); } - // dedup user and system extensions by giving priority to user extensions. + // dedup workspace, user and system extensions by giving priority to workspace first and then to user extension. const installed = groupByExtension(all, r => r.identifier).reduce((result, extensions) => { - const extension = extensions.length === 1 ? extensions[0] - : extensions.find(e => e.type === ExtensionType.User) || extensions.find(e => e.type === ExtensionType.System); - result.push(extension!); + if (extensions.length === 1) { + result.push(extensions[0]); + } else { + let workspaceExtension: ILocalExtension | undefined, + userExtension: ILocalExtension | undefined, + systemExtension: ILocalExtension | undefined; + for (const extension of extensions) { + if (extension.isWorkspaceScoped) { + workspaceExtension = extension; + } else if (extension.type === ExtensionType.User) { + userExtension = extension; + } else { + systemExtension = extension; + } + } + const extension = workspaceExtension ?? userExtension ?? systemExtension; + if (extension) { + result.push(extension); + } + } return result; }, []); @@ -1300,7 +1317,9 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension if (isUninstalled) { const canRemoveRunningExtension = runningExtension && this.extensionService.canRemoveExtension(runningExtension); - const isSameExtensionRunning = runningExtension && (!extension.server || extension.server === this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension))); + const isSameExtensionRunning = runningExtension + && (!extension.server || extension.server === this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension))) + && (!extension.resourceExtension || this.uriIdentityService.extUri.isEqual(extension.resourceExtension.location, runningExtension.extensionLocation)); if (!canRemoveRunningExtension && isSameExtensionRunning && !runningExtension.isUnderDevelopment) { return { action: reloadAction, reason: nls.localize('postUninstallTooltip', "Please {0} to complete the uninstallation of this extension.", reloadActionLabel) }; } @@ -1828,6 +1847,9 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension update = true; } } + if (extensionOrPublisher.local?.pinned) { + await this.extensionManagementService.updateMetadata(extensionOrPublisher.local, { pinned: false }); + } } // Disable Auto Updates else { @@ -2147,7 +2169,27 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension if (!extension.local || isApplicationScopedExtension(extension.local.manifest) || extension.isBuiltin) { return; } - await this.extensionManagementService.toggleAppliationScope(extension.local, this.userDataProfileService.currentProfile.extensionsResource); + const isApplicationScoped = extension.local.isApplicationScoped; + await Promise.all(this.getAllExtensions().map(async extensions => { + const local = extensions.local.find(e => areSameExtensions(e.identifier, extension.identifier))?.local; + if (local && local.isApplicationScoped === isApplicationScoped) { + await this.extensionManagementService.toggleAppliationScope(local, this.userDataProfileService.currentProfile.extensionsResource); + } + })); + } + + private getAllExtensions(): Extensions[] { + const extensions: Extensions[] = []; + if (this.localExtensions) { + extensions.push(this.localExtensions); + } + if (this.remoteExtensions) { + extensions.push(this.remoteExtensions); + } + if (this.webExtensions) { + extensions.push(this.webExtensions); + } + return extensions; } private isInstalledExtensionSynced(extension: ILocalExtension): boolean { diff --git a/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css b/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css index 59a07a33c6f..a59e7c53d77 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css +++ b/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css @@ -215,7 +215,6 @@ } .extension-editor > .header > .details > .actions-status-container > .monaco-action-bar > .actions-container > .action-item:not(.checkbox-action-item) .extension-action:not(.icon) { - border-radius: 0; padding-top: 0; padding-bottom: 0; } diff --git a/src/vs/workbench/contrib/extensions/common/extensions.ts b/src/vs/workbench/contrib/extensions/common/extensions.ts index 737e37568bc..179624e281b 100644 --- a/src/vs/workbench/contrib/extensions/common/extensions.ts +++ b/src/vs/workbench/contrib/extensions/common/extensions.ts @@ -230,3 +230,9 @@ export const INSTALL_ACTIONS_GROUP = '0_install'; export const UPDATE_ACTIONS_GROUP = '0_update'; export const extensionsSearchActionsMenu = new MenuId('extensionsSearchActionsMenu'); + +export interface IExtensionArg { + id: string; + version: string; + location: URI | undefined; +} diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index d8e22884dc8..a94048551aa 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -610,7 +610,7 @@ export class ExplorerView extends ViewPane implements IExplorerView { let anchor = e.anchor; // Adjust for compressed folders (except when mouse is used) - if (anchor instanceof HTMLElement) { + if (DOM.isHTMLElement(anchor)) { if (stat) { const controllers = this.renderer.getCompressedNavigationController(stat); diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index 068fde51b80..bda9eb9b2aa 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -575,7 +575,7 @@ export class FilesRenderer implements ICompressibleTreeRenderer { } function getIconLabelNameFromHTMLElement(target: HTMLElement | EventTarget | Element | null): { element: HTMLElement; count: number; index: number } | null { - if (!(target instanceof HTMLElement)) { + if (!(DOM.isHTMLElement(target))) { return null; } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatAccessibilityHelp.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatAccessibilityHelp.ts index d168f54f836..a2348928fb6 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatAccessibilityHelp.ts @@ -23,4 +23,5 @@ export class InlineChatAccessibilityHelp implements IAccessibleViewImplentation } return getChatAccessibilityHelpProvider(accessor, codeEditor, 'inlineChat'); } + dispose() { } } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatAccessibleView.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatAccessibleView.ts index 4cac306c23f..91a719e1999 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatAccessibleView.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatAccessibleView.ts @@ -42,4 +42,5 @@ export class InlineChatAccessibleView implements IAccessibleViewImplentation { options: { type: AccessibleViewType.View } }; } + dispose() { } } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 5d2d6916b25..bcb365cb1e1 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -442,15 +442,9 @@ export class InlineChatController implements IEditorContribution { } }); } else if (e.kind === 'removeRequest') { - // TODO@jrieken this currently is buggy when removing not the very last request/response - // if (this._session!.lastExchange?.response instanceof ReplyResponse) { - // try { - // this._session!.hunkData.ignoreTextModelNChanges = true; - // await this._strategy!.undoChanges(this._session!.lastExchange.response.modelAltVersionId); - // } finally { - // this._session!.hunkData.ignoreTextModelNChanges = false; - // } - // } + // TODO@jrieken this is buggy/weird when having code changes from multiple turns because + // logically they are all the same hunks + this._strategy?.cancel(); } })); diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index 7610ddc410c..4d04b681c5b 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -614,6 +614,16 @@ export class EditorBasedInlineChatWidget extends InlineChatWidget { // --- layout + override get contentHeight(): number { + let result = super.contentHeight; + + if (this._accessibleViewer.value) { + result += this._accessibleViewer.value.height; + } + + return result; + } + protected override _doLayout(dimension: Dimension): void { let newHeight = dimension.height; diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.ts index 3b857169ade..2002f061913 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.ts @@ -147,6 +147,7 @@ export class InlineChatZoneWidget extends ZoneWidget { super.show(position, this._computeHeightInLines()); this._setWidgetMargins(position); + this.widget.chatWidget.setVisible(true); this.widget.focus(); scrollState.restore(this.editor); @@ -209,6 +210,7 @@ export class InlineChatZoneWidget extends ZoneWidget { this.container!.classList.remove('inside-selection'); this._ctxCursorPosition.reset(); this.widget.reset(); + this.widget.chatWidget.setVisible(false); super.hide(); aria.status(localize('inlineChatClosed', 'Closed inline chat widget')); } diff --git a/src/vs/workbench/contrib/inlineChat/browser/media/inlineChat.css b/src/vs/workbench/contrib/inlineChat/browser/media/inlineChat.css index e7b6f8a6c0b..a2d1666ef79 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/media/inlineChat.css +++ b/src/vs/workbench/contrib/inlineChat/browser/media/inlineChat.css @@ -68,6 +68,7 @@ display: flex; justify-content: space-between; align-items: center; + margin-top: 3px; /*makes space for action focus borders: https://github.com/microsoft/vscode-copilot/issues/5814 */ } .monaco-workbench .inline-chat .status .actions.hidden { @@ -142,6 +143,7 @@ .monaco-workbench .inline-chat .status .actions { display: flex; + padding-top: 3px; } .monaco-workbench .inline-chat .status .actions > .monaco-button, diff --git a/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts b/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts index 12fbfb027af..14d1bac7f24 100644 --- a/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts +++ b/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts @@ -60,6 +60,7 @@ import { ChatVariablesService } from 'vs/workbench/contrib/chat/browser/chatVari import { ICommandService } from 'vs/platform/commands/common/commands'; import { TestCommandService } from 'vs/editor/test/browser/editorTestServices'; import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService'; +import { RerunAction } from 'vs/workbench/contrib/inlineChat/browser/inlineChatActions'; suite('InteractiveChatController', function () { @@ -458,4 +459,39 @@ suite('InteractiveChatController', function () { assert.ok(model.getValue().includes('MANUAL')); }); + + test('re-run should discard pending edits', async function () { + + let count = 1; + + store.add(chatAgentService.registerDynamicAgent({ + id: 'testEditorAgent2', + ...agentData + }, { + async invoke(request, progress, history, token) { + progress({ kind: 'textEdit', uri: model.uri, edits: [{ range: new Range(1, 1, 1, 1), text: request.message + (count++) }] }); + return {}; + }, + })); + + ctrl = instaService.createInstance(TestController, editor); + const rerun = new RerunAction(); + + model.setValue(''); + + const p = ctrl.waitFor([...TestController.INIT_SEQUENCE, State.SHOW_REQUEST, State.SHOW_RESPONSE, State.WAIT_FOR_INPUT]); + const r = ctrl.run({ message: 'PROMPT_', autoSend: true }); + await p; + + assert.strictEqual(model.getValue(), 'PROMPT_1'); + + const p2 = ctrl.waitFor([State.SHOW_REQUEST, State.SHOW_RESPONSE, State.WAIT_FOR_INPUT]); + await instaService.invokeFunction(rerun.runInlineChatCommand, ctrl, editor); + + await p2; + + assert.strictEqual(model.getValue(), 'PROMPT_2'); + ctrl.finishExistingSession(); + await r; + }); }); diff --git a/src/vs/workbench/contrib/issue/browser/issue.contribution.ts b/src/vs/workbench/contrib/issue/browser/issue.contribution.ts index 601380c33e2..475437b79a9 100644 --- a/src/vs/workbench/contrib/issue/browser/issue.contribution.ts +++ b/src/vs/workbench/contrib/issue/browser/issue.contribution.ts @@ -40,7 +40,7 @@ Registry.as(ConfigurationExtensions.Configuration) properties: { 'issueReporter.experimental.webReporter': { type: 'boolean', - default: true, + default: false, description: 'Enable experimental issue reporter for web.', }, } diff --git a/src/vs/workbench/contrib/issue/browser/issueReporterService.ts b/src/vs/workbench/contrib/issue/browser/issueReporterService.ts index b89619f91bc..59eae428a91 100644 --- a/src/vs/workbench/contrib/issue/browser/issueReporterService.ts +++ b/src/vs/workbench/contrib/issue/browser/issueReporterService.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { $, reset, windowOpenNoOpener } from 'vs/base/browser/dom'; +import { $, isHTMLInputElement, isHTMLTextAreaElement, reset, windowOpenNoOpener } from 'vs/base/browser/dom'; import { Codicon } from 'vs/base/common/codicons'; import { groupBy } from 'vs/base/common/collections'; import { isMacintosh } from 'vs/base/common/platform'; @@ -124,7 +124,7 @@ export class IssueWebReporter extends BaseIssueReporterService { // Manually perform the selection if (isMacintosh) { if (cmdOrCtrlKey && e.key === 'a' && e.target) { - if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) { + if (isHTMLInputElement(e.target) || isHTMLTextAreaElement(e.target)) { (e.target).select(); } } diff --git a/src/vs/workbench/contrib/issue/browser/issueService.ts b/src/vs/workbench/contrib/issue/browser/issueService.ts index b67e59d7cbb..6030bbfd928 100644 --- a/src/vs/workbench/contrib/issue/browser/issueService.ts +++ b/src/vs/workbench/contrib/issue/browser/issueService.ts @@ -49,6 +49,7 @@ export class BrowserIssueService implements IWorkbenchIssueService { } async openReporter(options: Partial): Promise { + // If web reporter setting is false open the old GitHub issue reporter if (!this.configurationService.getValue('issueReporter.experimental.webReporter')) { const extensionId = options.extensionId; // If we don't have a extensionId, treat this as a Core issue diff --git a/src/vs/workbench/contrib/issue/browser/media/issueReporter.css b/src/vs/workbench/contrib/issue/browser/media/issueReporter.css index ba6e7b1ea9b..2f2bf7d3e6b 100644 --- a/src/vs/workbench/contrib/issue/browser/media/issueReporter.css +++ b/src/vs/workbench/contrib/issue/browser/media/issueReporter.css @@ -3,8 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - -.mac.web.issue-reporter-body { +.web.issue-reporter-body { position: absolute; overflow-y: scroll; } diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService.ts b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService.ts index 873d3b92a3a..961ba3291a1 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService.ts +++ b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { $, createStyleSheet, reset, windowOpenNoOpener } from 'vs/base/browser/dom'; +import { $, createStyleSheet, isHTMLInputElement, isHTMLTextAreaElement, reset, windowOpenNoOpener } from 'vs/base/browser/dom'; import { Button, unthemedButtonStyles } from 'vs/base/browser/ui/button/button'; import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels'; import { mainWindow } from 'vs/base/browser/window'; @@ -458,7 +458,7 @@ export class IssueReporter extends Disposable { // Manually perform the selection if (isMacintosh) { if (cmdOrCtrlKey && e.keyCode === 65 && e.target) { - if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) { + if (isHTMLInputElement(e.target) || isHTMLTextAreaElement(e.target)) { (e.target).select(); } } diff --git a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService2.ts b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService2.ts index 0c6477b7bfe..6f6bdd1c1f4 100644 --- a/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService2.ts +++ b/src/vs/workbench/contrib/issue/electron-sandbox/issueReporterService2.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { $, reset, windowOpenNoOpener } from 'vs/base/browser/dom'; +import { $, isHTMLInputElement, isHTMLTextAreaElement, reset, windowOpenNoOpener } from 'vs/base/browser/dom'; import { mainWindow } from 'vs/base/browser/window'; import { Codicon } from 'vs/base/common/codicons'; import { groupBy } from 'vs/base/common/collections'; @@ -146,7 +146,7 @@ export class IssueReporter2 extends BaseIssueReporterService { // Manually perform the selection if (isMacintosh) { if (cmdOrCtrlKey && e.key === 'a' && e.target) { - if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) { + if (isHTMLInputElement(e.target) || isHTMLTextAreaElement(e.target)) { (e.target).select(); } } diff --git a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts index fd3f51d3560..3feb89c6616 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts +++ b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts @@ -231,7 +231,7 @@ class LanguageStatus { const targetWindow = dom.getWindow(editor?.getContainerDomNode()); const node = targetWindow.document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus A>SPAN.codicon'); const container = targetWindow.document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus'); - if (node instanceof HTMLElement && container) { + if (dom.isHTMLElement(node) && container) { const _wiggle = 'wiggle'; const _flash = 'flash'; if (!isOneBusy) { @@ -251,7 +251,7 @@ class LanguageStatus { // use that as signal that the user has interacted/learned language status items work if (!userHasInteractedWithStatus) { const hoverTarget = targetWindow.document.querySelector('.monaco-workbench .context-view'); - if (hoverTarget instanceof HTMLElement) { + if (dom.isHTMLElement(hoverTarget)) { const observer = new MutationObserver(() => { if (targetWindow.document.contains(element)) { this._interactionCounter.increment(); diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts b/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts index 2c4a1d43436..8aa8b3f3319 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts @@ -28,7 +28,7 @@ import { Categories } from 'vs/platform/action/common/actionCommonCategories'; import { ILogService } from 'vs/platform/log/common/log'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { showWindowLogActionId } from 'vs/workbench/services/log/common/logConstants'; -import { getActiveElement, getWindow, isAncestor } from 'vs/base/browser/dom'; +import { getActiveElement, getWindow, isAncestor, isHTMLElement } from 'vs/base/browser/dom'; let _logging: boolean = false; function toggleLogging() { @@ -360,7 +360,7 @@ export class NotebookClipboardContribution extends Disposable { const loggerService = accessor.get(ILogService); const activeElement = getActiveElement(); - if (activeElement instanceof HTMLElement && ['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) >= 0) { + if (isHTMLElement(activeElement) && ['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) >= 0) { _log(loggerService, '[NotebookEditor] focus is on input or textarea element, bypass'); return false; } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findFilters.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findFilters.ts index a4bf2fd2d9f..0901d295edd 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findFilters.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/findFilters.ts @@ -5,17 +5,19 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; -export interface INotebookFindFiltersChangeEvent { +export interface INotebookFindChangeEvent { markupInput?: boolean; markupPreview?: boolean; codeInput?: boolean; codeOutput?: boolean; + searchInRanges?: boolean; } export class NotebookFindFilters extends Disposable { - private readonly _onDidChange: Emitter = this._register(new Emitter()); - readonly onDidChange: Event = this._onDidChange.event; + private readonly _onDidChange: Emitter = this._register(new Emitter()); + readonly onDidChange: Event = this._onDidChange.event; private _markupInput: boolean = true; @@ -68,17 +70,44 @@ export class NotebookFindFilters extends Disposable { } } + private _searchInRanges: boolean = false; + + get searchInRanges(): boolean { + return this._searchInRanges; + } + + set searchInRanges(value: boolean) { + if (this._searchInRanges !== value) { + this._searchInRanges = value; + this._onDidChange.fire({ searchInRanges: value }); + } + } + + private _selectedRanges: ICellRange[] = []; + + get selectedRanges(): ICellRange[] { + return this._selectedRanges; + } + + set selectedRanges(value: ICellRange[]) { + if (this._selectedRanges !== value) { + this._selectedRanges = value; + this._onDidChange.fire({ searchInRanges: this._searchInRanges }); + } + } + private readonly _initialMarkupInput: boolean; private readonly _initialMarkupPreview: boolean; private readonly _initialCodeInput: boolean; private readonly _initialCodeOutput: boolean; - constructor( markupInput: boolean, markupPreview: boolean, codeInput: boolean, - codeOutput: boolean + codeOutput: boolean, + searchInRanges: boolean, + selectedRanges: ICellRange[] ) { super(); @@ -86,6 +115,8 @@ export class NotebookFindFilters extends Disposable { this._markupPreview = markupPreview; this._codeInput = codeInput; this._codeOutput = codeOutput; + this._searchInRanges = searchInRanges; + this._selectedRanges = selectedRanges; this._initialMarkupInput = markupInput; this._initialMarkupPreview = markupPreview; @@ -94,6 +125,7 @@ export class NotebookFindFilters extends Disposable { } isModified(): boolean { + // do not include searchInRanges or selectedRanges in the check. This will incorrectly mark the filter icon as modified return ( this._markupInput !== this._initialMarkupInput || this._markupPreview !== this._initialMarkupPreview @@ -107,5 +139,7 @@ export class NotebookFindFilters extends Disposable { this._markupPreview = v.markupPreview; this._codeInput = v.codeInput; this._codeOutput = v.codeOutput; + this._searchInRanges = v.searchInRanges; + this._selectedRanges = v.selectedRanges; } } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts index 6c0cca31b75..de522b344a5 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts @@ -115,11 +115,7 @@ export class FindModel extends Disposable { } private _updateCellStates(e: FindReplaceStateChangedEvent) { - if (!this._state.filters?.markupInput) { - return; - } - - if (!this._state.filters?.markupPreview) { + if (!this._state.filters?.markupInput || !this._state.filters?.markupPreview || !this._state.filters?.searchInRanges || !this._state.filters?.selectedRanges) { return; } @@ -139,7 +135,9 @@ export class FindModel extends Disposable { includeMarkupInput: true, includeCodeInput: false, includeMarkupPreview: false, - includeOutput: false + includeOutput: false, + searchInRanges: this._state.filters?.searchInRanges, + selectedRanges: this._state.filters?.selectedRanges }; const contentMatches = viewModel.find(this._state.searchString, options); @@ -486,7 +484,9 @@ export class FindModel extends Disposable { includeMarkupInput: this._state.filters?.markupInput ?? true, includeCodeInput: this._state.filters?.codeInput ?? true, includeMarkupPreview: !!this._state.filters?.markupPreview, - includeOutput: !!this._state.filters?.codeOutput + includeOutput: !!this._state.filters?.codeOutput, + searchInRanges: this._state.filters?.searchInRanges, + selectedRanges: this._state.filters?.selectedRanges }; ret = await this._notebookEditor.find(val, options, token); diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts index f91d2ed8863..fd39a06a3f7 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts @@ -25,6 +25,7 @@ import { CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INTERACTIVE_WINDOW_IS_ACTIVE_EDITOR, KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { INotebookCommandContext, NotebookMultiCellAction } from 'vs/workbench/contrib/notebook/browser/controller/coreActions'; registerNotebookContribution(NotebookFindContrib.id, NotebookFindContrib); @@ -55,7 +56,7 @@ registerAction2(class extends Action2 { } }); -registerAction2(class extends Action2 { +registerAction2(class extends NotebookMultiCellAction { constructor() { super({ id: 'notebook.find', @@ -68,7 +69,7 @@ registerAction2(class extends Action2 { }); } - async run(accessor: ServicesAccessor): Promise { + async runWithContext(accessor: ServicesAccessor, context: INotebookCommandContext): Promise { const editorService = accessor.get(IEditorService); const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); @@ -77,7 +78,12 @@ registerAction2(class extends Action2 { } const controller = editor.getContribution(NotebookFindContrib.id); - controller.show(); + + if (context.selectedCells.length > 1) { + controller.show(undefined, { searchInRanges: true, selectedRanges: editor.getSelections() }); + } else { + controller.show(undefined, { searchInRanges: false, selectedRanges: [] }); + } } }); @@ -200,4 +206,3 @@ StartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, codeE return false; }); - diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts index d616161b309..7b261f5dc0e 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts @@ -13,7 +13,7 @@ import { Delayer } from 'vs/base/common/async'; import { KeyCode } from 'vs/base/common/keyCodes'; import 'vs/css!./notebookFindReplaceWidget'; import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/browser/findState'; -import { findNextMatchIcon, findPreviousMatchIcon, findReplaceAllIcon, findReplaceIcon, SimpleButton } from 'vs/editor/contrib/find/browser/findWidget'; +import { findNextMatchIcon, findPreviousMatchIcon, findReplaceAllIcon, findReplaceIcon, findSelectionIcon, SimpleButton } from 'vs/editor/contrib/find/browser/findWidget'; import * as nls from 'vs/nls'; import { ContextScopedReplaceInput, registerAndCreateHistoryNavigationContext } from 'vs/platform/history/browser/contextScopedHistoryWidget'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -35,19 +35,23 @@ import { filterIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIc import { NotebookFindFilters } from 'vs/workbench/contrib/notebook/browser/contrib/find/findFilters'; import { isSafari } from 'vs/base/common/platform'; import { ISashEvent, Orientation, Sash } from 'vs/base/browser/ui/sash/sash'; -import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { INotebookDeltaDecoration, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { defaultInputBoxStyles, defaultProgressBarStyles, defaultToggleStyles } from 'vs/platform/theme/browser/defaultStyles'; -import { IToggleStyles } from 'vs/base/browser/ui/toggle/toggle'; +import { IToggleStyles, Toggle } from 'vs/base/browser/ui/toggle/toggle'; import { Disposable } from 'vs/base/common/lifecycle'; import { NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { IHoverService } from 'vs/platform/hover/browser/hover'; +import { asCssVariable, inputActiveOptionBackground, inputActiveOptionBorder, inputActiveOptionForeground } from 'vs/platform/theme/common/colorRegistry'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; + const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find"); const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find"); const NLS_PREVIOUS_MATCH_BTN_LABEL = nls.localize('label.previousMatchButton', "Previous Match"); // const NLS_FILTER_BTN_LABEL = nls.localize('label.findFilterButton', "Search in View"); const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next Match"); +const NLS_FIND_IN_CELL_SELECTION_BTN_LABEL = nls.localize('label.findInCellSelectionButton', "Find in Cell Selection"); const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close"); const NLS_TOGGLE_REPLACE_MODE_BTN_LABEL = nls.localize('label.toggleReplaceButton', "Toggle Replace"); const NLS_REPLACE_INPUT_LABEL = nls.localize('label.replace', "Replace"); @@ -314,6 +318,10 @@ export abstract class SimpleFindReplaceWidget extends Widget { private _filters: NotebookFindFilters; + private readonly inSelectionToggle: Toggle; + private searchInSelectionEnabled: boolean; + private selectionDecorationIds: string[] = []; + constructor( @IContextViewService private readonly _contextViewService: IContextViewService, @IContextKeyService contextKeyService: IContextKeyService, @@ -326,14 +334,14 @@ export abstract class SimpleFindReplaceWidget extends Widget { ) { super(); - const findScope = this._configurationService.getValue<{ + const findFilters = this._configurationService.getValue<{ markupSource: boolean; markupPreview: boolean; codeSource: boolean; codeOutput: boolean; - }>(NotebookSetting.findScope) ?? { markupSource: true, markupPreview: true, codeSource: true, codeOutput: true }; + }>(NotebookSetting.findFilters) ?? { markupSource: true, markupPreview: true, codeSource: true, codeOutput: true }; - this._filters = new NotebookFindFilters(findScope.markupSource, findScope.markupPreview, findScope.codeSource, findScope.codeOutput); + this._filters = new NotebookFindFilters(findFilters.markupSource, findFilters.markupPreview, findFilters.codeSource, findFilters.codeOutput, false, []); this._state.change({ filters: this._filters }, false); this._filters.onDidChange(() => { @@ -430,7 +438,6 @@ export abstract class SimpleFindReplaceWidget extends Widget { this._findInput.setWholeWords(this._state.wholeWord); this._findInput.setCaseSensitive(this._state.matchCase); this._replaceInput.setPreserveCase(this._state.preserveCase); - this.findFirst(); })); this._matchesCount = document.createElement('div'); @@ -453,6 +460,27 @@ export abstract class SimpleFindReplaceWidget extends Widget { } }, hoverService)); + this.inSelectionToggle = this._register(new Toggle({ + icon: findSelectionIcon, + title: NLS_FIND_IN_CELL_SELECTION_BTN_LABEL, + isChecked: false, + inputActiveOptionBackground: asCssVariable(inputActiveOptionBackground), + inputActiveOptionBorder: asCssVariable(inputActiveOptionBorder), + inputActiveOptionForeground: asCssVariable(inputActiveOptionForeground), + })); + + this.inSelectionToggle.onChange(() => { + const checked = this.inSelectionToggle.checked; + this._filters.searchInRanges = checked; + if (checked) { + this._filters.selectedRanges = this._notebookEditor.getSelections(); + this.setCellSelectionDecorations(); + } else { + this._filters.selectedRanges = []; + this.clearCellSelectionDecorations(); + } + }); + const closeBtn = this._register(new SimpleButton({ label: NLS_CLOSE_BTN_LABEL, icon: widgetClose, @@ -465,8 +493,25 @@ export abstract class SimpleFindReplaceWidget extends Widget { this._innerFindDomNode.appendChild(this._matchesCount); this._innerFindDomNode.appendChild(this.prevBtn.domNode); this._innerFindDomNode.appendChild(this.nextBtn.domNode); + this._innerFindDomNode.appendChild(this.inSelectionToggle.domNode); this._innerFindDomNode.appendChild(closeBtn.domNode); + this.searchInSelectionEnabled = this._configurationService.getValue(NotebookSetting.findScope); + this.inSelectionToggle.domNode.style.display = this.searchInSelectionEnabled ? 'inline' : 'none'; + + this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(NotebookSetting.findScope)) { + this.searchInSelectionEnabled = this._configurationService.getValue(NotebookSetting.findScope); + if (this.searchInSelectionEnabled) { + this.inSelectionToggle.domNode.style.display = 'inline'; + } else { + this.inSelectionToggle.domNode.style.display = 'none'; + this.inSelectionToggle.checked = false; + this.clearCellSelectionDecorations(); + } + } + }); + // _domNode wraps _innerDomNode, ensuring that this._domNode.appendChild(this._innerFindDomNode); @@ -599,7 +644,6 @@ export abstract class SimpleFindReplaceWidget extends Widget { protected abstract onInputChanged(): boolean; protected abstract find(previous: boolean): void; - protected abstract findFirst(): void; protected abstract replaceOne(): void; protected abstract replaceAll(): void; protected abstract onFocusTrackerFocus(): void; @@ -647,6 +691,26 @@ export abstract class SimpleFindReplaceWidget extends Widget { this.updateButtons(this.foundMatch); } + private setCellSelectionDecorations() { + const cellHandles: number[] = []; + this._notebookEditor.getSelectionViewModels().forEach(viewModel => { + cellHandles.push(viewModel.handle); + }); + + const decorations: INotebookDeltaDecoration[] = []; + for (const handle of cellHandles) { + decorations.push({ + handle: handle, + options: { className: 'nb-multiCellHighlight', outputClassName: 'nb-multiCellHighlight' } + } satisfies INotebookDeltaDecoration); + } + this.selectionDecorationIds = this._notebookEditor.deltaCellDecorations([], decorations); + } + + private clearCellSelectionDecorations() { + this._notebookEditor.deltaCellDecorations(this.selectionDecorationIds, []); + } + protected _updateMatchesCount(): void { } @@ -686,11 +750,20 @@ export abstract class SimpleFindReplaceWidget extends Widget { this._findInput.focus(); } - public show(initialInput?: string, options?: { focus?: boolean }): void { + public show(initialInput?: string, options?: { focus?: boolean; searchInRanges?: boolean; selectedRanges?: ICellRange[] }): void { if (initialInput) { this._findInput.setValue(initialInput); } + if (this.searchInSelectionEnabled && options?.searchInRanges !== undefined) { + this._filters.searchInRanges = options.searchInRanges; + this.inSelectionToggle.checked = options.searchInRanges; + if (options.searchInRanges && options.selectedRanges) { + this._filters.selectedRanges = options.selectedRanges; + this.setCellSelectionDecorations(); + } + } + this._isVisible = true; setTimeout(() => { @@ -738,6 +811,9 @@ export abstract class SimpleFindReplaceWidget extends Widget { public hide(): void { if (this._isVisible) { + this.inSelectionToggle.checked = false; + this._notebookEditor.deltaCellDecorations(this.selectionDecorationIds, []); + this._domNode.classList.remove('visible-transition'); this._domNode.setAttribute('aria-hidden', 'true'); // Need to delay toggling visibility until after Transition, then visibility hidden - removes from tabIndex list diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts index 7c92a6b0576..c4307db60b9 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts @@ -26,6 +26,7 @@ import { FindModel } from 'vs/workbench/contrib/notebook/browser/contrib/find/fi import { SimpleFindReplaceWidget } from 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget'; import { CellEditState, ICellViewModel, INotebookEditor, INotebookEditorContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; +import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; const FIND_HIDE_TRANSITION = 'find-hide-transition'; const FIND_SHOW_TRANSITION = 'find-show-transition'; @@ -39,6 +40,8 @@ export interface IShowNotebookFindWidgetOptions { matchIndex?: number; focus?: boolean; searchStringSeededFrom?: { cell: ICellViewModel; range: Range }; + searchInRanges?: boolean; + selectedRanges?: ICellRange[]; } export class NotebookFindContrib extends Disposable implements INotebookEditorContribution { @@ -118,7 +121,7 @@ class NotebookFindWidget extends SimpleFindReplaceWidget implements INotebookEdi })); this._register(DOM.addDisposableListener(this.getDomNode(), DOM.EventType.FOCUS, e => { - this._previousFocusElement = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : undefined; + this._previousFocusElement = DOM.isHTMLElement(e.relatedTarget) ? e.relatedTarget : undefined; }, true)); } diff --git a/src/vs/workbench/contrib/notebook/browser/controller/chat/notebook.chat.contribution.ts b/src/vs/workbench/contrib/notebook/browser/controller/chat/notebook.chat.contribution.ts index 995340fb191..f35264aa8cc 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/chat/notebook.chat.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/chat/notebook.chat.contribution.ts @@ -3,4 +3,38 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Disposable } from 'vs/base/common/lifecycle'; +import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from 'vs/workbench/common/contributions'; +import { IChatVariablesService } from 'vs/workbench/contrib/chat/common/chatVariables'; import 'vs/workbench/contrib/notebook/browser/controller/chat/cellChatActions'; +import { NotebookChatController } from 'vs/workbench/contrib/notebook/browser/controller/chat/notebookChatController'; +import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService'; + +class NotebookChatVariables extends Disposable implements IWorkbenchContribution { + + static readonly ID = 'workbench.contrib.notebookChatVariables'; + + constructor( + @IChatVariablesService private readonly _chatVariableService: IChatVariablesService, + @INotebookEditorService private readonly _notebookEditorService: INotebookEditorService + ) { + super(); + + this._register(this._chatVariableService.registerVariable( + { id: '_notebookChatInput', name: '_notebookChatInput', description: '', hidden: true }, + async (_message, _arg, model) => { + const editors = this._notebookEditorService.listNotebookEditors(); + for (const editor of editors) { + const chatController = editor.getContribution(NotebookChatController.id) as NotebookChatController | undefined; + if (chatController?.hasSession(model)) { + return chatController.getSessionInputUri(); + } + } + + return undefined; + } + )); + } +} + +registerWorkbenchContribution2(NotebookChatVariables.ID, NotebookChatVariables, WorkbenchPhase.BlockRestore); diff --git a/src/vs/workbench/contrib/notebook/browser/controller/chat/notebookChatController.ts b/src/vs/workbench/contrib/notebook/browser/controller/chat/notebookChatController.ts index e5c83779451..4662ab11501 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/chat/notebookChatController.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/chat/notebookChatController.ts @@ -31,9 +31,8 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ChatAgentLocation } from 'vs/workbench/contrib/chat/common/chatAgents'; -import { ChatModel } from 'vs/workbench/contrib/chat/common/chatModel'; +import { ChatModel, IChatModel } from 'vs/workbench/contrib/chat/common/chatModel'; import { IChatService } from 'vs/workbench/contrib/chat/common/chatService'; -import { IChatVariablesService } from 'vs/workbench/contrib/chat/common/chatVariables'; import { countWords } from 'vs/workbench/contrib/chat/common/chatWordCounter'; import { ProgressingEditsOptions } from 'vs/workbench/contrib/inlineChat/browser/inlineChatStrategies'; import { InlineChatWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatWidget'; @@ -279,8 +278,7 @@ export class NotebookChatController extends Disposable implements INotebookEdito @ILanguageService private readonly _languageService: ILanguageService, @INotebookExecutionStateService private _executionStateService: INotebookExecutionStateService, @IStorageService private readonly _storageService: IStorageService, - @IChatService private readonly _chatService: IChatService, - @IChatVariablesService private readonly _chatVariableService: IChatVariablesService, + @IChatService private readonly _chatService: IChatService ) { super(); this._ctxHasActiveRequest = CTX_NOTEBOOK_CHAT_HAS_ACTIVE_REQUEST.bindTo(this._contextKeyService); @@ -301,13 +299,6 @@ export class NotebookChatController extends Disposable implements INotebookEdito this._historyCandidate = ''; this._storageService.store(NotebookChatController._storageKey, JSON.stringify(NotebookChatController._promptHistory), StorageScope.PROFILE, StorageTarget.USER); }; - - this._register(this._chatVariableService.registerVariable( - { id: '_notebookChatInput', name: '_notebookChatInput', description: '', hidden: true }, - async (_message, _arg, model) => { - return this._widget?.parentEditor.getModel()?.uri; - } - )); } private _registerFocusTracker() { @@ -541,6 +532,14 @@ export class NotebookChatController extends Disposable implements INotebookEdito this._widget.updateNotebookEditorFocusNSelections(); } + hasSession(chatModel: IChatModel) { + return this._model.value === chatModel; + } + + getSessionInputUri() { + return this._widget?.parentEditor.getModel()?.uri; + } + async acceptInput() { assertType(this._widget); await this._sessionCtor; diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index 93989cbc04f..d659b3cf277 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -446,6 +446,12 @@ background-color: var(--vscode-notebook-symbolHighlightBackground) !important; } +/** Cell Search Range selection highlight */ +.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.nb-multiCellHighlight .cell-focus-indicator, +.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row.nb-multiCellHighlight { + background-color: var(--vscode-notebook-symbolHighlightBackground) !important; +} + /** Cell focused editor border */ .notebookOverlay .monaco-list:focus-within .monaco-list-row.focused .cell-editor-focus .cell-editor-part:before { outline: solid 1px var(--vscode-notebook-focusedEditorBorder); diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 67c09c27463..0f9026c0dde 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -1026,8 +1026,8 @@ configurationRegistry.registerConfiguration({ type: 'boolean', default: true }, - [NotebookSetting.findScope]: { - markdownDescription: nls.localize('notebook.findScope', "Customize the Find Widget behavior for searching within notebook cells. When both markup source and markup preview are enabled, the Find Widget will search either the source code or preview based on the current state of the cell."), + [NotebookSetting.findFilters]: { + markdownDescription: nls.localize('notebook.findFilters', "Customize the Find Widget behavior for searching within notebook cells. When both markup source and markup preview are enabled, the Find Widget will search either the source code or preview based on the current state of the cell."), type: 'object', properties: { markupSource: { @@ -1055,6 +1055,11 @@ configurationRegistry.registerConfiguration({ }, tags: ['notebookLayout'] }, + [NotebookSetting.findScope]: { + markdownDescription: nls.localize('notebook.experimental.find.scope.enabled', "Enables the user to search within a selection of cells in the notebook. When enabled, the user will see a \"Find in Cell Selection\" icon in the notebook find widget."), + type: 'boolean', + default: false, + }, [NotebookSetting.remoteSaving]: { markdownDescription: nls.localize('notebook.remoteSaving', "Enables the incremental saving of notebooks between processes and across Remote connections. When enabled, only the changes to the notebook are sent to the extension host, improving performance for large notebooks and slow network connections."), type: 'boolean', diff --git a/src/vs/workbench/contrib/notebook/browser/notebookAccessibilityHelp.ts b/src/vs/workbench/contrib/notebook/browser/notebookAccessibilityHelp.ts index c06912b28f9..b146d0f71d2 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookAccessibilityHelp.ts @@ -28,6 +28,7 @@ export class NotebookAccessibilityHelp implements IAccessibleViewImplentation { } return; } + dispose() { } } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookAccessibleView.ts b/src/vs/workbench/contrib/notebook/browser/notebookAccessibleView.ts index 3975c17bb9e..daa9bae804d 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookAccessibleView.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookAccessibleView.ts @@ -20,6 +20,7 @@ export class NotebookAccessibleView implements IAccessibleViewImplentation { const editorService = accessor.get(IEditorService); return showAccessibleOutput(editorService); } + dispose() { } } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 05156eebb72..2f83ab690ff 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -80,7 +80,7 @@ import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/ import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { NotebookOptions, OutputInnerContainerTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookOptions'; -import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; +import { cellRangesToIndexes, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { INotebookRendererMessagingService } from 'vs/workbench/contrib/notebook/common/notebookRendererMessagingService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IWebviewElement } from 'vs/workbench/contrib/webview/browser/webview'; @@ -835,6 +835,18 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD } `); + styleSheets.push(` + .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.nb-multiCellHighlight:has(+ .monaco-list-row.nb-multiCellHighlight) .cell-focus-indicator-bottom { + height: ${bottomToolbarGap + cellBottomMargin}px; + background-color: var(--vscode-notebook-symbolHighlightBackground) !important; + } + + .notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row.nb-multiCellHighlight:has(+ .monaco-list-row.nb-multiCellHighlight) .cell-focus-indicator-bottom { + height: ${bottomToolbarGap + cellBottomMargin - 6}px; + background-color: var(--vscode-notebook-symbolHighlightBackground) !important; + } + `); + styleSheets.push(` .monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .input-collapse-container .cell-collapse-preview { @@ -2537,7 +2549,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD } } - return Promise.all(requests); } @@ -2576,7 +2587,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD return []; } - const webviewMatches = await this._webview.find(query, { caseSensitive: options.caseSensitive, wholeWord: options.wholeWord, includeMarkup: !!options.includeMarkupPreview, includeOutput: !!options.includeOutput, shouldGetSearchPreviewInfo, ownerID }); + const selectedRanges = options.selectedRanges?.map(range => this._notebookViewModel?.validateRange(range)).filter(range => !!range); + const selectedIndexes = cellRangesToIndexes(selectedRanges ?? []); + const findIds: string[] = selectedIndexes.map(index => this._notebookViewModel?.viewCells[index].id ?? ''); + + const webviewMatches = await this._webview.find(query, { caseSensitive: options.caseSensitive, wholeWord: options.wholeWord, includeMarkup: !!options.includeMarkupPreview, includeOutput: !!options.includeOutput, shouldGetSearchPreviewInfo, ownerID, findIds: options.searchInRanges ? findIds : [] }); if (token.isCancellationRequested) { return []; diff --git a/src/vs/workbench/contrib/notebook/browser/services/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/services/notebookServiceImpl.ts index d512f580f14..6a0fd291276 100644 --- a/src/vs/workbench/contrib/notebook/browser/services/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/services/notebookServiceImpl.ts @@ -13,7 +13,7 @@ import { Lazy } from 'vs/base/common/lazy'; import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ResourceMap } from 'vs/base/common/map'; import { Schemas } from 'vs/base/common/network'; -import { isEqual } from 'vs/base/common/resources'; +import { basename, isEqual } from 'vs/base/common/resources'; import { isDefined } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; @@ -34,12 +34,14 @@ import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebo import { NotebookOutputRendererInfo, NotebookStaticPreloadInfo as NotebookStaticPreloadInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer'; import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider'; import { INotebookSerializer, INotebookService, SimpleNotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookService'; -import { DiffEditorInputFactoryFunction, EditorInputFactoryFunction, EditorInputFactoryObject, IEditorResolverService, IEditorType, RegisteredEditorInfo, RegisteredEditorPriority, UntitledEditorInputFactoryFunction } from 'vs/workbench/services/editor/common/editorResolverService'; +import { DiffEditorInputFactoryFunction, EditorInputFactoryFunction, EditorInputFactoryObject, IEditorResolverService, IEditorType, RegisteredEditorInfo, RegisteredEditorPriority, UntitledEditorInputFactoryFunction, type MergeEditorInputFactoryFunction } from 'vs/workbench/services/editor/common/editorResolverService'; import { IExtensionService, isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import { IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { InstallRecommendedExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { INotebookDocument, INotebookDocumentService } from 'vs/workbench/services/notebook/common/notebookDocumentService'; +import { MergeEditorInput } from 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInput'; +import type { EditorInputWithOptions, IResourceMergeEditorInput } from 'vs/workbench/common/editor'; export class NotebookProviderInfoStore extends Disposable { @@ -214,11 +216,33 @@ export class NotebookProviderInfoStore extends Disposable { const notebookDiffEditorInputFactory: DiffEditorInputFactoryFunction = ({ modified, original, label, description }) => { return { editor: NotebookDiffEditorInput.create(this._instantiationService, modified.resource!, label, description, original.resource!, notebookProviderInfo.id) }; }; + const mergeEditorInputFactory: MergeEditorInputFactoryFunction = (mergeEditor: IResourceMergeEditorInput): EditorInputWithOptions => { + return { + editor: this._instantiationService.createInstance( + MergeEditorInput, + mergeEditor.base.resource, + { + uri: mergeEditor.input1.resource, + title: mergeEditor.input1.label ?? basename(mergeEditor.input1.resource), + description: mergeEditor.input1.description ?? '', + detail: mergeEditor.input1.detail + }, + { + uri: mergeEditor.input2.resource, + title: mergeEditor.input2.label ?? basename(mergeEditor.input2.resource), + description: mergeEditor.input2.description ?? '', + detail: mergeEditor.input2.detail + }, + mergeEditor.result.resource + ) + }; + }; const notebookFactoryObject: EditorInputFactoryObject = { createEditorInput: notebookEditorInputFactory, createDiffEditorInput: notebookDiffEditorInputFactory, createUntitledEditorInput: notebookUntitledEditorFactory, + createMergeEditorInput: mergeEditorInputFactory }; const notebookCellFactoryObject: EditorInputFactoryObject = { createEditorInput: notebookEditorInputFactory, diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellFocusIndicator.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellFocusIndicator.ts index 7549fdeaab8..189ef50f166 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellFocusIndicator.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellFocusIndicator.ts @@ -77,7 +77,7 @@ export class CellFocusIndicator extends CellContentPart { override updateInternalLayoutNow(element: ICellViewModel): void { if (element.cellKind === CellKind.Markup) { const indicatorPostion = this.notebookEditor.notebookOptions.computeIndicatorPosition(element.layoutInfo.totalHeight, (element as MarkupCellViewModel).layoutInfo.foldHintHeight, this.notebookEditor.textModel?.viewType); - this.bottom.domNode.style.transform = `translateY(${indicatorPostion.bottomIndicatorTop}px)`; + this.bottom.domNode.style.transform = `translateY(${indicatorPostion.bottomIndicatorTop + 6}px)`; this.left.setHeight(indicatorPostion.verticalIndicatorHeight); this.right.setHeight(indicatorPostion.verticalIndicatorHeight); this.codeFocusIndicator.setHeight(indicatorPostion.verticalIndicatorHeight - this.getIndicatorTopMargin() * 2 - element.layoutInfo.chatHeight); diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markupCell.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markupCell.ts index d334bb1db3f..b1a3e8b3e93 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markupCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markupCell.ts @@ -228,12 +228,14 @@ export class MarkupCell extends Disposable { e.added.forEach(options => { if (options.className) { this.notebookEditor.deltaCellContainerClassNames(this.viewCell.id, [options.className], []); + this.templateData.rootContainer.classList.add(options.className); } }); e.removed.forEach(options => { if (options.className) { this.notebookEditor.deltaCellContainerClassNames(this.viewCell.id, [], [options.className]); + this.templateData.rootContainer.classList.remove(options.className); } }); })); @@ -241,6 +243,7 @@ export class MarkupCell extends Disposable { this.viewCell.getCellDecorations().forEach(options => { if (options.className) { this.notebookEditor.deltaCellContainerClassNames(this.viewCell.id, [options.className], []); + this.templateData.rootContainer.classList.add(options.className); } }); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 702182063b3..9cc82bc223a 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -401,6 +401,14 @@ export class BackLayerWebView extends Themable { background-color: var(--theme-notebook-symbol-highlight-background); } + #container .markup > div.nb-multiCellHighlight { + background-color: var(--theme-notebook-symbol-highlight-background); + } + + #container .nb-multiCellHighlight .output_container .output { + background-color: var(--theme-notebook-symbol-highlight-background); + } + #container .nb-chatGenerationHighlight .output_container .output { background-color: var(--vscode-notebook-selectedCellBackground); } @@ -1772,7 +1780,7 @@ export class BackLayerWebView extends Themable { }); } - async find(query: string, options: { wholeWord?: boolean; caseSensitive?: boolean; includeMarkup: boolean; includeOutput: boolean; shouldGetSearchPreviewInfo: boolean; ownerID: string }): Promise { + async find(query: string, options: { wholeWord?: boolean; caseSensitive?: boolean; includeMarkup: boolean; includeOutput: boolean; shouldGetSearchPreviewInfo: boolean; ownerID: string; findIds: string[] }): Promise { if (query === '') { this._sendMessageToWebview({ type: 'findStop', diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts index 5d0e13ad3b2..a59abdada13 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts @@ -399,7 +399,7 @@ export interface ITokenizedStylesChangedMessage { export interface IFindMessage { readonly type: 'find'; readonly query: string; - readonly options: { wholeWord?: boolean; caseSensitive?: boolean; includeMarkup: boolean; includeOutput: boolean; shouldGetSearchPreviewInfo: boolean; ownerID: string }; + readonly options: { wholeWord?: boolean; caseSensitive?: boolean; includeMarkup: boolean; includeOutput: boolean; shouldGetSearchPreviewInfo: boolean; ownerID: string; findIds: string[] }; } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index 6e4aed1f573..fb7dffded14 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -90,7 +90,7 @@ declare function __import(path: string): Promise; async function webviewPreloads(ctx: PreloadContext) { - /* eslint-disable no-restricted-globals */ + /* eslint-disable no-restricted-globals, no-restricted-syntax */ // The use of global `window` should be fine in this context, even // with aux windows. This code is running from within an `iframe` @@ -1425,9 +1425,9 @@ async function webviewPreloads(ctx: PreloadContext) { return offset + getSelectionOffsetRelativeTo(parentElement, currentNode.parentNode); } - const find = (query: string, options: { wholeWord?: boolean; caseSensitive?: boolean; includeMarkup: boolean; includeOutput: boolean; shouldGetSearchPreviewInfo: boolean; ownerID: string }) => { + const find = (query: string, options: { wholeWord?: boolean; caseSensitive?: boolean; includeMarkup: boolean; includeOutput: boolean; shouldGetSearchPreviewInfo: boolean; ownerID: string; findIds: string[] }) => { let find = true; - const matches: IFindMatch[] = []; + let matches: IFindMatch[] = []; const range = document.createRange(); range.selectNodeContents(window.document.getElementById('findStart')!); @@ -1553,6 +1553,8 @@ async function webviewPreloads(ctx: PreloadContext) { console.log(e); } + + matches = matches.filter(match => options.findIds.length ? options.findIds.includes(match.cellId) : true); _highlighter.addHighlights(matches, options.ownerID); window.document.getSelection()?.removeAllRanges(); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModelImpl.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModelImpl.ts index b7fa0bc7ecf..8a0f8379011 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModelImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModelImpl.ts @@ -910,7 +910,18 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD //#region Find find(value: string, options: INotebookSearchOptions): CellFindMatchWithIndex[] { const matches: CellFindMatchWithIndex[] = []; - this._viewCells.forEach((cell, index) => { + let findCells: CellViewModel[] = []; + + const selectedRanges = options.selectedRanges?.map(range => this.validateRange(range)).filter(range => !!range); + + if (options.searchInRanges && selectedRanges) { + const selectedIndexes = cellRangesToIndexes(selectedRanges); + findCells = selectedIndexes.map(index => this._viewCells[index]); + } else { + findCells = this._viewCells; + } + + findCells.forEach((cell, index) => { const cellMatches = cell.startFind(value, options); if (cellMatches) { matches.push(new CellFindMatchModel( diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 7828091e598..33c85b27420 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -827,6 +827,8 @@ export interface INotebookSearchOptions { includeMarkupPreview?: boolean; includeCodeInput?: boolean; includeOutput?: boolean; + searchInRanges?: boolean; + selectedRanges?: ICellRange[]; } export interface INotebookExclusiveDocumentFilter { @@ -951,7 +953,8 @@ export const NotebookSetting = { outputFontSize: 'notebook.output.fontSize', outputFontFamilyDeprecated: 'notebook.outputFontFamily', outputFontFamily: 'notebook.output.fontFamily', - findScope: 'notebook.find.scope', + findFilters: 'notebook.find.filters', + findScope: 'notebook.experimental.find.scope.enabled', logging: 'notebook.logging', confirmDeleteRunningCell: 'notebook.confirmDeleteRunningCell', remoteSaving: 'notebook.experimental.remoteSave', diff --git a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts index 10577676318..81653b58f6d 100644 --- a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts +++ b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts @@ -17,7 +17,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { writeTransientState } from 'vs/workbench/contrib/codeEditor/browser/toggleWordWrap'; -import { LoaderStats, isESM } from 'vs/base/common/amd'; +import { LoaderEventType, LoaderStats, isESM } from 'vs/base/common/amd'; import { IProductService } from 'vs/platform/product/common/productService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts index dcf8e572093..2c8e669e7a0 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts @@ -1055,7 +1055,7 @@ class SourceColumnRenderer implements ITableRenderer this.editSetting(idx) }, @@ -910,7 +910,7 @@ export class ObjectSettingDropdownWidget extends AbstractListSettingWidget this._onDidChangeList.fire({ originalItem: item, item: undefined, targetIndex: idx }) }); @@ -919,7 +919,7 @@ export class ObjectSettingDropdownWidget extends AbstractListSettingWidget this._onDidChangeList.fire({ originalItem: item, item: undefined, targetIndex: idx }) }); diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 0ba86ba97b8..4e826cecb77 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -750,7 +750,7 @@ export class TunnelPanel extends ViewPane { static readonly TITLE: ILocalizedString = nls.localize2('remote.tunnel', "Ports"); private panelContainer: HTMLElement | undefined; - private table!: WorkbenchTable; + private table: WorkbenchTable | undefined; private readonly tableDisposables: DisposableStore = this._register(new DisposableStore()); private tunnelTypeContext: IContextKey; private tunnelCloseableContext: IContextKey; @@ -830,7 +830,7 @@ export class TunnelPanel extends ViewPane { updateActions(); this.registerPrivacyActions(); this.createTable(); - this.table.layout(this.height, this.width); + this.table?.layout(this.height, this.width); } })); } @@ -913,7 +913,7 @@ export class TunnelPanel extends ViewPane { this.tableDisposables.add(this.table.onDidFocus(() => this.tunnelViewFocusContext.set(true))); this.tableDisposables.add(this.table.onDidBlur(() => this.tunnelViewFocusContext.set(false))); - const rerender = () => this.table.splice(0, Number.POSITIVE_INFINITY, this.viewModel.all); + const rerender = () => this.table?.splice(0, Number.POSITIVE_INFINITY, this.viewModel.all); rerender(); let lastPortCount = this.portCount; @@ -927,7 +927,7 @@ export class TunnelPanel extends ViewPane { })); this.tableDisposables.add(this.table.onMouseClick(e => { - if (this.hasOpenLinkModifier(e.browserEvent)) { + if (this.hasOpenLinkModifier(e.browserEvent) && this.table) { const selection = this.table.getSelectedElements(); if ((selection.length === 0) || ((selection.length === 1) && (selection[0] === e.element))) { @@ -959,11 +959,11 @@ export class TunnelPanel extends ViewPane { widgetContainer.classList.add('highlight'); if (!e) { // When we are in editing mode for a new forward, rather than updating an existing one we need to reveal the input box since it might be out of view. - this.table.reveal(this.table.indexOf(this.viewModel.input)); + this.table?.reveal(this.table.indexOf(this.viewModel.input)); } } else { if (e && (e.tunnel.tunnelType !== TunnelType.Add)) { - this.table.setFocus(this.lastFocus); + this.table?.setFocus(this.lastFocus); } this.focus(); } @@ -983,7 +983,7 @@ export class TunnelPanel extends ViewPane { override focus(): void { super.focus(); - this.table.domFocus(); + this.table?.domFocus(); } private onFocusChanged(event: ITableEvent) { @@ -1045,7 +1045,7 @@ export class TunnelPanel extends ViewPane { const node: TunnelItem | undefined = event.element; if (node) { - this.table.setFocus([this.table.indexOf(node)]); + this.table?.setFocus([this.table.indexOf(node)]); this.tunnelTypeContext.set(node.tunnelType); this.tunnelCloseableContext.set(!!node.closeable); this.tunnelPrivacyContext.set(node.privacy.id); @@ -1062,7 +1062,7 @@ export class TunnelPanel extends ViewPane { this.contextMenuService.showContextMenu({ menuId: MenuId.TunnelContext, menuActionOptions: { shouldForwardArgs: true }, - contextKeyService: this.table.contextKeyService, + contextKeyService: this.table?.contextKeyService, getAnchor: () => event.anchor, getActionViewItem: (action) => { const keybinding = this.keybindingService.lookupKeybinding(action.id); @@ -1073,7 +1073,7 @@ export class TunnelPanel extends ViewPane { }, onHide: (wasCancelled?: boolean) => { if (wasCancelled) { - this.table.domFocus(); + this.table?.domFocus(); } }, getActionsContext: () => node?.strip(), @@ -1093,7 +1093,7 @@ export class TunnelPanel extends ViewPane { this.height = height; this.width = width; super.layoutBody(height, width); - this.table.layout(height, width); + this.table?.layout(height, width); } } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 7f7da99a2a8..97455f3bc25 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -3149,6 +3149,8 @@ export class SCMViewPane extends ViewPane { if (resource) { await this.tree.expandTo(resource); + this.tree.reveal(resource); + this.tree.setSelection([resource]); this.tree.setFocus([resource]); return; diff --git a/src/vs/workbench/contrib/scm/browser/workingSet.ts b/src/vs/workbench/contrib/scm/browser/workingSet.ts index 498b667390e..3a023470ea2 100644 --- a/src/vs/workbench/contrib/scm/browser/workingSet.ts +++ b/src/vs/workbench/contrib/scm/browser/workingSet.ts @@ -11,6 +11,7 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { getProviderKey } from 'vs/workbench/contrib/scm/browser/util'; import { ISCMRepository, ISCMService } from 'vs/workbench/contrib/scm/common/scm'; import { IEditorGroupsService, IEditorWorkingSet } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; type ISCMSerializedWorkingSet = { readonly providerKey: string; @@ -35,7 +36,8 @@ export class SCMWorkingSetController implements IWorkbenchContribution { @IConfigurationService private readonly configurationService: IConfigurationService, @IEditorGroupsService private readonly editorGroupsService: IEditorGroupsService, @ISCMService private readonly scmService: ISCMService, - @IStorageService private readonly storageService: IStorageService + @IStorageService private readonly storageService: IStorageService, + @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService ) { const onDidChangeConfiguration = Event.filter(configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.workingSets.enabled'), this._disposables); this._disposables.add(Event.runAndSubscribe(onDidChangeConfiguration, () => this._onDidChangeConfiguration())); @@ -147,7 +149,13 @@ export class SCMWorkingSetController implements IWorkbenchContribution { } if (editorWorkingSetId) { - await this.editorGroupsService.applyWorkingSet(editorWorkingSetId); + // Applying a working set can be the result of a user action that has been + // initiated from the terminal (ex: switching branches). As such, we want + // to preserve the focus in the terminal. This does not cover the scenario + // in which the terminal is in the editor part. + const preserveFocus = this.layoutService.hasFocus(Parts.PANEL_PART); + + await this.editorGroupsService.applyWorkingSet(editorWorkingSetId, { preserveFocus }); } } diff --git a/src/vs/workbench/contrib/search/browser/searchWidget.ts b/src/vs/workbench/contrib/search/browser/searchWidget.ts index 766990702f8..cf86112b1c2 100644 --- a/src/vs/workbench/contrib/search/browser/searchWidget.ts +++ b/src/vs/workbench/contrib/search/browser/searchWidget.ts @@ -204,7 +204,9 @@ export class SearchWidget extends Widget { notebookOptions.isInNotebookMarkdownInput, notebookOptions.isInNotebookMarkdownPreview, notebookOptions.isInNotebookCellInput, - notebookOptions.isInNotebookCellOutput + notebookOptions.isInNotebookCellOutput, + false, + [] )); this._register( @@ -226,13 +228,13 @@ export class SearchWidget extends Widget { this.render(container, options); - this.configurationService.onDidChangeConfiguration(e => { + this._register(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('editor.accessibilitySupport')) { this.updateAccessibilitySupport(); } - }); + })); - this.accessibilityService.onDidChangeScreenReaderOptimized(() => this.updateAccessibilitySupport()); + this._register(this.accessibilityService.onDidChangeScreenReaderOptimized(() => this.updateAccessibilitySupport())); this.updateAccessibilitySupport(); } @@ -419,7 +421,7 @@ export class SearchWidget extends Widget { ) ); - this.searchInput.onKeyDown((keyboardEvent: IKeyboardEvent) => this.onSearchInputKeyDown(keyboardEvent)); + this._register(this.searchInput.onKeyDown((keyboardEvent: IKeyboardEvent) => this.onSearchInputKeyDown(keyboardEvent))); this.searchInput.setValue(options.value || ''); this.searchInput.setRegex(!!options.isRegex); this.searchInput.setCaseSensitive(!!options.isCaseSensitive); diff --git a/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts b/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts index 37cd9c5f169..136c9b7a84c 100644 --- a/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts +++ b/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts @@ -33,6 +33,7 @@ import { isBoolean, isNumber, isString } from 'vs/base/common/types'; import { LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService'; import { AutoUpdateConfigurationKey } from 'vs/workbench/contrib/extensions/common/extensions'; import { KEYWORD_ACTIVIATION_SETTING_ID } from 'vs/workbench/contrib/chat/common/chatService'; +import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; type TelemetryData = { mimeType: TelemetryTrustedValue; @@ -245,6 +246,7 @@ class ConfigurationTelemetryContribution extends Disposable implements IWorkbenc constructor( @IConfigurationService private readonly configurationService: IConfigurationService, + @IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService, @ITelemetryService private readonly telemetryService: ITelemetryService, ) { super(); @@ -424,6 +426,23 @@ class ConfigurationTelemetryContribution extends Disposable implements IWorkbenc source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'source of the setting' }; }>('window.systemColorTheme', { settingValue: this.getValueToReport(key, target), source }); return; + + case 'window.newWindowProfile': + { + const valueToReport = this.getValueToReport(key, target); + const settingValue = + valueToReport === null ? 'null' + : valueToReport === this.userDataProfilesService.defaultProfile.name + ? 'default' + : 'custom'; + this.telemetryService.publicLog2('window.systemColorTheme', { settingValue, source }); + return; + } } } diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 index f010f5945cb..c2971c0de2a 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1 @@ -203,7 +203,7 @@ function Send-Completions { # `[` is included here as namespace commands are not included in CompleteCommand(''), # additionally for some reason CompleteVariable('[') causes the prompt to clear and reprint # multiple times - if ($completionPrefix.Contains(' ') -or $completionPrefix.Contains('[')) { + if ($completionPrefix.Contains(' ') -or $completionPrefix.Contains('[') -or $PSVersionTable.PSVersion -lt "6.0") { $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex if ($null -ne $completions.CompletionMatches) { $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);" diff --git a/src/vs/workbench/contrib/terminalContrib/chat/browser/media/terminalInitialHint.css b/src/vs/workbench/contrib/terminalContrib/chat/browser/media/terminalInitialHint.css index ba2c96cf4a9..6055da8a2a9 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/browser/media/terminalInitialHint.css +++ b/src/vs/workbench/contrib/terminalContrib/chat/browser/media/terminalInitialHint.css @@ -3,9 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.monaco-workbench .pane-body.integrated-terminal .contentWidgets .terminal-initial-hint { +.monaco-workbench .pane-body.integrated-terminal .terminal-initial-hint { color: var(--vscode-input-placeholderForeground); } .monaco-workbench .pane-body.integrated-terminal .terminal-initial-hint a { - color: var(--vscode-textLink-foreground) + cursor: pointer; + color: var(--vscode-textLink-foreground); +} + +.monaco-workbench .pane-body.integrated-terminal .terminal-initial-hint a, +.monaco-workbench .pane-body.integrated-terminal .terminal-initial-hint .detail { + font-style: italic; } diff --git a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.initialHint.contribution.ts b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.initialHint.contribution.ts index dbead33ec9a..a8f77d089e0 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.initialHint.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminal.initialHint.contribution.ts @@ -108,7 +108,7 @@ export class TerminalInitialHintContribution extends Disposable implements ITerm private _createHint(): void { const instance = this._instance instanceof TerminalInstance ? this._instance : undefined; const commandDetectionCapability = instance?.capabilities.get(TerminalCapability.CommandDetection); - if (!instance || !this._xterm || this._hintWidget || !commandDetectionCapability || commandDetectionCapability?.hasInput || instance.reconnectionProperties) { + if (!instance || !this._xterm || this._hintWidget || !commandDetectionCapability || commandDetectionCapability.promptInputModel.value || instance.reconnectionProperties) { return; } @@ -247,7 +247,7 @@ class TerminalInitialHintWidget extends Disposable { } }; - const hintElement = $('terminal-initial-hint'); + const hintElement = $('div.terminal-initial-hint'); hintElement.style.display = 'block'; const keybindingHint = this.keybindingService.lookupKeybinding(TerminalChatCommandId.Start); @@ -275,8 +275,7 @@ class TerminalInitialHintWidget extends Disposable { hintElement.appendChild(after); const typeToDismiss = localize('hintTextDismiss', 'Start typing to dismiss.'); - const textHint2 = $('span', undefined, typeToDismiss); - textHint2.style.fontStyle = 'italic'; + const textHint2 = $('span.detail', undefined, typeToDismiss); hintElement.appendChild(textHint2); ariaLabel = actionPart.concat(typeToDismiss); diff --git a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatAccessibilityHelp.ts b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatAccessibilityHelp.ts index f0bdac465ba..35fcdd0410c 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatAccessibilityHelp.ts @@ -35,6 +35,7 @@ export class TerminalChatAccessibilityHelp implements IAccessibleViewImplentatio options: { type: AccessibleViewType.Help } }; } + dispose() { } } export function getAccessibilityHelpText(accessor: ServicesAccessor): string { diff --git a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatAccessibleView.ts b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatAccessibleView.ts index 215f1fe6f05..2898dfde41c 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatAccessibleView.ts +++ b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatAccessibleView.ts @@ -33,4 +33,5 @@ export class TerminalInlineChatAccessibleView implements IAccessibleViewImplenta options: { type: AccessibleViewType.View } }; } + dispose() { } } diff --git a/src/vs/workbench/contrib/terminalContrib/chat/common/terminalInitialHintConfiguration.ts b/src/vs/workbench/contrib/terminalContrib/chat/common/terminalInitialHintConfiguration.ts index 41567ee5921..711ebbb18fe 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/common/terminalInitialHintConfiguration.ts +++ b/src/vs/workbench/contrib/terminalContrib/chat/common/terminalInitialHintConfiguration.ts @@ -6,6 +6,7 @@ import { IStringDictionary } from 'vs/base/common/collections'; import { localize } from 'vs/nls'; import { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; +import product from 'vs/platform/product/common/product'; export const enum TerminalInitialHintSettingId { Enabled = 'terminal.integrated.initialHint' @@ -16,6 +17,6 @@ export const terminalInitialHintConfiguration: IStringDictionary; private readonly isCurrentProfileTransientContext: IContextKey; private readonly hasProfilesContext: IContextKey; + private readonly startTime: number = Date.now(); constructor( @IUserDataProfileService private readonly userDataProfileService: IUserDataProfileService, @@ -206,6 +207,19 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements } async run(accessor: ServicesAccessor) { if (that.userDataProfileService.currentProfile.id !== profile.id) { + if (profile.isDefault && Date.now() - that.startTime < (1000 * 20 /* 20 seconds */)) { + type SwitchToDefaultProfileInfoClassification = { + owner: 'sandy081'; + comment: 'Report if the user switches to the default profile.'; + emptyWindow: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'If the current window is empty window or not' }; + }; + type SwitchToDefaultProfileInfoEvent = { + emptyWindow: boolean; + }; + that.telemetryService.publicLog2('profiles:newwindowprofile', { + emptyWindow: that.workspaceContextService.getWorkbenchState() === WorkbenchState.EMPTY + }); + } return that.userDataProfileManagementService.switchProfile(profile); } } diff --git a/src/vs/workbench/contrib/webview/browser/webviewService.ts b/src/vs/workbench/contrib/webview/browser/webviewService.ts index 9e1d51b89cc..7b75404adf4 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter } from 'vs/base/common/event'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/browser/themeing'; import { IOverlayWebview, IWebview, IWebviewElement, IWebviewService, WebviewInitInfo } from 'vs/workbench/contrib/webview/browser/webview'; @@ -58,9 +58,11 @@ export class WebviewService extends Disposable implements IWebviewService { protected registerNewWebview(webview: IWebview) { this._webviews.add(webview); - webview.onDidFocus(() => { + const store = new DisposableStore(); + + store.add(webview.onDidFocus(() => { this._updateActiveWebview(webview); - }); + })); const onBlur = () => { if (this._activeWebview === webview) { @@ -68,10 +70,11 @@ export class WebviewService extends Disposable implements IWebviewService { } }; - webview.onDidBlur(onBlur); - webview.onDidDispose(() => { + store.add(webview.onDidBlur(onBlur)); + store.add(webview.onDidDispose(() => { onBlur(); + store.dispose(); this._webviews.delete(webview); - }); + })); } } diff --git a/src/vs/workbench/contrib/welcomeWalkthrough/browser/walkThroughPart.ts b/src/vs/workbench/contrib/welcomeWalkthrough/browser/walkThroughPart.ts index dd11b080f6b..c2c1e099961 100644 --- a/src/vs/workbench/contrib/welcomeWalkthrough/browser/walkThroughPart.ts +++ b/src/vs/workbench/contrib/welcomeWalkthrough/browser/walkThroughPart.ts @@ -32,7 +32,7 @@ import { UILabelProvider } from 'vs/base/common/keybindingLabels'; import { OS, OperatingSystem } from 'vs/base/common/platform'; import { deepClone } from 'vs/base/common/objects'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { addDisposableListener, Dimension, safeInnerHtml, size } from 'vs/base/browser/dom'; +import { addDisposableListener, Dimension, isHTMLAnchorElement, isHTMLButtonElement, isHTMLElement, safeInnerHtml, size } from 'vs/base/browser/dom'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -142,12 +142,12 @@ export class WalkThroughPart extends EditorPane { })); this.disposables.add(this.addEventListener(this.content, 'focusin', (e: FocusEvent) => { // Work around scrolling as side-effect of setting focus on the offscreen zone widget (#18929) - if (e.target instanceof HTMLElement && e.target.classList.contains('zone-widget-container')) { + if (isHTMLElement(e.target) && e.target.classList.contains('zone-widget-container')) { const scrollPosition = this.scrollbar.getScrollPosition(); this.content.scrollTop = scrollPosition.scrollTop; this.content.scrollLeft = scrollPosition.scrollLeft; } - if (e.target instanceof HTMLElement) { + if (isHTMLElement(e.target)) { this.lastFocus = e.target; } })); @@ -156,7 +156,7 @@ export class WalkThroughPart extends EditorPane { private registerClickHandler() { this.content.addEventListener('click', event => { for (let node = event.target as HTMLElement; node; node = node.parentNode as HTMLElement) { - if (node instanceof HTMLAnchorElement && node.href) { + if (isHTMLAnchorElement(node) && node.href) { const baseElement = node.ownerDocument.getElementsByTagName('base')[0] || this.window.location; if (baseElement && node.href.indexOf(baseElement.href) >= 0 && node.hash) { const scrollTarget = this.content.querySelector(node.hash); @@ -171,7 +171,7 @@ export class WalkThroughPart extends EditorPane { } event.preventDefault(); break; - } else if (node instanceof HTMLButtonElement) { + } else if (isHTMLButtonElement(node)) { const href = node.getAttribute('data-href'); if (href) { this.open(URI.parse(href)); diff --git a/src/vs/workbench/electron-sandbox/desktop.contribution.ts b/src/vs/workbench/electron-sandbox/desktop.contribution.ts index 2115ddfecc0..e1519b9e31d 100644 --- a/src/vs/workbench/electron-sandbox/desktop.contribution.ts +++ b/src/vs/workbench/electron-sandbox/desktop.contribution.ts @@ -172,15 +172,15 @@ import { MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL } from 'vs/platform/window/electron-sand 'type': 'string', 'enum': ['preserve', 'all', 'folders', 'one', 'none'], 'enumDescriptions': [ - localize('window.reopenFolders.preserve', "Always reopen all windows. If a folder or workspace is opened (e.g. from the command line) it opens as a new window unless it was opened before. If files are opened they will open in one of the restored windows."), - localize('window.reopenFolders.all', "Reopen all windows unless a folder, workspace or file is opened (e.g. from the command line)."), - localize('window.reopenFolders.folders', "Reopen all windows that had folders or workspaces opened unless a folder, workspace or file is opened (e.g. from the command line)."), - localize('window.reopenFolders.one', "Reopen the last active window unless a folder, workspace or file is opened (e.g. from the command line)."), + localize('window.reopenFolders.preserve', "Always reopen all windows. If a folder or workspace is opened (e.g. from the command line) it opens as a new window unless it was opened before. If files are opened they will open in one of the restored windows together with editors that were previously opened."), + localize('window.reopenFolders.all', "Reopen all windows unless a folder, workspace or file is opened (e.g. from the command line). If a file is opened, it will replace any of the editors that were previously opened in a window."), + localize('window.reopenFolders.folders', "Reopen all windows that had folders or workspaces opened unless a folder, workspace or file is opened (e.g. from the command line). If a file is opened, it will replace any of the editors that were previously opened in a window."), + localize('window.reopenFolders.one', "Reopen the last active window unless a folder, workspace or file is opened (e.g. from the command line). If a file is opened, it will replace any of the editors that were previously opened in a window."), localize('window.reopenFolders.none', "Never reopen a window. Unless a folder or workspace is opened (e.g. from the command line), an empty window will appear.") ], 'default': 'all', 'scope': ConfigurationScope.APPLICATION, - 'description': localize('restoreWindows', "Controls how windows are being reopened after starting for the first time. This setting has no effect when the application is already running.") + 'description': localize('restoreWindows', "Controls how windows and editors within are being restored when opening.") }, 'window.restoreFullscreen': { 'type': 'boolean', diff --git a/src/vs/workbench/services/authentication/browser/authenticationService.ts b/src/vs/workbench/services/authentication/browser/authenticationService.ts index 2509a589d38..84cc7730f4b 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from 'vs/base/common/event'; -import { Disposable, DisposableMap, DisposableStore, IDisposable, isDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableMap, DisposableStore, IDisposable, isDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; import { isString } from 'vs/base/common/types'; import { localize } from 'vs/nls'; @@ -200,10 +200,12 @@ export class AuthenticationService extends Disposable implements IAuthentication return provider; } + const store = new DisposableStore(); + // When activate has completed, the extension has made the call to `registerAuthenticationProvider`. // However, activate cannot block on this, so the renderer may not have gotten the event yet. const didRegister: Promise = new Promise((resolve, _) => { - this.onDidRegisterAuthenticationProvider(e => { + store.add(Event.once(this.onDidRegisterAuthenticationProvider)(e => { if (e.id === providerId) { provider = this._authenticationProviders.get(providerId); if (provider) { @@ -212,16 +214,18 @@ export class AuthenticationService extends Disposable implements IAuthentication throw new Error(`No authentication provider '${providerId}' is currently registered.`); } } - }); + })); }); const didTimeout: Promise = new Promise((_, reject) => { - setTimeout(() => { + const handle = setTimeout(() => { reject('Timed out waiting for authentication provider to register'); }, 5000); + + store.add(toDisposable(() => clearTimeout(handle))); }); - return Promise.race([didRegister, didTimeout]); + return Promise.race([didRegister, didTimeout]).finally(() => store.dispose()); } } diff --git a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts index e47c8923019..5178f4c9457 100644 --- a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts +++ b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts @@ -6,14 +6,14 @@ import { localize } from 'vs/nls'; import { mark } from 'vs/base/common/performance'; import { Emitter, Event } from 'vs/base/common/event'; -import { Dimension, EventHelper, EventType, ModifierKeyEmitter, addDisposableListener, cloneGlobalStylesheets, copyAttributes, createLinkElement, createMetaElement, getActiveWindow, getClientArea, getWindowId, isGlobalStylesheet, position, registerWindow, sharedMutationObserver, trackAttributes } from 'vs/base/browser/dom'; +import { Dimension, EventHelper, EventType, ModifierKeyEmitter, addDisposableListener, cloneGlobalStylesheets, copyAttributes, createLinkElement, createMetaElement, getActiveWindow, getClientArea, getWindowId, isGlobalStylesheet, isHTMLElement, position, registerWindow, sharedMutationObserver, trackAttributes } from 'vs/base/browser/dom'; import { CodeWindow, ensureCodeWindow, mainWindow } from 'vs/base/browser/window'; import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { onUnexpectedError } from 'vs/base/common/errors'; -import { isWeb } from 'vs/base/common/platform'; +import { isFirefox, isWeb } from 'vs/base/common/platform'; import { IRectangle, WindowMinimumSize } from 'vs/platform/window/common/window'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import Severity from 'vs/base/common/severity'; @@ -332,7 +332,7 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili options?.mode === AuxiliaryWindowMode.Fullscreen ? 'window-fullscreen=yes' : undefined // non-standard property ]); - const auxiliaryWindow = mainWindow.open('about:blank', undefined, features.join(',')); + const auxiliaryWindow = mainWindow.open(isFirefox ? '' /* FF immediately fires an unload event if using about:blank */ : 'about:blank', undefined, features.join(',')); if (!auxiliaryWindow && isWeb) { return (await this.dialogService.prompt({ type: Severity.Warning, @@ -461,7 +461,7 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili for (const node of mutation.addedNodes) { //