From 83e4841e8835df18a307b26b0fe8660f85bfd238 Mon Sep 17 00:00:00 2001 From: tisilent Date: Mon, 2 Oct 2023 23:53:46 +0800 Subject: [PATCH 001/162] fix renameWithQuickPick and injection --- .../workbench/contrib/terminal/browser/terminalActions.ts | 6 +++++- .../contrib/terminal/browser/terminalQuickAccess.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 0cca842ad38..ccecae910b4 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -1841,7 +1841,11 @@ async function focusActiveTerminal(instance: ITerminalInstance, c: ITerminalServ } async function renameWithQuickPick(c: ITerminalServicesCollection, accessor: ServicesAccessor, resource?: unknown) { - const instance = getResourceOrActiveInstance(c, resource); + let instance: ITerminalInstance | undefined = resource as ITerminalInstance; + if (!instance) { + instance = getResourceOrActiveInstance(c, resource); + } + if (instance) { const title = await accessor.get(IQuickInputService).input({ value: instance.title, diff --git a/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts b/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts index 3ffc1ad2b3a..892cbc5dcb9 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts @@ -26,7 +26,7 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider Date: Fri, 6 Oct 2023 00:01:09 +0800 Subject: [PATCH 002/162] Add multi-select renames to terminalAction --- .../workbench/contrib/terminal/browser/terminalActions.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 0cca842ad38..81ba4fe19b4 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -765,7 +765,8 @@ export function registerTerminalActions() { precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), TerminalContextKeys.tabsSingularSelection), run: async (c, accessor) => { const notificationService = accessor.get(INotificationService); - const instance = getSelectedInstances(accessor)?.[0]; + const instances = getSelectedInstances(accessor); + const instance = instances?.[0]; if (!instance) { return; } @@ -778,7 +779,9 @@ export function registerTerminalActions() { c.service.setEditingTerminal(undefined); if (success) { try { - await instance.rename(value); + instances.forEach(async _instance => { + await _instance.rename(value); + }); } catch (e) { notificationService.error(e); } From 013455ab73489deb09beb4872a9d22faef8e871a Mon Sep 17 00:00:00 2001 From: tisilent Date: Fri, 6 Oct 2023 00:12:29 +0800 Subject: [PATCH 003/162] :lipstick: --- .../contrib/terminal/browser/terminalActions.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 81ba4fe19b4..587ab9e7d67 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -766,22 +766,22 @@ export function registerTerminalActions() { run: async (c, accessor) => { const notificationService = accessor.get(INotificationService); const instances = getSelectedInstances(accessor); - const instance = instances?.[0]; - if (!instance) { + const firstInstance = instances?.[0]; + if (!firstInstance) { return; } - c.service.setEditingTerminal(instance); - c.service.setEditable(instance, { + c.service.setEditingTerminal(firstInstance); + c.service.setEditable(firstInstance, { validationMessage: value => validateTerminalName(value), onFinish: async (value, success) => { // Cancel editing first as instance.rename will trigger a rerender automatically - c.service.setEditable(instance, null); + c.service.setEditable(firstInstance, null); c.service.setEditingTerminal(undefined); if (success) { try { - instances.forEach(async _instance => { - await _instance.rename(value); - }); + for (const instance of instances) { + await instance.rename(value); + } } catch (e) { notificationService.error(e); } From 03d419e90146931f7550b2d72d377dd246a0793f Mon Sep 17 00:00:00 2001 From: tisilent Date: Fri, 6 Oct 2023 21:50:21 +0800 Subject: [PATCH 004/162] Promise --- .../contrib/terminal/browser/terminalActions.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 587ab9e7d67..44d881342b3 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -778,10 +778,14 @@ export function registerTerminalActions() { c.service.setEditable(firstInstance, null); c.service.setEditingTerminal(undefined); if (success) { - try { - for (const instance of instances) { + const promises: Promise[] = []; + for (const instance of instances) { + promises.push((async () => { await instance.rename(value); - } + })()); + } + try { + await Promise.all(promises); } catch (e) { notificationService.error(e); } From 2c973350c5e1b54c8df177314e4f70b3cff2cab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 23 Oct 2023 14:43:33 +0200 Subject: [PATCH 005/162] chore: bump electron@25.9.2 (#196249) * chore: bump electron@25.9.2 * chore: bump distro * install setuptools https://github.com/nodejs/node-gyp/issues/2915 --- .yarnrc | 4 +- build/azure-pipelines/sdl-scan.yml | 1 + .../win32/product-build-win32.yml | 1 + build/checksums/electron.txt | 98 ++++++++++++++----- cgmanifest.json | 4 +- package.json | 4 +- yarn.lock | 8 +- 7 files changed, 87 insertions(+), 33 deletions(-) diff --git a/.yarnrc b/.yarnrc index eb7739abf44..bb7778b5a27 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,5 +1,5 @@ disturl "https://electronjs.org/headers" -target "25.9.1" -ms_build_id "24472542" +target "25.9.2" +ms_build_id "24603566" runtime "electron" build_from_source "true" diff --git a/build/azure-pipelines/sdl-scan.yml b/build/azure-pipelines/sdl-scan.yml index 165d4d00a86..91c8a2477af 100644 --- a/build/azure-pipelines/sdl-scan.yml +++ b/build/azure-pipelines/sdl-scan.yml @@ -108,6 +108,7 @@ stages: exec { git clone https://github.com/rzhao271/node-gyp.git . } "Cloning rzhao271/node-gyp failed" exec { git checkout 102b347da0c92c29f9c67df22e864e70249cf086 } "Checking out 102b347 failed" exec { npm install } "Building rzhao271/node-gyp failed" + exec { python3 -m pip install setuptools } "Installing setuptools failed" displayName: Install custom node-gyp workingDirectory: .build/node-gyp condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 4591ba6c618..d5d62fa031f 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -105,6 +105,7 @@ steps: exec { git checkout v9.4.0 } "Checking out v9.4.0 failed" exec { git am --3way --whitespace=fix ../../build/npm/gyp/patches/gyp_spectre_mitigation_support.patch } "Apply spectre patch failed" exec { npm install } "Building node-gyp failed" + exec { python3 -m pip install setuptools } "Installing setuptools failed" displayName: Install custom node-gyp workingDirectory: .build/node-gyp condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true')) diff --git a/build/checksums/electron.txt b/build/checksums/electron.txt index 421b88a4fdb..07aca726e4e 100644 --- a/build/checksums/electron.txt +++ b/build/checksums/electron.txt @@ -1,23 +1,75 @@ -4a472f48b54e92855ad77606f11a620523f3abe4ee1bc2997a300ae72da4b2f5 *electron-v25.9.1-darwin-arm64-symbols.zip -247daa6c9faf711162dc623832fcb189d3c1ef6a15884084cb45c8da3a037b6b *electron-v25.9.1-darwin-arm64.zip -7d8ec9d3272dbe356deb09b47ccfda30c421b32f7e906f1186ea26f894b22dc1 *electron-v25.9.1-darwin-x64-symbols.zip -35fc99808ea026a21afeca537c218ace398d299fba7ab73d2630be513f1e1617 *electron-v25.9.1-darwin-x64.zip -bfcd6ac66f067cfec08b6d18ed80b519e6d70a96d9b1d31dc2cfcf86f4a9af96 *electron-v25.9.1-linux-arm64-symbols.zip -1c8aa3f13ade23858664b687ad334634ccd698ec7d627554d16cbb596ffa7a0f *electron-v25.9.1-linux-arm64.zip -dcfb4a1d6b2ceffa7a8d9a60b9de027d006753eae1278f07de907c474e71c270 *electron-v25.9.1-linux-armv7l-symbols.zip -f4320f1888354e17595fb6901c03c383f45325bfba5e6e1b91b4200ff696049f *electron-v25.9.1-linux-armv7l.zip -772dd276d328549e0111b93b43d395de51ff46eba550be48c649c386997125a8 *electron-v25.9.1-linux-x64-symbols.zip -35529c411275791abf9aa46f0a2e216b0affa542757583afb438a76047f6b90c *electron-v25.9.1-linux-x64.zip -5b0b4595691da19258ce0b2c09f58ba969987d24ae8160661a715eaadf42c16b *electron-v25.9.1-win32-arm64-pdb.zip -1e67a35b41927962765a8d8cb01ce73e8c28db6453323f2661e63afd8fdf49e8 *electron-v25.9.1-win32-arm64-symbols.zip -a378f5fc44e872f05d037c3ca7f03802ed3a9b2611f59741ce933f500557af7c *electron-v25.9.1-win32-arm64.zip -b50f8675b12eda5d0717f83179e40b411ba3254f81bd7142821745c00b566560 *electron-v25.9.1-win32-x64-pdb.zip -8ddaa416e51bac1e93c63d1223bec37b6dd78b00c860e5b91912da09af7ff7b5 *electron-v25.9.1-win32-x64-symbols.zip -f6762a98193baa9877f443c9414b1f825f99b7cf1094be579d5202b72442b5be *electron-v25.9.1-win32-x64.zip -a0c2566efff0a796f751cfc63cddd52d6c4153b35b6ad582bbdd15a2c4317bc9 *ffmpeg-v25.9.1-darwin-arm64.zip -b8cd9d93cdf8ebbd3caf68581b6504529b8bf2dea984b6e5f637343ea9d61946 *ffmpeg-v25.9.1-darwin-x64.zip -bd52d57ff97fb56ac01a3482af905d04f0d4e9c13c53858c6d9f99957eca82da *ffmpeg-v25.9.1-linux-arm64.zip -9b3d09177fa1e63e2a6beecfa70aeec30aeb5c1873ff21128a68051c4e23f95d *ffmpeg-v25.9.1-linux-armv7l.zip -edc7b1c9f1a0733f109a2c0375a4e40c5bfe0bf28b7f06dcc76e1ada0aa2f125 *ffmpeg-v25.9.1-linux-x64.zip -2467f6567356340e8d9872753a3df486555334b7c868c0d12991f80f2353ce1f *ffmpeg-v25.9.1-win32-arm64.zip -fe4676a13bf9d6f87353f3496e0fb37cd3db151fcea13dad7610a2835d238062 *ffmpeg-v25.9.1-win32-x64.zip +2606d6745056d248fe7ba21e6a30467d3ea80d2689c5fa6d2a35acf1b4a72ddd *chromedriver-v25.9.2-darwin-arm64.zip +22a86732b9e6c2afc07021ea0adeb92cdbaaa8751843c0d5170b5e96550685e7 *chromedriver-v25.9.2-darwin-x64.zip +f5f42513bb55c7c1098e669d12488844ca2e63cd0d3a375db2eab517975c130c *chromedriver-v25.9.2-linux-arm64.zip +28a5613f7e4b117a65ec2882b124bf1d388f1c4fb86b228acadc297601faa6fd *chromedriver-v25.9.2-linux-armv7l.zip +7d01d537383df4b1653647e14fb768d27879943596a87b57ae3f171aa2aaf5d1 *chromedriver-v25.9.2-linux-x64.zip +3fac66fe45b4a5dcd9a4784d66bd8087d0dee5fccf06cb3f34e78f8bef3f0f8f *chromedriver-v25.9.2-mas-arm64.zip +a15fc80fac243330f15a7ff7cc834c50c79833e81b871cc45f7239bf1743b4ac *chromedriver-v25.9.2-mas-x64.zip +f0a354e01e277b14422e34f8af9c8c43ae975c6fb69a2e61ef275b6ec919f2ab *chromedriver-v25.9.2-win32-arm64.zip +570a6b5bc485bfea9681c97b79832d5d5bcafdd993c13dc4ab11558e3a27c554 *chromedriver-v25.9.2-win32-ia32.zip +4134f539ac304c65dfca9812b0d3943ea64d886989eba8f62828718b106c4eee *chromedriver-v25.9.2-win32-x64.zip +835418b9274c76503542c986d63bb9d98f071c702170536bdd62c1760589e01e *electron-api.json +fd9f5b1439445acc69441ef66cc47f56c5c0848dec5f6daf91a476073e72a756 *electron-v25.9.2-darwin-arm64-dsym-snapshot.zip +de29ef2a4c7b76281b1cf3ac9e6047a9275cc60167c6cd60509f2eb2a3258842 *electron-v25.9.2-darwin-arm64-dsym.zip +732f51802f2902ca08c3a06a45fe23820b1effbeb3ebd39fcae9fce5a1e0b25d *electron-v25.9.2-darwin-arm64-symbols.zip +ab82efb59077a85fd20264f8ad0dedc4c8b0b2fc9d2948ed9461425faf5e35f6 *electron-v25.9.2-darwin-arm64.zip +fb924b4dd0d781a14114e54fa556ca326c60665b674712c59163e7b44db675d8 *electron-v25.9.2-darwin-x64-dsym-snapshot.zip +197fc3e120e54578658e2f10b5fcec1d2004f1637d4bee116ff1e12b0c5a1429 *electron-v25.9.2-darwin-x64-dsym.zip +57d0a0f55726524ff843a040e516e425c3537a4602ab8c23120433fbc51470fb *electron-v25.9.2-darwin-x64-symbols.zip +0fe310e2ed13a97cd9c28fb0cf806338cd2e720083e6d1b13d60ba4cedb8f295 *electron-v25.9.2-darwin-x64.zip +eb1a31ccd6a89a21538a8b1f0b5d3b77e1fe946b898319e1832cb9dc3abcd753 *electron-v25.9.2-linux-arm64-debug.zip +b5b128bed0a09955ad5bb91fa9f5ab9155a547f787ad580bcd5bf409bb697ff6 *electron-v25.9.2-linux-arm64-symbols.zip +0b2d48a29d79fcd21d72d05fdb7638dd2fd257cf0d4cf9bd32f182b2634de466 *electron-v25.9.2-linux-arm64.zip +eb1a31ccd6a89a21538a8b1f0b5d3b77e1fe946b898319e1832cb9dc3abcd753 *electron-v25.9.2-linux-armv7l-debug.zip +43f1f4c1475335719ba8f1f7f036a084fb22b5faa908bf4f7d30a96d5d9c159d *electron-v25.9.2-linux-armv7l-symbols.zip +4ea3ee3ad41c69454d9a12518eeff1ec5dbd841c8200dc8652e6c0b101d1259c *electron-v25.9.2-linux-armv7l.zip +1a8daf1f9e155d7143d16367e54e4e3b8e9d71ad580b44c8dfba0cb4e7a1c640 *electron-v25.9.2-linux-x64-debug.zip +803f32ca345d8974cc074dc177e06c62f8bcc98d4a39eccb676b7d302b8fc466 *electron-v25.9.2-linux-x64-symbols.zip +aab65a562723e04eadbdee1251a749756b366dc1c5014bcc987c21c0a523fe2f *electron-v25.9.2-linux-x64.zip +fd9f5b1439445acc69441ef66cc47f56c5c0848dec5f6daf91a476073e72a756 *electron-v25.9.2-mas-arm64-dsym-snapshot.zip +0ec88ec7bd2b7cb2e5e6b94f13df7d8c22433637004a473370e0959cb01f78cc *electron-v25.9.2-mas-arm64-dsym.zip +398a0575c1974565af99b6759a74967c0709bc101059542a00bfe64a1210a86f *electron-v25.9.2-mas-arm64-symbols.zip +17f86ad33f9fc2ca5eaac5ef87604e65b1eefba5a51d4ad58e70018fdfb84ac6 *electron-v25.9.2-mas-arm64.zip +db61b29802ee1f598a3e61211a281656f16e70ae84041e6b2b5dd8ecae43cd67 *electron-v25.9.2-mas-x64-dsym-snapshot.zip +2f76620eb7d632335f7620f5d3713af5e59c98bdb0b323269c2319b7164fcaac *electron-v25.9.2-mas-x64-dsym.zip +ea226c8d049e527d84ec5058474fd4e64476e6924fef42b1dbea774925f59064 *electron-v25.9.2-mas-x64-symbols.zip +51b9d192ccb7612211ca9cc8ddb373a86f791d38b369337ad099a133e9d9807a *electron-v25.9.2-mas-x64.zip +53b39857303191ea2f26dda06461e6e612ca0ed799bdf0c26a1a63ff89f7ea1b *electron-v25.9.2-win32-arm64-pdb.zip +49199591c69fbeb68dd57252a3d8525babe79ab98447ad639f2d0c3e63aba4b6 *electron-v25.9.2-win32-arm64-symbols.zip +e7b968fc53cc7a10a4ccb5133af045968479685ebb9617f06817f03667fdd425 *electron-v25.9.2-win32-arm64-toolchain-profile.zip +6abd0a6697d7fe8b6add4d1017a01a0ac756d16da5bfa077bd373a685b529bd8 *electron-v25.9.2-win32-arm64.zip +cc5c67b027c679eb86882c2ec267d38fafcc5127b49e8a060002541253e2b26b *electron-v25.9.2-win32-ia32-pdb.zip +2cd8aab8aa4eadfce90c8ba6565a77689db1efe55b7eaafedede3b08e8c41f53 *electron-v25.9.2-win32-ia32-symbols.zip +e7b968fc53cc7a10a4ccb5133af045968479685ebb9617f06817f03667fdd425 *electron-v25.9.2-win32-ia32-toolchain-profile.zip +ac2aebe7d7b21351256fb3b60219269e75ff33f8c3cfbbca682c3622d1943b94 *electron-v25.9.2-win32-ia32.zip +000b506bab92c92e0ff8428033fc7e1c15049437606794c4bec84a66eb29b6cd *electron-v25.9.2-win32-x64-pdb.zip +fd40d04de0ef4a04dd720505f03a6d209a38387fe05493869f441037aa950e4d *electron-v25.9.2-win32-x64-symbols.zip +e7b968fc53cc7a10a4ccb5133af045968479685ebb9617f06817f03667fdd425 *electron-v25.9.2-win32-x64-toolchain-profile.zip +de3fc45f4fa5572d6dbb4f21580e75d3b6429a6b3b833a962c810e7e199b8573 *electron-v25.9.2-win32-x64.zip +c3f22fbf99713bb44546278ef1456e4fc9a83d33bf038f6752fea12c7a721337 *electron.d.ts +2a088f4c227405783466e456e69154193a730130f5cc39520091abc8993977bc *ffmpeg-v25.9.2-darwin-arm64.zip +4da4197282a9a31379d2194d1072888b9ed3200663e322df2759b971725a2915 *ffmpeg-v25.9.2-darwin-x64.zip +bd52d57ff97fb56ac01a3482af905d04f0d4e9c13c53858c6d9f99957eca82da *ffmpeg-v25.9.2-linux-arm64.zip +9b3d09177fa1e63e2a6beecfa70aeec30aeb5c1873ff21128a68051c4e23f95d *ffmpeg-v25.9.2-linux-armv7l.zip +39c3e411873262873edff4b9f4b5d9973fb3cab8f700d6ff665872dab3b39eb3 *ffmpeg-v25.9.2-linux-x64.zip +861287a6cb0f546c0e39f49a2b28f5575d66fbddb26486584cc7802e84402339 *ffmpeg-v25.9.2-mas-arm64.zip +bcc8315a9e07394510c96ffca20720e3cdb2a4aecc75798bfca8fd60417782aa *ffmpeg-v25.9.2-mas-x64.zip +0ebfe5a72aaf0a9af81ffbcba03763f4baa142c93c31b50ad0145365366f0076 *ffmpeg-v25.9.2-win32-arm64.zip +d8e7ea1268145d3481a74152ced8ae677ca5b174f06eb874a6ce0005ff0d471c *ffmpeg-v25.9.2-win32-ia32.zip +d1f499b957377c3822c43eadf3bc32e7cb04b52fb2fd51ba22f14cd61ef01727 *ffmpeg-v25.9.2-win32-x64.zip +86a0df1394e741feb21a891747775911d5c2f9cd940662826b33c309275abb7c *hunspell_dictionaries.zip +4c4bab279b39c4e463dcb3a897e256e5e4f088e6e6495f6aea10e26703ecafc3 *libcxx-objects-v25.9.2-linux-arm64.zip +d2b6349a89c9fce3ccc0a9a430b059eb18cd3967dbbe34bfcae54b3f58cd462a *libcxx-objects-v25.9.2-linux-armv7l.zip +e8d4b1a3228c0709dc54d780bd4d33727fff30c38f8e00409a6eaf54a69e5869 *libcxx-objects-v25.9.2-linux-x64.zip +7679259e7cb02140806cc616d012102462d671ae07c4673ad0c2c9a6716444a6 *libcxx_headers.zip +b1683af6708bceaa966e5168fda51223fa51e09549abc90f5744d500f9260c92 *libcxxabi_headers.zip +4fed33611a889d0100a6fbf4253cf9dcb9fbe3c42f7c86d8886d460a9a9cf8e6 *mksnapshot-v25.9.2-darwin-arm64.zip +5e1daea6393bd977a70020c36f1e4ee4e416c8c4eafe2b27b38292e4acb1764b *mksnapshot-v25.9.2-darwin-x64.zip +92ff719eb83df7f107d4dd3970122333f4bde194292c568b5c0a5ea4684bc9f1 *mksnapshot-v25.9.2-linux-arm64-x64.zip +e621d50652f2afa49f47ab7cccd07f7d29ef60f694a0e70d4e6434ddd07cf282 *mksnapshot-v25.9.2-linux-armv7l-x64.zip +012c24dd59f7b5b4322e53c12bb6450a7b15bc6800042fcf3804ba14685f8188 *mksnapshot-v25.9.2-linux-x64.zip +62e880bf8594b1d83926984c252d86990f1386655bd1375afc0fd3054018adef *mksnapshot-v25.9.2-mas-arm64.zip +0742e1bfcbe171199f0a333fddbf401a61777928d462b852d21fec2822b2c46e *mksnapshot-v25.9.2-mas-x64.zip +b019e6e117e13238465d1758274ebbaf7ccb999921dcb11ef1e3a9a5a6df952b *mksnapshot-v25.9.2-win32-arm64-x64.zip +bc7196f1fd2ba3aedc6c16e96e455d280155dfc493a0d0f6ce7bffe645e39e1e *mksnapshot-v25.9.2-win32-ia32.zip +2d152f09969d69439e831b4212e77ea157a9e4b3a9b3ad55d4f2efcc547c25eb *mksnapshot-v25.9.2-win32-x64.zip \ No newline at end of file diff --git a/cgmanifest.json b/cgmanifest.json index 2fa163fb7ba..1610dea5d34 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -528,12 +528,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "805674fa8aae4d652b6956a96f8eadf9d9137457" + "commitHash": "468c4af6611c88762b7ba6c4400c5022895457c2" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "25.9.1" + "version": "25.9.2" }, { "component": { diff --git a/package.json b/package.json index 0fdbab3c9e3..d0f068bf344 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.84.0", - "distro": "b30d9687a6941b0d17b73334fc5a0f12590bff90", + "distro": "1718b161bc9e156c23d1040ef7655b9313618104", "author": { "name": "Microsoft Corporation" }, @@ -150,7 +150,7 @@ "cssnano": "^4.1.11", "debounce": "^1.0.0", "deemon": "^1.8.0", - "electron": "25.9.1", + "electron": "25.9.2", "eslint": "8.36.0", "eslint-plugin-header": "3.1.1", "eslint-plugin-jsdoc": "^46.5.0", diff --git a/yarn.lock b/yarn.lock index 9937e7f3471..8974fecac79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3518,10 +3518,10 @@ electron-to-chromium@^1.4.202: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.207.tgz#9c3310ebace2952903d05dcaba8abe3a4ed44c01" integrity sha512-piH7MJDJp4rJCduWbVvmUd59AUne1AFBJ8JaRQvk0KzNTSUnZrVXHCZc+eg+CGE4OujkcLJznhGKD6tuAshj5Q== -electron@25.9.1: - version "25.9.1" - resolved "https://registry.yarnpkg.com/electron/-/electron-25.9.1.tgz#cc4baecbebe346b050b9cf9db9882d3d00fc4abd" - integrity sha512-Uo/Fh7igjoUXA/f90iTATZJesQEArVL1uLA672JefNWTLymdKSZkJKiCciu/Xnd0TS6qvdIOUGuJFSTQnKskXQ== +electron@25.9.2: + version "25.9.2" + resolved "https://registry.yarnpkg.com/electron/-/electron-25.9.2.tgz#12be98fbcff485c94ff99df21e0727797a45364a" + integrity sha512-hVBN5rsrL99BKNHvzMeYy2PkAmewuIobu4U3o3EzVz4MDoLmMfW4yTH5GZ4RbJrpokoEky5IzGtRR/ggPzL6Fw== dependencies: "@electron/get" "^2.0.0" "@types/node" "^18.11.18" From b9ccb87c62f940050d0599579f30663498df0d3c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2023 14:51:47 +0200 Subject: [PATCH 006/162] voice - rename mic action (#196263) --- .../contrib/chat/electron-sandbox/actions/voiceChatActions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts index 787443bd275..682280ee4c8 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts @@ -445,8 +445,8 @@ export class StartVoiceChatAction extends Action2 { super({ id: StartVoiceChatAction.ID, title: { - value: localize('workbench.action.chat.startVoiceChat', "Start Voice Chat"), - original: 'Start Voice Chat' + value: localize('workbench.action.chat.startVoiceChat', "Chat by Voice"), + original: 'Chat by Voice' }, icon: Codicon.mic, precondition: ContextKeyExpr.and(HasSpeechProvider, CONTEXT_VOICE_CHAT_GETTING_READY.negate()), From 84b9410ef590789ff42472595c1e402b65d58ef2 Mon Sep 17 00:00:00 2001 From: BeniBenj Date: Mon, 23 Oct 2023 15:00:18 +0200 Subject: [PATCH 007/162] Command Center File name when no tabs --- .../parts/titlebar/commandCenterControl.ts | 18 +++++++++++++++++- .../browser/parts/titlebar/windowTitle.ts | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts b/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts index 4e62e3a111d..7347399f6dd 100644 --- a/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts @@ -20,6 +20,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { WindowTitle } from 'vs/workbench/browser/parts/titlebar/windowTitle'; +import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; export class CommandCenterControl { @@ -81,6 +82,7 @@ class CommandCenterCenterViewItem extends BaseActionViewItem { options: IBaseActionViewItemOptions, @IKeybindingService private _keybindingService: IKeybindingService, @IInstantiationService private _instaService: IInstantiationService, + @IEditorGroupsService private _editorGroupService: IEditorGroupsService, ) { super(undefined, _submenu.actions.find(action => action.id === 'workbench.action.quickOpenWithModes') ?? _submenu.actions[0], options); } @@ -157,6 +159,14 @@ class CommandCenterCenterViewItem extends BaseActionViewItem { hover.update(this.getTooltip()); labelElement.innerText = this._getLabel(); })); + + // update label & tooltip when tabs visibility changes + this._store.add(that._editorGroupService.onDidChangeEditorPartOptions(({ newPartOptions, oldPartOptions }) => { + if (newPartOptions.showTabs !== oldPartOptions.showTabs) { + hover.update(this.getTooltip()); + labelElement.innerText = this._getLabel(); + } + })); } protected override getTooltip() { @@ -165,7 +175,13 @@ class CommandCenterCenterViewItem extends BaseActionViewItem { private _getLabel(): string { const { prefix, suffix } = that._windowTitle.getTitleDecorations(); - let label = that._windowTitle.isCustomTitleFormat() ? that._windowTitle.getWindowTitle() : that._windowTitle.workspaceName; + let label = that._windowTitle.workspaceName; + if (that._windowTitle.isCustomTitleFormat()) { + label = that._windowTitle.getWindowTitle(); + } else if (that._editorGroupService.partOptions.showTabs === 'none') { + label = that._windowTitle.fileName ?? label; + } + if (!label) { label = localize('label.dfl', "Search"); } diff --git a/src/vs/workbench/browser/parts/titlebar/windowTitle.ts b/src/vs/workbench/browser/parts/titlebar/windowTitle.ts index 5e97cbebd85..c340b7ef959 100644 --- a/src/vs/workbench/browser/parts/titlebar/windowTitle.ts +++ b/src/vs/workbench/browser/parts/titlebar/windowTitle.ts @@ -47,6 +47,7 @@ export class WindowTitle extends Disposable { get value() { return this.title ?? ''; } get workspaceName() { return this.labelService.getWorkspaceLabel(this.contextService.getWorkspace()); } + get fileName() { return this.editorService.activeEditor?.getTitle(Verbosity.SHORT); } private title: string | undefined; private titleIncludesFocusedView: boolean = false; From a824942dd5c6f09c4ca18358f68284c80186c076 Mon Sep 17 00:00:00 2001 From: BeniBenj Date: Mon, 23 Oct 2023 15:18:00 +0200 Subject: [PATCH 008/162] Accessing filename through windowTitle is weird chnged it back --- .../workbench/browser/parts/titlebar/commandCenterControl.ts | 3 ++- src/vs/workbench/browser/parts/titlebar/windowTitle.ts | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts b/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts index 7347399f6dd..088a5d32281 100644 --- a/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts @@ -20,6 +20,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { WindowTitle } from 'vs/workbench/browser/parts/titlebar/windowTitle'; +import { Verbosity } from 'vs/workbench/common/editor'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; export class CommandCenterControl { @@ -179,7 +180,7 @@ class CommandCenterCenterViewItem extends BaseActionViewItem { if (that._windowTitle.isCustomTitleFormat()) { label = that._windowTitle.getWindowTitle(); } else if (that._editorGroupService.partOptions.showTabs === 'none') { - label = that._windowTitle.fileName ?? label; + label = that._editorGroupService.activeGroup.activeEditor?.getTitle(Verbosity.SHORT) ?? label; } if (!label) { diff --git a/src/vs/workbench/browser/parts/titlebar/windowTitle.ts b/src/vs/workbench/browser/parts/titlebar/windowTitle.ts index c340b7ef959..5e97cbebd85 100644 --- a/src/vs/workbench/browser/parts/titlebar/windowTitle.ts +++ b/src/vs/workbench/browser/parts/titlebar/windowTitle.ts @@ -47,7 +47,6 @@ export class WindowTitle extends Disposable { get value() { return this.title ?? ''; } get workspaceName() { return this.labelService.getWorkspaceLabel(this.contextService.getWorkspace()); } - get fileName() { return this.editorService.activeEditor?.getTitle(Verbosity.SHORT); } private title: string | undefined; private titleIncludesFocusedView: boolean = false; From 4cd1f6ce8406004fc5ce2c58a66c457d0104cae0 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Mon, 23 Oct 2023 15:22:45 +0200 Subject: [PATCH 009/162] Git - automatically wrap generated commit message (#196268) * Git - automatically wrap generated commit messages * Handle edge cases when wrapping the commit message --- extensions/git/src/repository.ts | 47 +++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 21aac729dd9..21859a62434 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -34,6 +34,47 @@ function getIconUri(iconName: string, theme: string): Uri { return Uri.file(path.join(iconsRootPath, theme, `${iconName}.svg`)); } +function wrapCommitMessage(message: string, subjectLineLength: number, bodyLineLength: number): string { + const messageLinesWrapped: string[] = []; + const messageLines = message.split(/\r?\n/g); + + for (let index = 0; index < messageLines.length; index++) { + const messageLine = messageLines[index]; + const threshold = index === 0 ? subjectLineLength : bodyLineLength; + + if (messageLine.length <= threshold) { + messageLinesWrapped.push(messageLine); + continue; + } + + let position = 0; + const lineSegments: string[] = []; + while (messageLine.length - position > threshold) { + const lastSpaceBeforeThreshold = messageLine.lastIndexOf(' ', position + threshold); + if (lastSpaceBeforeThreshold !== -1 && lastSpaceBeforeThreshold > position) { + lineSegments.push(...[messageLine.substring(position, lastSpaceBeforeThreshold), '\n']); + position = lastSpaceBeforeThreshold + 1; + } else { + // Find first space after threshold + const firstSpaceAfterThreshold = messageLine.indexOf(' ', position); + if (firstSpaceAfterThreshold !== -1) { + lineSegments.push(...[messageLine.substring(position, firstSpaceAfterThreshold), '\n']); + position = firstSpaceAfterThreshold + 1; + } else { + lineSegments.push(messageLine.substring(position)); + position = messageLine.length; + } + } + } + if (position < messageLine.length) { + lineSegments.push(messageLine.substring(position)); + } + messageLinesWrapped.push(lineSegments.join('')); + } + + return messageLinesWrapped.join('\n'); +} + export const enum RepositoryState { Idle, Disposed @@ -2050,7 +2091,11 @@ export class Repository implements Disposable { const provider = this.commitMessageProviderRegistry.commitMessageProvider; const commitMessage = await provider.provideCommitMessage(new ApiRepository(this), diff, token); if (commitMessage) { - this.inputBox.value = commitMessage; + const config = workspace.getConfiguration('git'); + const subjectLineLength = config.get('inputValidationSubjectLength', null); + const bodyLineLength = config.get('inputValidationLength', 50); + + this.inputBox.value = wrapCommitMessage(commitMessage, subjectLineLength ?? bodyLineLength, bodyLineLength); } } catch (err) { From a8eab0831bb5905a6fb49c67373ce3a273dc5b8d Mon Sep 17 00:00:00 2001 From: BeniBenj Date: Mon, 23 Oct 2023 15:26:08 +0200 Subject: [PATCH 010/162] :lipstick: --- .../browser/parts/titlebar/commandCenterControl.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts b/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts index 088a5d32281..e9b53aef62e 100644 --- a/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts @@ -22,6 +22,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { WindowTitle } from 'vs/workbench/browser/parts/titlebar/windowTitle'; import { Verbosity } from 'vs/workbench/common/editor'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; export class CommandCenterControl { @@ -84,6 +85,7 @@ class CommandCenterCenterViewItem extends BaseActionViewItem { @IKeybindingService private _keybindingService: IKeybindingService, @IInstantiationService private _instaService: IInstantiationService, @IEditorGroupsService private _editorGroupService: IEditorGroupsService, + @IEditorService private _editorService: IEditorService, ) { super(undefined, _submenu.actions.find(action => action.id === 'workbench.action.quickOpenWithModes') ?? _submenu.actions[0], options); } @@ -179,8 +181,8 @@ class CommandCenterCenterViewItem extends BaseActionViewItem { let label = that._windowTitle.workspaceName; if (that._windowTitle.isCustomTitleFormat()) { label = that._windowTitle.getWindowTitle(); - } else if (that._editorGroupService.partOptions.showTabs === 'none') { - label = that._editorGroupService.activeGroup.activeEditor?.getTitle(Verbosity.SHORT) ?? label; + } else if (that._editorGroupService.partOptions.showTabs === 'none' && that._editorService.activeEditor) { + label = that._editorService.activeEditor.getTitle(Verbosity.SHORT); } if (!label) { From e1d9c44890114df2c27a916d2701c70a84583217 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Mon, 23 Oct 2023 15:34:11 +0200 Subject: [PATCH 011/162] Bump distro (#196271) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d0f068bf344..3084298609a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.84.0", - "distro": "1718b161bc9e156c23d1040ef7655b9313618104", + "distro": "5aa48e269e387638c21b3e3ed6863c739b2df0e6", "author": { "name": "Microsoft Corporation" }, From c366d0f2b9f7f0d9dab3605f9aea762a1ca0d5d0 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 23 Oct 2023 15:39:03 +0200 Subject: [PATCH 012/162] Update title bar style context key and activity bar position actions (#196276) --- src/vs/workbench/browser/contextkeys.ts | 6 +++++- .../workbench/browser/parts/activitybar/activitybarPart.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts index f052cd5f7a9..85fcf0f5968 100644 --- a/src/vs/workbench/browser/contextkeys.ts +++ b/src/vs/workbench/browser/contextkeys.ts @@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey'; import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys'; -import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, MaximizedEditorGroupContext, TitleBarVisibleContext } from 'vs/workbench/common/contextkeys'; +import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, MaximizedEditorGroupContext, TitleBarVisibleContext, TitleBarStyleContext } from 'vs/workbench/common/contextkeys'; import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow } from 'vs/base/browser/dom'; import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -25,6 +25,7 @@ import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/b import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess'; import { IProductService } from 'vs/platform/product/common/productService'; import { FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files'; +import { getTitleBarStyle } from 'vs/platform/window/common/window'; export class WorkbenchContextKeysHandler extends Disposable { private inputFocusedContext: IContextKey; @@ -76,6 +77,7 @@ export class WorkbenchContextKeysHandler extends Disposable { private auxiliaryBarVisibleContext: IContextKey; private editorTabsVisibleContext: IContextKey; private titleAreaVisibleContext: IContextKey; + private titleBarStyleContext: IContextKey; constructor( @IContextKeyService private readonly contextKeyService: IContextKeyService, @@ -200,6 +202,7 @@ export class WorkbenchContextKeysHandler extends Disposable { // Title Bar this.titleAreaVisibleContext = TitleBarVisibleContext.bindTo(this.contextKeyService); + this.titleBarStyleContext = TitleBarStyleContext.bindTo(this.contextKeyService); this.updateTitleBarContextKeys(); // Panel @@ -379,6 +382,7 @@ export class WorkbenchContextKeysHandler extends Disposable { private updateTitleBarContextKeys(): void { this.titleAreaVisibleContext.set(this.layoutService.isVisible(Parts.TITLEBAR_PART)); + this.titleBarStyleContext.set(getTitleBarStyle(this.configurationService)); } private updateWorkspaceContextKeys(): void { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 4a3f1f9b669..dd1a27b0088 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -359,7 +359,7 @@ registerAction2(class extends Action2 { }, shortTitle: localize('side', "Side"), category: Categories.View, - toggled: ContextKeyExpr.equals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.SIDE), + toggled: ContextKeyExpr.or(ContextKeyExpr.equals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.SIDE), ContextKeyExpr.and(ContextKeyExpr.equals(`config.${LayoutSettings.ACTIVITY_BAR_LOCATION}`, ActivityBarPosition.TOP), TitleBarStyleContext.isEqualTo('native'))), menu: [{ id: MenuId.ActivityBarPositionMenu, order: 1 From 3a30095066eca757411ea45ac4544d60fd948f75 Mon Sep 17 00:00:00 2001 From: BeniBenj Date: Mon, 23 Oct 2023 15:40:43 +0200 Subject: [PATCH 013/162] Empty Group Maximized Action Item --- .../workbench/browser/parts/editor/editor.contribution.ts | 2 +- src/vs/workbench/browser/parts/editor/editorActions.ts | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 43df6bf2818..e732015eee0 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -357,7 +357,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTabsBarContext, { command: { id: SPLIT_ MenuRegistry.appendMenuItem(MenuId.EditorTabsBarContext, { command: { id: SPLIT_EDITOR_DOWN, title: localize('splitDown', "Split Down") }, group: '2_split', order: 20 }); MenuRegistry.appendMenuItem(MenuId.EditorTabsBarContext, { command: { id: SPLIT_EDITOR_LEFT, title: localize('splitLeft', "Split Left") }, group: '2_split', order: 30 }); MenuRegistry.appendMenuItem(MenuId.EditorTabsBarContext, { command: { id: SPLIT_EDITOR_RIGHT, title: localize('splitRight', "Split Right") }, group: '2_split', order: 40 }); -MenuRegistry.appendMenuItem(MenuId.EditorTabsBarContext, { submenu: MenuId.EditorTabsBarShowTabsSubmenu, title: localize('tabBar', "Tab bar"), group: '3_config', order: 10 }); +MenuRegistry.appendMenuItem(MenuId.EditorTabsBarContext, { submenu: MenuId.EditorTabsBarShowTabsSubmenu, title: localize('tabBar', "Tab Bar"), group: '3_config', order: 10 }); MenuRegistry.appendMenuItem(MenuId.EditorTabsBarShowTabsSubmenu, { command: { id: ShowMultipleEditorTabsAction.ID, title: localize('multipleTabs', "Multiple Tabs"), toggled: ContextKeyExpr.equals('config.workbench.editor.showTabs', 'multiple') }, group: '1_config', order: 10 }); MenuRegistry.appendMenuItem(MenuId.EditorTabsBarShowTabsSubmenu, { command: { id: ShowSingleEditorTabAction.ID, title: localize('singleTab', "Single Tab"), toggled: ContextKeyExpr.equals('config.workbench.editor.showTabs', 'single') }, group: '1_config', order: 20 }); MenuRegistry.appendMenuItem(MenuId.EditorTabsBarShowTabsSubmenu, { command: { id: HideEditorTabsAction.ID, title: localize('hideTabBar', "Hide"), toggled: ContextKeyExpr.equals('config.workbench.editor.showTabs', 'none') }, group: '1_config', order: 30 }); diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 38800f952db..4b96cc8a0e7 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -1125,12 +1125,18 @@ export class UnmaximizeEditorGroupAction extends Action2 { weight: KeybindingWeight.WorkbenchContrib, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyM), }, - menu: { + menu: [{ id: MenuId.EditorTitle, order: -10000, // towards the front group: 'navigation', when: MaximizedEditorGroupContext }, + { + id: MenuId.EmptyEditorGroup, + order: -10000, // towards the front + group: 'navigation', + when: MaximizedEditorGroupContext + }], icon: Codicon.screenFull, toggled: MaximizedEditorGroupContext, }); From c523b5e9e0406380961740442c642a59a2aa8147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20Ruales?= <1588988+jruales@users.noreply.github.com> Date: Mon, 23 Oct 2023 07:27:12 -0700 Subject: [PATCH 014/162] Skip regex.replace() cost when there's nothing to replace (#194854) * Skip regex.replace() cost when there's nothing to replace * Change spaces to tabs --- src/vs/base/common/strings.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index 02d9179c792..7e354e3bce5 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -42,6 +42,9 @@ const _format2Regexp = /{([^}]+)}/g; * Similar to `format` but with objects instead of positional arguments. */ export function format2(template: string, values: Record): string { + if (Object.keys(values).length === 0) { + return template; + } return template.replace(_format2Regexp, (match, group) => (values[group] ?? match) as string); } From 0f1b533b7b810758022dd746214786a98df7fd45 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2023 16:52:10 +0200 Subject: [PATCH 015/162] aux window - less use of `ILayoutService.container` (#196282) * aux window - less use of `ILayoutService.container` * . --- src/vs/base/browser/dom.ts | 18 ++++++------ src/vs/base/browser/touch.ts | 10 +++---- .../browser/quickInputController.ts | 2 +- .../browser/actions/textInputActions.ts | 23 +++++++++------ src/vs/workbench/browser/contextkeys.ts | 2 +- .../codeEditor/browser/toggleWordWrap.ts | 8 +++--- .../browser/contextmenu.contribution.ts | 2 +- .../browser/auxiliaryWindowService.ts | 28 ++++++++++++++++--- .../history/browser/historyService.ts | 19 +++++++++++-- .../keybinding/browser/keybindingService.ts | 2 +- .../progress/browser/progressService.ts | 4 +-- 11 files changed, 79 insertions(+), 39 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 46290602d90..e6bd07fb66d 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -19,7 +19,7 @@ import { URI } from 'vs/base/common/uri'; export const { registerWindow, getWindows, onDidRegisterWindow, onWillUnregisterWindow, onDidUnregisterWindow } = (function () { const windows = new Set([window]); - const onDidRegisterWindow = new event.Emitter<{ window: Window & typeof globalThis; disposableStore: DisposableStore }>(); + const onDidRegisterWindow = new event.Emitter<{ window: Window & typeof globalThis; disposables: DisposableStore }>(); const onDidUnregisterWindow = new event.Emitter(); const onWillUnregisterWindow = new event.Emitter(); return { @@ -33,19 +33,21 @@ export const { registerWindow, getWindows, onDidRegisterWindow, onWillUnregister windows.add(window); - const disposableStore = new DisposableStore(); - disposableStore.add(toDisposable(() => { + const disposables = new DisposableStore(); + disposables.add(toDisposable(() => { windows.delete(window); onDidUnregisterWindow.fire(window); })); - onDidRegisterWindow.fire({ window, disposableStore }); - - disposableStore.add(addDisposableListener(window, 'beforeunload', () => { + disposables.add(addDisposableListener(window, EventType.BEFORE_UNLOAD, () => { onWillUnregisterWindow.fire(window); })); - return disposableStore; + const eventDisposables = new DisposableStore(); + disposables.add(eventDisposables); + onDidRegisterWindow.fire({ window, disposables: eventDisposables }); + + return disposables; }, getWindows(): Iterable { return windows; @@ -1652,7 +1654,7 @@ export class ModifierKeyEmitter extends event.Emitter { metaKey: false }; - this._subscriptions.add(event.Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposableStore }) => this.registerListeners(window, disposableStore), { window, disposableStore: this._subscriptions })); + this._subscriptions.add(event.Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => this.registerListeners(window, disposables), { window, disposables: this._subscriptions })); } private registerListeners(window: Window, disposables: DisposableStore): void { diff --git a/src/vs/base/browser/touch.ts b/src/vs/base/browser/touch.ts index 9b59c8d5b1a..dd74dca3eb4 100644 --- a/src/vs/base/browser/touch.ts +++ b/src/vs/base/browser/touch.ts @@ -91,11 +91,11 @@ export class Gesture extends Disposable { this.handle = null; this._lastSetTapCountTime = 0; - this._register(EventUtils.runAndSubscribe(DomUtils.onDidRegisterWindow, ({ window, disposableStore }) => { - disposableStore.add(DomUtils.addDisposableListener(window.document, 'touchstart', (e: TouchEvent) => this.onTouchStart(e), { passive: false })); - disposableStore.add(DomUtils.addDisposableListener(window.document, 'touchend', (e: TouchEvent) => this.onTouchEnd(e))); - disposableStore.add(DomUtils.addDisposableListener(window.document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e), { passive: false })); - }, { window, disposableStore: this._store })); + this._register(EventUtils.runAndSubscribe(DomUtils.onDidRegisterWindow, ({ window, disposables }) => { + disposables.add(DomUtils.addDisposableListener(window.document, 'touchstart', (e: TouchEvent) => this.onTouchStart(e), { passive: false })); + disposables.add(DomUtils.addDisposableListener(window.document, 'touchend', (e: TouchEvent) => this.onTouchEnd(e))); + disposables.add(DomUtils.addDisposableListener(window.document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e), { passive: false })); + }, { window, disposables: this._store })); } public static addTarget(element: HTMLElement): IDisposable { diff --git a/src/vs/platform/quickinput/browser/quickInputController.ts b/src/vs/platform/quickinput/browser/quickInputController.ts index f0040a3206b..86976df649f 100644 --- a/src/vs/platform/quickinput/browser/quickInputController.ts +++ b/src/vs/platform/quickinput/browser/quickInputController.ts @@ -58,7 +58,7 @@ export class QuickInputController extends Disposable { this.idPrefix = options.idPrefix; this.parentElement = options.container; this.styles = options.styles; - this._register(Event.runAndSubscribe(dom.onDidRegisterWindow, ({ window, disposableStore }) => this.registerKeyModsListeners(window, disposableStore), { window, disposableStore: this._store })); + this._register(Event.runAndSubscribe(dom.onDidRegisterWindow, ({ window, disposables }) => this.registerKeyModsListeners(window, disposables), { window, disposables: this._store })); this._register(dom.onWillUnregisterWindow(window => { if (this.ui && dom.getWindow(this.ui.container) === window) { // The window this quick input is contained in is about to diff --git a/src/vs/workbench/browser/actions/textInputActions.ts b/src/vs/workbench/browser/actions/textInputActions.ts index c52e15228ca..99a82cd7460 100644 --- a/src/vs/workbench/browser/actions/textInputActions.ts +++ b/src/vs/workbench/browser/actions/textInputActions.ts @@ -8,13 +8,14 @@ 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 } from 'vs/base/browser/dom'; +import { EventHelper, addDisposableListener, getActiveDocument } from 'vs/base/browser/dom'; import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { Registry } from 'vs/platform/registry/common/platform'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { isNative } from 'vs/base/common/platform'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; +import { IAuxiliaryWindowService } from 'vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService'; export class TextInputActionsProvider extends Disposable implements IWorkbenchContribution { @@ -23,7 +24,8 @@ export class TextInputActionsProvider extends Disposable implements IWorkbenchCo constructor( @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, @IContextMenuService private readonly contextMenuService: IContextMenuService, - @IClipboardService private readonly clipboardService: IClipboardService + @IClipboardService private readonly clipboardService: IClipboardService, + @IAuxiliaryWindowService private readonly auxiliaryWindowService: IAuxiliaryWindowService ) { super(); @@ -36,18 +38,18 @@ export class TextInputActionsProvider extends Disposable implements IWorkbenchCo this.textInputActions.push( // Undo/Redo - new Action('undo', localize('undo', "Undo"), undefined, true, async () => document.execCommand('undo')), - new Action('redo', localize('redo', "Redo"), undefined, true, async () => document.execCommand('redo')), + new Action('undo', localize('undo', "Undo"), undefined, true, async () => getActiveDocument().execCommand('undo')), + new Action('redo', localize('redo', "Redo"), undefined, true, async () => getActiveDocument().execCommand('redo')), new Separator(), // Cut / Copy / Paste - new Action('editor.action.clipboardCutAction', localize('cut', "Cut"), undefined, true, async () => document.execCommand('cut')), - new Action('editor.action.clipboardCopyAction', localize('copy', "Copy"), undefined, true, async () => document.execCommand('copy')), + new Action('editor.action.clipboardCutAction', localize('cut', "Cut"), undefined, true, async () => getActiveDocument().execCommand('cut')), + new Action('editor.action.clipboardCopyAction', localize('copy', "Copy"), undefined, true, async () => getActiveDocument().execCommand('copy')), new Action('editor.action.clipboardPasteAction', localize('paste', "Paste"), undefined, true, async element => { // Native: paste is supported if (isNative) { - document.execCommand('paste'); + getActiveDocument().execCommand('paste'); } // Web: paste is not supported due to security reasons @@ -69,14 +71,17 @@ export class TextInputActionsProvider extends Disposable implements IWorkbenchCo new Separator(), // Select All - new Action('editor.action.selectAll', localize('selectAll', "Select All"), undefined, true, async () => document.execCommand('selectAll')) + new Action('editor.action.selectAll', localize('selectAll', "Select All"), undefined, true, async () => getActiveDocument().execCommand('selectAll')) ); } private registerListeners(): void { // Context menu support in input/textarea - this.layoutService.container.addEventListener('contextmenu', e => this.onContextMenu(e)); + this._register(addDisposableListener(this.layoutService.container, 'contextmenu', e => this.onContextMenu(e))); + this._register(this.auxiliaryWindowService.onDidOpenAuxiliaryWindow(({ window, disposables }) => { + disposables.add(addDisposableListener(window.container, 'contextmenu', e => this.onContextMenu(e))); + })); } private onContextMenu(e: MouseEvent): void { diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts index 85fcf0f5968..174a0ac7a8c 100644 --- a/src/vs/workbench/browser/contextkeys.ts +++ b/src/vs/workbench/browser/contextkeys.ts @@ -242,7 +242,7 @@ export class WorkbenchContextKeysHandler extends Disposable { this._register(this.editorGroupService.onDidChangeEditorPartOptions(() => this.updateEditorAreaContextKeys())); - this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposableStore }) => disposableStore.add(addDisposableListener(window, EventType.FOCUS_IN, () => this.updateInputContextKeys(window.document), true)), { window, disposableStore: this._store })); + this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => disposables.add(addDisposableListener(window, EventType.FOCUS_IN, () => this.updateInputContextKeys(window.document), true)), { window, disposables: this._store })); this._register(this.contextService.onDidChangeWorkbenchState(() => this.updateWorkbenchStateContextKey())); this._register(this.contextService.onDidChangeWorkspaceFolders(() => { diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts index d3849333ddc..2593f25e9ac 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts @@ -270,10 +270,10 @@ class EditorWordWrapContextKeyTracker extends Disposable implements IWorkbenchCo @IContextKeyService private readonly _contextService: IContextKeyService, ) { super(); - this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposableStore }) => { - disposableStore.add(addDisposableListener(window, 'focus', () => this._update(), true)); - disposableStore.add(addDisposableListener(window, 'blur', () => this._update(), true)); - }, { window, disposableStore: this._store })); + this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => { + disposables.add(addDisposableListener(window, 'focus', () => this._update(), true)); + disposables.add(addDisposableListener(window, 'blur', () => this._update(), true)); + }, { window, disposables: this._store })); this._editorService.onDidActiveEditorChange(() => this._update()); this._canToggleWordWrap = CAN_TOGGLE_WORD_WRAP.bindTo(this._contextService); this._editorWordWrap = EDITOR_WORD_WRAP.bindTo(this._contextService); diff --git a/src/vs/workbench/contrib/contextmenu/browser/contextmenu.contribution.ts b/src/vs/workbench/contrib/contextmenu/browser/contextmenu.contribution.ts index ee27b0aefa9..e903b24dc39 100644 --- a/src/vs/workbench/contrib/contextmenu/browser/contextmenu.contribution.ts +++ b/src/vs/workbench/contrib/contextmenu/browser/contextmenu.contribution.ts @@ -18,7 +18,7 @@ class ContextMenuContribution implements IWorkbenchContribution { @ILayoutService layoutService: ILayoutService, @IContextMenuService contextMenuService: IContextMenuService ) { - const update = (visible: boolean) => layoutService.container.classList.toggle('context-menu-visible', visible); + const update = (visible: boolean) => layoutService.activeContainer.classList.toggle('context-menu-visible', visible); contextMenuService.onDidShowContextMenu(() => update(true), null, this.disposables); contextMenuService.onDidHideContextMenu(() => update(false), null, this.disposables); } diff --git a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts index 01e46db38f5..e6bd5e9b144 100644 --- a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts +++ b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import { Emitter, Event } from 'vs/base/common/event'; import { Dimension, EventHelper, EventType, addDisposableListener, copyAttributes, getActiveWindow, getClientArea, position, registerWindow, size, trackAttributes } from 'vs/base/browser/dom'; -import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +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'; @@ -18,10 +18,17 @@ import Severity from 'vs/base/common/severity'; export const IAuxiliaryWindowService = createDecorator('auxiliaryWindowService'); +export interface IAuxiliaryWindowOpenEvent { + readonly window: IAuxiliaryWindow; + readonly disposables: DisposableStore; +} + export interface IAuxiliaryWindowService { readonly _serviceBrand: undefined; + readonly onDidOpenAuxiliaryWindow: Event; + open(options?: { position?: IRectangle }): Promise; } @@ -38,16 +45,21 @@ export interface IAuxiliaryWindow extends IDisposable { export type AuxiliaryWindow = Window & typeof globalThis; -export class BrowserAuxiliaryWindowService implements IAuxiliaryWindowService { +export class BrowserAuxiliaryWindowService extends Disposable implements IAuxiliaryWindowService { declare readonly _serviceBrand: undefined; private static readonly DEFAULT_SIZE = { width: 800, height: 600 }; + private readonly _onDidOpenAuxiliaryWindow = this._register(new Emitter()); + readonly onDidOpenAuxiliaryWindow = this._onDidOpenAuxiliaryWindow.event; + constructor( @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, @IDialogService private readonly dialogService: IDialogService - ) { } + ) { + super(); + } async open(options?: { position?: IRectangle }): Promise { const disposables = new DisposableStore(); @@ -62,7 +74,7 @@ export class BrowserAuxiliaryWindowService implements IAuxiliaryWindowService { const { container, onWillLayout, onDidClose } = this.create(auxiliaryWindow, disposables); - return { + const result = { window: auxiliaryWindow, container, onWillLayout: onWillLayout.event, @@ -70,6 +82,12 @@ export class BrowserAuxiliaryWindowService implements IAuxiliaryWindowService { layout: () => onWillLayout.fire(getClientArea(container)), dispose: () => disposables.dispose() }; + + const eventDisposables = new DisposableStore(); + disposables.add(eventDisposables); + this._onDidOpenAuxiliaryWindow.fire({ window: result, disposables: eventDisposables }); + + return result; } private async doOpen(options?: { position?: IRectangle }): Promise { @@ -222,6 +240,8 @@ export class BrowserAuxiliaryWindowService implements IAuxiliaryWindowService { onWillLayout.fire(dimension); })); + this._register(addDisposableListener(container, EventType.SCROLL, () => container.scrollTop = 0)); // // Prevent container from scrolling (#55456) + if (isWeb) { disposables.add(addDisposableListener(container, EventType.DROP, e => EventHelper.stop(e, true))); // Prevent default navigation on drop disposables.add(addDisposableListener(container, EventType.WHEEL, e => e.preventDefault(), { passive: false })); // Prevent the back/forward gestures in macOS diff --git a/src/vs/workbench/services/history/browser/historyService.ts b/src/vs/workbench/services/history/browser/historyService.ts index a92bb81906a..75cf8b627f5 100644 --- a/src/vs/workbench/services/history/browser/historyService.ts +++ b/src/vs/workbench/services/history/browser/historyService.ts @@ -34,6 +34,7 @@ import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { ILogService, LogLevel } from 'vs/platform/log/common/log'; +import { IAuxiliaryWindowService } from 'vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService'; export class HistoryService extends Disposable implements IHistoryService { @@ -57,7 +58,8 @@ export class HistoryService extends Disposable implements IHistoryService { @IWorkspacesService private readonly workspacesService: IWorkspacesService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, - @IContextKeyService private readonly contextKeyService: IContextKeyService + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @IAuxiliaryWindowService private readonly auxiliaryWindowService: IAuxiliaryWindowService ) { super(); @@ -111,8 +113,14 @@ export class HistoryService extends Disposable implements IHistoryService { mouseBackForwardSupportListener.clear(); if (this.configurationService.getValue(HistoryService.MOUSE_NAVIGATION_SETTING)) { - mouseBackForwardSupportListener.add(addDisposableListener(this.layoutService.container, EventType.MOUSE_DOWN, e => this.onMouseDownOrUp(e, true))); - mouseBackForwardSupportListener.add(addDisposableListener(this.layoutService.container, EventType.MOUSE_UP, e => this.onMouseDownOrUp(e, false))); + this.doRegisterMouseNavigationListener(this.layoutService.container, mouseBackForwardSupportListener); + + this._register(this.auxiliaryWindowService.onDidOpenAuxiliaryWindow(({ window, disposables }) => { + const listenerDisposables = new DisposableStore(); + mouseBackForwardSupportListener.add(listenerDisposables); + disposables.add(listenerDisposables); + this.doRegisterMouseNavigationListener(window.container, listenerDisposables); + })); } }; @@ -125,6 +133,11 @@ export class HistoryService extends Disposable implements IHistoryService { handleMouseBackForwardSupport(); } + private doRegisterMouseNavigationListener(container: HTMLElement, disposables: DisposableStore): void { + disposables.add(addDisposableListener(container, EventType.MOUSE_DOWN, e => this.onMouseDownOrUp(e, true))); + disposables.add(addDisposableListener(container, EventType.MOUSE_UP, e => this.onMouseDownOrUp(e, false))); + } + private onMouseDownOrUp(event: MouseEvent, isMouseDown: boolean): void { // Support to navigate in history when mouse buttons 4/5 are pressed diff --git a/src/vs/workbench/services/keybinding/browser/keybindingService.ts b/src/vs/workbench/services/keybinding/browser/keybindingService.ts index 742acba161d..ceb42385327 100644 --- a/src/vs/workbench/services/keybinding/browser/keybindingService.ts +++ b/src/vs/workbench/services/keybinding/browser/keybindingService.ts @@ -238,7 +238,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService { this.updateKeybindingsJsonSchema(); this._register(extensionService.onDidRegisterExtensions(() => this.updateKeybindingsJsonSchema())); - this._register(Event.runAndSubscribe(dom.onDidRegisterWindow, ({ window, disposableStore }) => disposableStore.add(this._registerKeyListeners(window)), { window, disposableStore: this._store })); + this._register(Event.runAndSubscribe(dom.onDidRegisterWindow, ({ window, disposables }) => disposables.add(this._registerKeyListeners(window)), { window, disposables: this._store })); this._register(browser.onDidChangeFullscreen(() => { const keyboard: IKeyboard | null = (navigator).keyboard; diff --git a/src/vs/workbench/services/progress/browser/progressService.ts b/src/vs/workbench/services/progress/browser/progressService.ts index 9dbf8a6e216..556d4ebe3af 100644 --- a/src/vs/workbench/services/progress/browser/progressService.ts +++ b/src/vs/workbench/services/progress/browser/progressService.ts @@ -546,7 +546,7 @@ export class ProgressService extends Disposable implements IProgressService { } dialog = new Dialog( - this.layoutService.container, + this.layoutService.activeContainer, message, buttons, { @@ -556,7 +556,7 @@ export class ProgressService extends Disposable implements IProgressService { disableCloseAction: options.sticky, disableDefaultAction: options.sticky, keyEventProcessor: (event: StandardKeyboardEvent) => { - const resolved = this.keybindingService.softDispatch(event, this.layoutService.container); + const resolved = this.keybindingService.softDispatch(event, this.layoutService.activeContainer); if (resolved.kind === ResultKind.KbFound && resolved.commandId) { if (!allowableCommands.includes(resolved.commandId)) { EventHelper.stop(event, true); From f4f0a1dd9540752f51ad96cc1c6dac6091095eb8 Mon Sep 17 00:00:00 2001 From: Andrea Mah <31675041+andreamah@users.noreply.github.com> Date: Mon, 23 Oct 2023 08:46:57 -0700 Subject: [PATCH 016/162] cleanup related to #191731 (#191796) cleanup related to https://github.com/microsoft/vscode/pull/191731 --- .../browser/quickTextSearch/textSearchQuickAccess.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts index 3e23fe5fa73..c14c5fedbea 100644 --- a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts @@ -8,7 +8,7 @@ import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { ResourceSet } from 'vs/base/common/map'; import { basenameOrAuthority, dirname } from 'vs/base/common/resources'; import { ThemeIcon } from 'vs/base/common/themables'; -import { IRange, Range } from 'vs/editor/common/core/range'; +import { IRange } from 'vs/editor/common/core/range'; import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITextEditorSelection } from 'vs/platform/editor/common/editor'; @@ -22,7 +22,7 @@ import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspac import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; import { IViewsService } from 'vs/workbench/common/views'; import { searchDetailsIcon, searchOpenInFileIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; -import { FileMatch, Match, MatchInNotebook, RenderableMatch, SearchModel, searchComparer } from 'vs/workbench/contrib/search/browser/searchModel'; +import { FileMatch, Match, RenderableMatch, SearchModel, searchComparer } from 'vs/workbench/contrib/search/browser/searchModel'; import { SearchView, getEditorSelectionFromMatch } from 'vs/workbench/contrib/search/browser/searchView'; import { IWorkbenchSearchConfiguration, getOutOfWorkspaceEditorResources } from 'vs/workbench/contrib/search/common/search'; import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; @@ -223,8 +223,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider { + private async handleAccept(fileMatch: FileMatch, options: { keyMods?: IKeyMods; selection?: ITextEditorSelection; preserveFocus?: boolean; range?: IRange; forcePinned?: boolean; forceOpenSideBySide?: boolean }): Promise { const editorOptions = { preserveFocus: options.preserveFocus, pinned: options.keyMods?.ctrlCmd || options.forcePinned || this.configuration.openEditorPinned, From 2683aa01ac250fdb042d130e816db93c3b3d3468 Mon Sep 17 00:00:00 2001 From: Tatsunori Uchino Date: Tue, 24 Oct 2023 00:47:46 +0900 Subject: [PATCH 017/162] Add support for `--force-if-includes` to force push more safely (#187932) * Add support for `--force-if-includes` to force push * Change force push failed error message * Separate force push (no with lease) failed error message * Switch to `"markdownDescription"` * Add Git version requirement for config description * Improve error message when safer force push is rejected * Eliminate the option's effect if Git is too old * Minor improvements to community contribution --------- Co-authored-by: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> --- extensions/git/package.json | 5 +++++ extensions/git/package.nls.json | 1 + extensions/git/src/api/git.d.ts | 5 ++++- extensions/git/src/commands.ts | 8 +++++++- extensions/git/src/git.ts | 13 +++++++++++-- 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index b981bbad747..c7f64e2fecd 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -2569,6 +2569,11 @@ "default": true, "description": "%config.useForcePushWithLease%" }, + "git.useForcePushIfIncludes": { + "type": "boolean", + "default": true, + "markdownDescription": "%config.useForcePushIfIncludes%" + }, "git.confirmForcePush": { "type": "boolean", "default": true, diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 8081c900393..20a807be2cb 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -217,6 +217,7 @@ "config.autoStash": "Stash any changes before pulling and restore them after successful pull.", "config.allowForcePush": "Controls whether force push (with or without lease) is enabled.", "config.useForcePushWithLease": "Controls whether force pushing uses the safer force-with-lease variant.", + "config.useForcePushIfIncludes": "Controls whether force pushing uses the safer force-if-includes variant. Note: This setting requires the `#git.useForcePushWithLease#` setting to be enabled, and Git version `2.30.0` or later.", "config.confirmForcePush": "Controls whether to ask for confirmation before force-pushing.", "config.allowNoVerifyCommit": "Controls whether commits without running pre-commit and commit-msg hooks are allowed.", "config.confirmNoVerifyCommit": "Controls whether to ask for confirmation before committing without verification.", diff --git a/extensions/git/src/api/git.d.ts b/extensions/git/src/api/git.d.ts index 191a74e125b..1eb99ff0329 100644 --- a/extensions/git/src/api/git.d.ts +++ b/extensions/git/src/api/git.d.ts @@ -16,7 +16,8 @@ export interface InputBox { export const enum ForcePushMode { Force, - ForceWithLease + ForceWithLease, + ForceWithLeaseIfIncludes, } export const enum RefType { @@ -366,6 +367,8 @@ export const enum GitErrorCodes { StashConflict = 'StashConflict', UnmergedChanges = 'UnmergedChanges', PushRejected = 'PushRejected', + ForcePushWithLeaseRejected = 'ForcePushWithLeaseRejected', + ForcePushWithLeaseIfIncludesRejected = 'ForcePushWithLeaseIfIncludesRejected', RemoteConnectionError = 'RemoteConnectionError', DirtyWorkTree = 'DirtyWorkTree', CantOpenResource = 'CantOpenResource', diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 9b6b93d4078..f6b625a71de 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -2793,7 +2793,9 @@ export class CommandCenter { return; } - forcePushMode = config.get('useForcePushWithLease') === true ? ForcePushMode.ForceWithLease : ForcePushMode.Force; + const useForcePushWithLease = config.get('useForcePushWithLease') === true; + const useForcePushIfIncludes = config.get('useForcePushIfIncludes') === true; + forcePushMode = useForcePushWithLease ? useForcePushIfIncludes ? ForcePushMode.ForceWithLeaseIfIncludes : ForcePushMode.ForceWithLease : ForcePushMode.Force; if (config.get('confirmForcePush')) { const message = l10n.t('You are about to force push your changes, this can be destructive and could inadvertently overwrite changes made by others.\n\nAre you sure to continue?'); @@ -3682,6 +3684,10 @@ export class CommandCenter { case GitErrorCodes.PushRejected: message = l10n.t('Can\'t push refs to remote. Try running "Pull" first to integrate your changes.'); break; + case GitErrorCodes.ForcePushWithLeaseRejected: + case GitErrorCodes.ForcePushWithLeaseIfIncludesRejected: + message = l10n.t('Can\'t force push refs to remote. The tip of the remote-tracking branch has been updated since the last checkout. Try running "Pull" first to pull the latest changes from the remote branch first.'); + break; case GitErrorCodes.Conflict: message = l10n.t('There are merge conflicts. Resolve them before committing.'); type = 'warning'; diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 17e17c8c7f9..421cc14b752 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -1910,8 +1910,11 @@ export class Repository { async push(remote?: string, name?: string, setUpstream: boolean = false, followTags = false, forcePushMode?: ForcePushMode, tags = false): Promise { const args = ['push']; - if (forcePushMode === ForcePushMode.ForceWithLease) { + if (forcePushMode === ForcePushMode.ForceWithLease || forcePushMode === ForcePushMode.ForceWithLeaseIfIncludes) { args.push('--force-with-lease'); + if (forcePushMode === ForcePushMode.ForceWithLeaseIfIncludes && this._git.compareGitVersionTo('2.30') !== -1) { + args.push('--force-if-includes'); + } } else if (forcePushMode === ForcePushMode.Force) { args.push('--force'); } @@ -1940,7 +1943,13 @@ export class Repository { await this.exec(args, { env: { 'GIT_HTTP_USER_AGENT': this.git.userAgent } }); } catch (err) { if (/^error: failed to push some refs to\b/m.test(err.stderr || '')) { - err.gitErrorCode = GitErrorCodes.PushRejected; + if (forcePushMode === ForcePushMode.ForceWithLease && /! \[rejected\].*\(stale info\)/m.test(err.stderr || '')) { + err.gitErrorCode = GitErrorCodes.ForcePushWithLeaseRejected; + } else if (forcePushMode === ForcePushMode.ForceWithLeaseIfIncludes && /! \[rejected\].*\(remote ref updated since checkout\)/m.test(err.stderr || '')) { + err.gitErrorCode = GitErrorCodes.ForcePushWithLeaseIfIncludesRejected; + } else { + err.gitErrorCode = GitErrorCodes.PushRejected; + } } else if (/Permission.*denied/.test(err.stderr || '')) { err.gitErrorCode = GitErrorCodes.PermissionDenied; } else if (/Could not read from remote repository/.test(err.stderr || '')) { From 79c4cbce46757c9a6d092cffc110e29dff1dbee7 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 23 Oct 2023 09:50:37 -0700 Subject: [PATCH 018/162] Revert "Show Location ranges in used refs file label (#196129)" (#196293) This reverts commit ceeec96501b7cd1c813aad36db91c949c1a56739. --- src/vs/workbench/browser/labels.ts | 11 +++-------- .../contrib/chat/browser/chatListRenderer.ts | 4 +--- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 02bc6cc067f..44a200e8fb3 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -22,12 +22,10 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import { Disposable, dispose, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { normalizeDriveLetter } from 'vs/base/common/labels'; -import { IRange } from 'vs/editor/common/core/range'; export interface IResourceLabelProps { resource?: URI | { primary?: URI; secondary?: URI }; name?: string | string[]; - range?: IRange; description?: string; } @@ -64,7 +62,6 @@ export interface IResourceLabelOptions extends IIconLabelValueOptions { export interface IFileLabelOptions extends IResourceLabelOptions { hideLabel?: boolean; hidePath?: boolean; - range?: IRange; } export interface IResourceLabel extends IDisposable { @@ -416,7 +413,7 @@ class ResourceLabelWidget extends IconLabel { description = this.labelService.getUriLabel(dirname(resource), { relative: true }); } - this.setResource({ resource, name, description, range: options?.range }, options); + this.setResource({ resource, name, description }, options); } setResource(label: IResourceLabelProps, options: IResourceLabelOptions = Object.create(null)): void { @@ -549,6 +546,7 @@ class ResourceLabelWidget extends IconLabel { }; const resource = toResource(this.label); + const label = this.label.name; if (this.options?.title !== undefined) { iconLabelOptions.title = this.options.title; @@ -614,10 +612,7 @@ class ResourceLabelWidget extends IconLabel { } } - const rangePart = this.label.range ? `:${this.label.range.startLineNumber}-${this.label.range.endLineNumber}` : ''; - const label = this.label.name ? - this.label.name + rangePart : ''; - this.setLabel(label, this.label.description, iconLabelOptions); + this.setLabel(label || '', this.label.description, iconLabelOptions); this._onDidRender.fire(); diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 979c7ddb7fc..3f7c3001407 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -1143,12 +1143,10 @@ class ContentReferencesListRenderer implements IListRenderer Date: Mon, 23 Oct 2023 10:02:18 -0700 Subject: [PATCH 019/162] Bump rustix from 0.37.19 to 0.37.25 in /cli (#195931) Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.37.19 to 0.37.25. - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Commits](https://github.com/bytecodealliance/rustix/compare/v0.37.19...v0.37.25) --- updated-dependencies: - dependency-name: rustix dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/Cargo.lock b/cli/Cargo.lock index 4152c9b2b67..7b66ef0b266 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -1952,9 +1952,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.37.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" dependencies = [ "bitflags", "errno", From 46566fa29d6d12cfddd2c03377c86db8d2fe70a0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 23 Oct 2023 19:39:55 +0200 Subject: [PATCH 020/162] voice - tweak actions (#196303) --- .../actions/media/voiceChatActions.css | 12 +--- .../actions/voiceChatActions.ts | 69 ++++++++++--------- .../electron-sandbox/chat.contribution.ts | 14 ++-- 3 files changed, 44 insertions(+), 51 deletions(-) diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/media/voiceChatActions.css b/src/vs/workbench/contrib/chat/electron-sandbox/actions/media/voiceChatActions.css index 44a67e2efdf..8a07dfd2727 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/media/voiceChatActions.css +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/media/voiceChatActions.css @@ -12,24 +12,16 @@ } /* - * Clear animation styles when hovering or when reduced motion is enabled. + * Clear animation styles when reduced motion is enabled. */ -.monaco-workbench .interactive-input-part .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled):hover, -.monaco-workbench .inline-chat .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled):hover { - animation: none; -} .monaco-workbench.reduce-motion .interactive-input-part .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled), .monaco-workbench.reduce-motion .inline-chat .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled) { animation: none; } /* - * Replace with "stop" icon when hovering or when reduced motion is enabled. + * Replace with "stop" icon when reduced motion is enabled. */ -.monaco-workbench .interactive-input-part .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled):hover::before, -.monaco-workbench .inline-chat .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled):hover::before { - content: "\ead7"; -} .monaco-workbench.reduce-motion .interactive-input-part .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled)::before, .monaco-workbench.reduce-motion .inline-chat .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled)::before { content: "\ead7"; diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts index 682280ee4c8..83744d7a9b0 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts @@ -445,9 +445,10 @@ export class StartVoiceChatAction extends Action2 { super({ id: StartVoiceChatAction.ID, title: { - value: localize('workbench.action.chat.startVoiceChat', "Chat by Voice"), - original: 'Chat by Voice' + value: localize('workbench.action.chat.startVoiceChat.label', "Use Microphone"), + original: 'Use Microphone' }, + category: CHAT_CATEGORY, icon: Codicon.mic, precondition: ContextKeyExpr.and(HasSpeechProvider, CONTEXT_VOICE_CHAT_GETTING_READY.negate()), menu: [{ @@ -489,16 +490,16 @@ export class StartVoiceChatAction extends Action2 { } } -export class StopVoiceChatAction extends Action2 { +export class StopListeningAction extends Action2 { - static readonly ID = 'workbench.action.chat.stopVoiceChat'; + static readonly ID = 'workbench.action.chat.stopListening'; constructor() { super({ - id: StopVoiceChatAction.ID, + id: StopListeningAction.ID, title: { - value: localize('workbench.action.chat.stopVoiceChat.label', "Stop Voice Chat"), - original: 'Stop Voice Chat' + value: localize('workbench.action.chat.stopListening.label', "Stop Listening"), + original: 'Stop Listening' }, category: CHAT_CATEGORY, f1: true, @@ -516,16 +517,16 @@ export class StopVoiceChatAction extends Action2 { } } -export class StopVoiceChatInChatViewAction extends Action2 { +export class StopListeningInChatViewAction extends Action2 { - static readonly ID = 'workbench.action.chat.stopVoiceChatInChatView'; + static readonly ID = 'workbench.action.chat.stopListeningInChatView'; constructor() { super({ - id: StopVoiceChatInChatViewAction.ID, + id: StopListeningInChatViewAction.ID, title: { - value: localize('workbench.action.chat.stopVoiceChatInChatView.label', "Stop Voice Chat (Chat View)"), - original: 'Stop Voice Chat (Chat View)' + value: localize('workbench.action.chat.stopListeningInChatView.label', "Stop Listening"), + original: 'Stop Listening' }, category: CHAT_CATEGORY, keybinding: { @@ -549,16 +550,16 @@ export class StopVoiceChatInChatViewAction extends Action2 { } } -export class StopVoiceChatInChatEditorAction extends Action2 { +export class StopListeningInChatEditorAction extends Action2 { - static readonly ID = 'workbench.action.chat.stopVoiceChatInChatEditor'; + static readonly ID = 'workbench.action.chat.stopListeningInChatEditor'; constructor() { super({ - id: StopVoiceChatInChatEditorAction.ID, + id: StopListeningInChatEditorAction.ID, title: { - value: localize('workbench.action.chat.stopVoiceChatInChatEditor.label', "Stop Voice Chat (Chat Editor)"), - original: 'Stop Voice Chat (Chat Editor)' + value: localize('workbench.action.chat.stopListeningInChatEditor.label', "Stop Listening"), + original: 'Stop Listening' }, category: CHAT_CATEGORY, keybinding: { @@ -582,16 +583,16 @@ export class StopVoiceChatInChatEditorAction extends Action2 { } } -export class StopQuickVoiceChatAction extends Action2 { +export class StopListeningInQuickChatAction extends Action2 { - static readonly ID = 'workbench.action.chat.stopQuickVoiceChat'; + static readonly ID = 'workbench.action.chat.stopListeningInQuickChat'; constructor() { super({ - id: StopQuickVoiceChatAction.ID, + id: StopListeningInQuickChatAction.ID, title: { - value: localize('workbench.action.chat.stopQuickVoiceChat.label', "Stop Voice Chat (Quick Chat)"), - original: 'Stop Voice Chat (Quick Chat)' + value: localize('workbench.action.chat.stopListeningInQuickChat.label', "Stop Listening"), + original: 'Stop Listening' }, category: CHAT_CATEGORY, keybinding: { @@ -615,16 +616,16 @@ export class StopQuickVoiceChatAction extends Action2 { } } -export class StopInlineVoiceChatAction extends Action2 { +export class StopListeningInInlineChatAction extends Action2 { - static readonly ID = 'workbench.action.chat.stopInlineVoiceChat'; + static readonly ID = 'workbench.action.chat.stopListeningInInlineChat'; constructor() { super({ - id: StopInlineVoiceChatAction.ID, + id: StopListeningInInlineChatAction.ID, title: { - value: localize('workbench.action.chat.stopInlineVoiceChat.label', "Stop Voice Chat (Inline Editor)"), - original: 'Stop Voice Chat (Inline Editor)' + value: localize('workbench.action.chat.stopListeningInInlineChat.label', "Stop Listening"), + original: 'Stop Listening' }, category: CHAT_CATEGORY, keybinding: { @@ -648,16 +649,16 @@ export class StopInlineVoiceChatAction extends Action2 { } } -export class StopVoiceChatAndSubmitAction extends Action2 { +export class StopListeningAndSubmitAction extends Action2 { - static readonly ID = 'workbench.action.chat.stopVoiceChatAndSubmit'; + static readonly ID = 'workbench.action.chat.stopListeningAndSubmit'; constructor() { super({ - id: StopVoiceChatAndSubmitAction.ID, + id: StopListeningAndSubmitAction.ID, title: { - value: localize('workbench.action.chat.stopAndAcceptVoiceChat.label', "Stop Voice Chat and Submit"), - original: 'Stop Voice Chat and Submit' + value: localize('workbench.action.chat.stopListeningAndSubmit.label', "Stop Listening and Submit"), + original: 'Stop Listening and Submit' }, category: CHAT_CATEGORY, f1: true, @@ -683,8 +684,8 @@ registerThemingParticipant((theme, collector) => { // Show a "microphone" icon when recording is in progress that glows via outline. collector.addRule(` - .monaco-workbench:not(.reduce-motion) .interactive-input-part .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled):not(:hover), - .monaco-workbench:not(.reduce-motion) .inline-chat .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled):not(:hover) { + .monaco-workbench:not(.reduce-motion) .interactive-input-part .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled), + .monaco-workbench:not(.reduce-motion) .inline-chat .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled) { color: ${activeRecordingColor}; outline: 1px solid ${activeRecordingColor}; outline-offset: -1px; diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts b/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts index 4709e5aa354..9ba5430737e 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/chat.contribution.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { InlineVoiceChatAction, QuickVoiceChatAction, StartVoiceChatAction, StopInlineVoiceChatAction, StopQuickVoiceChatAction, StopVoiceChatAction, StopVoiceChatAndSubmitAction, StopVoiceChatInChatEditorAction, StopVoiceChatInChatViewAction, VoiceChatInChatViewAction } from 'vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions'; +import { InlineVoiceChatAction, QuickVoiceChatAction, StartVoiceChatAction, StopListeningInInlineChatAction, StopListeningInQuickChatAction, StopListeningInChatEditorAction, StopListeningInChatViewAction, VoiceChatInChatViewAction, StopListeningAction, StopListeningAndSubmitAction } from 'vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions'; import { registerAction2 } from 'vs/platform/actions/common/actions'; registerAction2(StartVoiceChatAction); @@ -12,11 +12,11 @@ registerAction2(VoiceChatInChatViewAction); registerAction2(QuickVoiceChatAction); registerAction2(InlineVoiceChatAction); -registerAction2(StopVoiceChatAction); -registerAction2(StopVoiceChatAndSubmitAction); +registerAction2(StopListeningAction); +registerAction2(StopListeningAndSubmitAction); -registerAction2(StopVoiceChatInChatViewAction); -registerAction2(StopVoiceChatInChatEditorAction); -registerAction2(StopQuickVoiceChatAction); -registerAction2(StopInlineVoiceChatAction); +registerAction2(StopListeningInChatViewAction); +registerAction2(StopListeningInChatEditorAction); +registerAction2(StopListeningInQuickChatAction); +registerAction2(StopListeningInInlineChatAction); From ad29091f39405a6a0e7898dccc306f34bbd74e11 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 23 Oct 2023 10:59:05 -0700 Subject: [PATCH 021/162] fix: don't wait for stdin pump to end before propagating process exit (#196306) --- cli/src/tunnels/control_server.rs | 46 ++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/cli/src/tunnels/control_server.rs b/cli/src/tunnels/control_server.rs index 48c11fc1b35..a33b59db32a 100644 --- a/cli/src/tunnels/control_server.rs +++ b/cli/src/tunnels/control_server.rs @@ -1153,18 +1153,19 @@ where let mut p = p.spawn().map_err(CodeError::ProcessSpawnFailed)?; - let futs = FuturesUnordered::new(); + let block_futs = FuturesUnordered::new(); + let poll_futs = FuturesUnordered::new(); if let (Some(mut a), Some(mut b)) = (p.stdout.take(), stdout) { - futs.push(async move { tokio::io::copy(&mut a, &mut b).await }.boxed()); + block_futs.push(async move { tokio::io::copy(&mut a, &mut b).await }.boxed()); } if let (Some(mut a), Some(mut b)) = (p.stderr.take(), stderr) { - futs.push(async move { tokio::io::copy(&mut a, &mut b).await }.boxed()); + block_futs.push(async move { tokio::io::copy(&mut a, &mut b).await }.boxed()); } if let (Some(mut b), Some(mut a)) = (p.stdin.take(), stdin) { - futs.push(async move { tokio::io::copy(&mut a, &mut b).await }.boxed()); + poll_futs.push(async move { tokio::io::copy(&mut a, &mut b).await }.boxed()); } - wait_for_process_exit(log, ¶ms.command, p, futs).await + wait_for_process_exit(log, ¶ms.command, p, block_futs, poll_futs).await } async fn handle_spawn_cli( @@ -1212,23 +1213,42 @@ async fn handle_spawn_cli( } debug!(log, "cli authenticated, attaching stdio"); - let futs = FuturesUnordered::new(); - futs.push(async move { tokio::io::copy(&mut protocol_in, &mut stdin).await }.boxed()); - futs.push(async move { tokio::io::copy(&mut stderr, &mut protocol_out).await }.boxed()); - futs.push(async move { log_pump.await.unwrap() }.boxed()); + let block_futs = FuturesUnordered::new(); + let poll_futs = FuturesUnordered::new(); + poll_futs.push(async move { tokio::io::copy(&mut protocol_in, &mut stdin).await }.boxed()); + block_futs.push(async move { tokio::io::copy(&mut stderr, &mut protocol_out).await }.boxed()); + block_futs.push(async move { log_pump.await.unwrap() }.boxed()); - wait_for_process_exit(log, ¶ms.command, p, futs).await + wait_for_process_exit(log, ¶ms.command, p, block_futs, poll_futs).await } type TokioCopyFuture = dyn futures::Future> + Send; +async fn get_joined_result( + mut process: tokio::process::Child, + block_futs: FuturesUnordered>>, +) -> Result { + let (_, r) = tokio::join!(futures::future::join_all(block_futs), process.wait()); + r +} + +/// Wait for the process to exit and sends the spawn result. Waits until the +/// `block_futs` and the process have exited, and polls the `poll_futs` while +/// doing so. async fn wait_for_process_exit( log: &log::Logger, command: &str, - mut process: tokio::process::Child, - futs: FuturesUnordered>>, + process: tokio::process::Child, + block_futs: FuturesUnordered>>, + poll_futs: FuturesUnordered>>, ) -> Result { - let (_, r) = tokio::join!(futures::future::join_all(futs), process.wait()); + let joined = get_joined_result(process, block_futs); + pin!(joined); + + let r = tokio::select! { + _ = futures::future::join_all(poll_futs) => joined.await, + r = &mut joined => r, + }; let r = match r { Ok(e) => SpawnResult { From eae846ae532fab054775f93c6d67569e760712ef Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 23 Oct 2023 11:13:44 -0700 Subject: [PATCH 022/162] Fix quick fix bg in editor Fixes #195809 --- .../quickFix/browser/media/terminalQuickFix.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/media/terminalQuickFix.css b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/media/terminalQuickFix.css index c907928d5fb..e549278d8f0 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/media/terminalQuickFix.css +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/media/terminalQuickFix.css @@ -12,6 +12,10 @@ background-color: var(--vscode-terminal-background, var(--vscode-panel-background)); } +.monaco-workbench .editor-instance .terminal .terminal-command-decoration.quick-fix { + background-color: var(--vscode-terminal-background, var(--vscode-editor-background)); +} + .monaco-workbench .terminal .terminal-command-decoration.quick-fix.explainOnly { color: var(--vscode-editorLightBulbAutoFix-foreground) !important; } From c51b33b2244077107b8b1cd120c6ab952cd99fc4 Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Mon, 23 Oct 2023 20:25:09 +0200 Subject: [PATCH 023/162] fix: memory leak in menu (#196302) * fix: memory leak in menu * :lipstick: --------- Co-authored-by: Benjamin Pasero --- src/vs/base/browser/ui/menu/menu.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index 93eb168121e..64c1daf2838 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -85,7 +85,6 @@ interface ISubMenuData { export class Menu extends ActionBar { private mnemonics: Map>; - private readonly menuDisposables: DisposableStore; private scrollableElement: DomScrollableElement; private menuElement: HTMLElement; static globalStyleSheet: HTMLStyleElement; @@ -113,23 +112,21 @@ export class Menu extends ActionBar { this.actionsList.tabIndex = 0; - this.menuDisposables = this._register(new DisposableStore()); - this.initializeOrUpdateStyleSheet(container, menuStyles); this._register(Gesture.addTarget(menuElement)); - addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => { + this._register(addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => { const event = new StandardKeyboardEvent(e); // Stop tab navigation of menus if (event.equals(KeyCode.Tab)) { e.preventDefault(); } - }); + })); if (options.enableMnemonics) { - this.menuDisposables.add(addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => { + this._register(addDisposableListener(menuElement, EventType.KEY_DOWN, (e) => { const key = e.key.toLocaleLowerCase(); if (this.mnemonics.has(key)) { EventHelper.stop(e, true); From 49b6fa9a20c1fbbfb4db343c63b68d0941d3d69b Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 23 Oct 2023 11:54:02 -0700 Subject: [PATCH 024/162] Show range for chat references, via IconLabel suffix (#196311) Bring back #196293 without breakage in #196252 --- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 23 ++++++++++++++++--- .../base/browser/ui/iconLabel/iconlabel.css | 5 ++++ src/vs/workbench/browser/labels.ts | 14 ++++++++--- .../contrib/chat/browser/chatListRenderer.ts | 1 + 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index 6fa5b4551a2..0bb344bfbb6 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -23,6 +23,7 @@ export interface IIconLabelCreationOptions { export interface IIconLabelValueOptions { title?: string | ITooltipMarkdownString; descriptionTitle?: string; + suffix?: string; hideIcon?: boolean; extraClasses?: readonly string[]; italic?: boolean; @@ -85,9 +86,11 @@ export class IconLabel extends Disposable { private readonly creationOptions?: IIconLabelCreationOptions; private readonly domNode: FastLabelNode; + private readonly nameContainer: HTMLElement; private readonly nameNode: Label | LabelWithHighlights; private descriptionNode: FastLabelNode | HighlightedLabel | undefined; + private suffixNode: FastLabelNode | undefined; private readonly labelContainer: HTMLElement; @@ -102,12 +105,12 @@ export class IconLabel extends Disposable { this.labelContainer = dom.append(this.domNode.element, dom.$('.monaco-icon-label-container')); - const nameContainer = dom.append(this.labelContainer, dom.$('span.monaco-icon-name-container')); + this.nameContainer = dom.append(this.labelContainer, dom.$('span.monaco-icon-name-container')); if (options?.supportHighlights || options?.supportIcons) { - this.nameNode = new LabelWithHighlights(nameContainer, !!options.supportIcons); + this.nameNode = new LabelWithHighlights(this.nameContainer, !!options.supportIcons); } else { - this.nameNode = new Label(nameContainer); + this.nameNode = new Label(this.nameContainer); } this.hoverDelegate = options?.hoverDelegate; @@ -164,6 +167,11 @@ export class IconLabel extends Disposable { descriptionNode.empty = !description; } } + + if (options?.suffix || this.suffixNode) { + const suffixNode = this.getOrCreateSuffixNode(); + suffixNode.textContent = options?.suffix ?? ''; + } } private setupHover(htmlElement: HTMLElement, tooltip: string | ITooltipMarkdownString | undefined): void { @@ -196,6 +204,15 @@ export class IconLabel extends Disposable { this.customHovers.clear(); } + private getOrCreateSuffixNode() { + if (!this.suffixNode) { + const suffixContainer = this._register(new FastLabelNode(dom.after(this.nameContainer, dom.$('span.monaco-icon-suffix-container')))); + this.suffixNode = this._register(new FastLabelNode(dom.append(suffixContainer.element, dom.$('span.label-suffix')))); + } + + return this.suffixNode; + } + private getOrCreateDescriptionNode() { if (!this.descriptionNode) { const descriptionContainer = this._register(new FastLabelNode(dom.append(this.labelContainer, dom.$('span.monaco-icon-description-container')))); diff --git a/src/vs/base/browser/ui/iconLabel/iconlabel.css b/src/vs/base/browser/ui/iconLabel/iconlabel.css index ab4c0e131eb..c847aecee2f 100644 --- a/src/vs/base/browser/ui/iconLabel/iconlabel.css +++ b/src/vs/base/browser/ui/iconLabel/iconlabel.css @@ -51,6 +51,11 @@ opacity: 0.5; } +.monaco-icon-label>.monaco-icon-label-container>.monaco-icon-suffix-container>.label-suffix { + opacity: .7; + white-space: pre; +} + .monaco-icon-label > .monaco-icon-label-container > .monaco-icon-description-container > .label-description { opacity: .7; margin-left: 0.5em; diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 44a200e8fb3..7fe92930a83 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -22,10 +22,12 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import { Disposable, dispose, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { normalizeDriveLetter } from 'vs/base/common/labels'; +import { IRange } from 'vs/editor/common/core/range'; export interface IResourceLabelProps { resource?: URI | { primary?: URI; secondary?: URI }; name?: string | string[]; + range?: IRange; description?: string; } @@ -62,6 +64,7 @@ export interface IResourceLabelOptions extends IIconLabelValueOptions { export interface IFileLabelOptions extends IResourceLabelOptions { hideLabel?: boolean; hidePath?: boolean; + range?: IRange; } export interface IResourceLabel extends IDisposable { @@ -413,7 +416,7 @@ class ResourceLabelWidget extends IconLabel { description = this.labelService.getUriLabel(dirname(resource), { relative: true }); } - this.setResource({ resource, name, description }, options); + this.setResource({ resource, name, description, range: options?.range }, options); } setResource(label: IResourceLabelProps, options: IResourceLabelOptions = Object.create(null)): void { @@ -546,7 +549,6 @@ class ResourceLabelWidget extends IconLabel { }; const resource = toResource(this.label); - const label = this.label.name; if (this.options?.title !== undefined) { iconLabelOptions.title = this.options.title; @@ -612,7 +614,13 @@ class ResourceLabelWidget extends IconLabel { } } - this.setLabel(label || '', this.label.description, iconLabelOptions); + if (this.label.range) { + iconLabelOptions.suffix = this.label.range.startLineNumber !== this.label.range.endLineNumber ? + `:${this.label.range.startLineNumber}-${this.label.range.endLineNumber}` : + `:${this.label.range.startLineNumber}`; + } + + this.setLabel(this.label.name ?? '', this.label.description, iconLabelOptions); this._onDidRender.fire(); diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 3f7c3001407..01277fbcc17 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -1147,6 +1147,7 @@ class ContentReferencesListRenderer implements IListRenderer Date: Mon, 23 Oct 2023 21:48:16 +0200 Subject: [PATCH 025/162] fix #196272 (#196315) * fix #196272 * fix reload --- .../configuration/browser/configuration.ts | 24 +++++++++++-------- .../browser/configurationService.ts | 6 ++--- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/services/configuration/browser/configuration.ts b/src/vs/workbench/services/configuration/browser/configuration.ts index ab82b7e543a..4630065bccf 100644 --- a/src/vs/workbench/services/configuration/browser/configuration.ts +++ b/src/vs/workbench/services/configuration/browser/configuration.ts @@ -179,10 +179,14 @@ export class UserConfiguration extends Disposable { this.settingsResource = settingsResource; this.tasksResource = tasksResource; this.configurationParseOptions = configurationParseOptions; + return this.doReset(); + } + + private async doReset(settingsConfiguration?: ConfigurationModel): Promise { const folder = this.uriIdentityService.extUri.dirname(this.settingsResource); const standAloneConfigurationResources: [string, URI][] = this.tasksResource ? [[TASKS_CONFIGURATION_KEY, this.tasksResource]] : []; const fileServiceBasedConfiguration = new FileServiceBasedConfiguration(folder.toString(), this.settingsResource, standAloneConfigurationResources, this.configurationParseOptions, this.fileService, this.uriIdentityService, this.logService); - const configurationModel = await fileServiceBasedConfiguration.loadConfiguration(); + const configurationModel = await fileServiceBasedConfiguration.loadConfiguration(settingsConfiguration); this.userConfiguration.value = fileServiceBasedConfiguration; // Check for value because userConfiguration might have been disposed. @@ -197,11 +201,11 @@ export class UserConfiguration extends Disposable { return this.userConfiguration.value!.loadConfiguration(); } - async reload(): Promise { + async reload(settingsConfiguration?: ConfigurationModel): Promise { if (this.hasTasksLoaded) { return this.userConfiguration.value!.loadConfiguration(); } - return this.reset(this.settingsResource, this.tasksResource, this.configurationParseOptions); + return this.doReset(settingsConfiguration); } reparse(parseOptions?: Partial): ConfigurationModel { @@ -254,7 +258,7 @@ class FileServiceBasedConfiguration extends Disposable { ), () => undefined, 100)(() => this._onDidChange.fire())); } - async resolveContents(): Promise<[string | undefined, [string, string | undefined][]]> { + async resolveContents(donotResolveSettings?: boolean): Promise<[string | undefined, [string, string | undefined][]]> { const resolveContents = async (resources: URI[]): Promise<(string | undefined)[]> => { return Promise.all(resources.map(async resource => { @@ -273,16 +277,16 @@ class FileServiceBasedConfiguration extends Disposable { }; const [[settingsContent], standAloneConfigurationContents] = await Promise.all([ - resolveContents([this.settingsResource]), + donotResolveSettings ? Promise.resolve([undefined]) : resolveContents([this.settingsResource]), resolveContents(this.standAloneConfigurationResources.map(([, resource]) => resource)), ]); return [settingsContent, standAloneConfigurationContents.map((content, index) => ([this.standAloneConfigurationResources[index][0], content]))]; } - async loadConfiguration(): Promise { + async loadConfiguration(settingsConfiguration?: ConfigurationModel): Promise { - const [settingsContent, standAloneConfigurationContents] = await this.resolveContents(); + const [settingsContent, standAloneConfigurationContents] = await this.resolveContents(!!settingsConfiguration); // reset this._standAloneConfigurations = []; @@ -302,7 +306,7 @@ class FileServiceBasedConfiguration extends Disposable { } // Consolidate (support *.json files in the workspace settings folder) - this.consolidate(); + this.consolidate(settingsConfiguration); return this._cache; } @@ -321,8 +325,8 @@ class FileServiceBasedConfiguration extends Disposable { return this._cache; } - private consolidate(): void { - this._cache = this._folderSettingsModelParser.configurationModel.merge(...this._standAloneConfigurations); + private consolidate(settingsConfiguration?: ConfigurationModel): void { + this._cache = (settingsConfiguration ?? this._folderSettingsModelParser.configurationModel).merge(...this._standAloneConfigurations); } private handleFileChangesEvent(event: FileChangesEvent): boolean { diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index d2c05378c9c..ef613d7ef76 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -576,7 +576,7 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat if (!this.localUserConfiguration.hasTasksLoaded) { // Reload local user configuration again to load user tasks - this._register(runWhenIdle(() => this.reloadLocalUserConfiguration())); + this._register(runWhenIdle(() => this.reloadLocalUserConfiguration(false, this._configuration.localUserConfiguration))); } } @@ -645,8 +645,8 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat return { local, remote }; } - async reloadLocalUserConfiguration(donotTrigger?: boolean): Promise { - const model = await this.localUserConfiguration.reload(); + async reloadLocalUserConfiguration(donotTrigger?: boolean, settingsConfiguration?: ConfigurationModel): Promise { + const model = await this.localUserConfiguration.reload(settingsConfiguration); if (!donotTrigger) { this.onLocalUserConfigurationChanged(model); } From 8887abd9fc30a5fa5d5919a0581ab63732df6155 Mon Sep 17 00:00:00 2001 From: Justin Chen <54879025+justschen@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:09:33 -0700 Subject: [PATCH 026/162] Allow additional extension data from Issue Reporter API (#196103) * issue-reporter-main merge into branch (#13) * laying the groundwork for issue reporter API * working version 1 * added additional support, checkbox * smol change with disabling edits and cleanup * added blocker, timeout of 5 seconds, instead of rejecting we return * added working template data as well * removed test code * cleaning up commit * working with injecting template and allowing editing * cleanup pass 1 * added progress bar and code cleanup * cleanup and adding docs * added default data in issuereporter test * extension data hidden by default, better loading indication * cleanup * added codicons * added codicon styling, removed progress bar: * code cleanup * better preview button handling * cleaning up part 4 Co-authored-by: Tyler James Leonhardt --------- Co-authored-by: Tyler James Leonhardt --- .../issue/issueReporterMain.ts | 16 +-- .../issue/issueReporterModel.ts | 13 ++ .../issue/issueReporterPage.ts | 13 ++ .../issue/issueReporterService.ts | 124 ++++++++++++++++-- .../issue/media/issueReporter.css | 5 + .../issue/testReporterModel.test.ts | 1 + src/vs/platform/issue/common/issue.ts | 5 + .../issue/electron-main/issueMainService.ts | 65 +++++++-- .../api/browser/mainThreadIssueReporter.ts | 20 ++- .../workbench/api/common/extHost.api.impl.ts | 4 + .../workbench/api/common/extHost.protocol.ts | 4 + .../api/common/extHostIssueReporter.ts | 49 ++++++- .../issue/common/issue.contribution.ts | 1 + .../services/issue/browser/issueService.ts | 22 ++-- .../workbench/services/issue/common/issue.ts | 6 + .../issue/electron-sandbox/issueService.ts | 67 +++++++--- .../vscode.proposed.handleIssueUri.d.ts | 26 ++++ 17 files changed, 391 insertions(+), 50 deletions(-) diff --git a/src/vs/code/electron-sandbox/issue/issueReporterMain.ts b/src/vs/code/electron-sandbox/issue/issueReporterMain.ts index 44263745539..3d7ef0fa47c 100644 --- a/src/vs/code/electron-sandbox/issue/issueReporterMain.ts +++ b/src/vs/code/electron-sandbox/issue/issueReporterMain.ts @@ -3,22 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import 'vs/css!./media/issueReporter'; -import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded import { safeInnerHtml } from 'vs/base/browser/dom'; +import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded import { isLinux, isWindows } from 'vs/base/common/platform'; import BaseHtml from 'vs/code/electron-sandbox/issue/issueReporterPage'; +import 'vs/css!./media/issueReporter'; +import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions'; +import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { IMainProcessService } from 'vs/platform/ipc/common/mainProcessService'; import { ElectronIPCMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; +import { registerMainProcessRemoteService } from 'vs/platform/ipc/electron-sandbox/services'; import { IIssueMainService, IssueReporterWindowConfiguration } from 'vs/platform/issue/common/issue'; import { INativeHostService } from 'vs/platform/native/common/native'; import { NativeHostService } from 'vs/platform/native/electron-sandbox/nativeHostService'; -import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { IMainProcessService } from 'vs/platform/ipc/common/mainProcessService'; import { IssueReporter } from './issueReporterService'; -import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; -import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions'; -import { registerMainProcessRemoteService } from 'vs/platform/ipc/electron-sandbox/services'; export function startup(configuration: IssueReporterWindowConfiguration) { const platformClass = isWindows ? 'windows' : isLinux ? 'linux' : 'mac'; diff --git a/src/vs/code/electron-sandbox/issue/issueReporterModel.ts b/src/vs/code/electron-sandbox/issue/issueReporterModel.ts index d72d5fcb24d..794d371126a 100644 --- a/src/vs/code/electron-sandbox/issue/issueReporterModel.ts +++ b/src/vs/code/electron-sandbox/issue/issueReporterModel.ts @@ -9,6 +9,7 @@ import { ISettingSearchResult, IssueReporterExtensionData, IssueType } from 'vs/ export interface IssueReporterData { issueType: IssueType; issueDescription?: string; + extensionData?: string; versionInfo?: any; systemInfo?: SystemInfo; @@ -20,6 +21,7 @@ export interface IssueReporterData { includeProcessInfo: boolean; includeExtensions: boolean; includeExperiments: boolean; + includeExtensionData: boolean; numberOfThemeExtesions?: number; allExtensions: IssueReporterExtensionData[]; @@ -47,6 +49,7 @@ export class IssueReporterModel { includeProcessInfo: true, includeExtensions: true, includeExperiments: true, + includeExtensionData: true, allExtensions: [] }; @@ -120,6 +123,12 @@ ${this.getInfos()} private getInfos(): string { let info = ''; + if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) { + if (!this._data.fileOnMarketplace && this._data.includeExtensionData && this._data.extensionData) { + info += this.getExtensionData(); + } + } + if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) { if (!this._data.fileOnMarketplace && this._data.includeSystemInfo && this._data.systemInfo) { info += this.generateSystemInfoMd(); @@ -152,6 +161,10 @@ ${this.getInfos()} return info; } + private getExtensionData(): string { + return this._data.extensionData ?? ''; + } + private generateSystemInfoMd(): string { let md = `
System Info diff --git a/src/vs/code/electron-sandbox/issue/issueReporterPage.ts b/src/vs/code/electron-sandbox/issue/issueReporterPage.ts index 0eedb215f1c..8f602f8b900 100644 --- a/src/vs/code/electron-sandbox/issue/issueReporterPage.ts +++ b/src/vs/code/electron-sandbox/issue/issueReporterPage.ts @@ -11,6 +11,7 @@ const sendProcessInfoLabel = escape(localize('sendProcessInfo', "Include my curr const sendWorkspaceInfoLabel = escape(localize('sendWorkspaceInfo', "Include my workspace metadata")); const sendExtensionsLabel = escape(localize('sendExtensions', "Include my enabled extensions")); const sendExperimentsLabel = escape(localize('sendExperiments', "Include A/B experiment info")); +const sendExtensionData = escape(localize('sendExtensionData', "Include Additional Extension info")); const reviewGuidanceLabel = localize( // intentionally not escaped because of its embedded tags { key: 'reviewGuidanceLabel', @@ -85,6 +86,18 @@ export default (): string => `
+
+ + + +
+
- +
+				
+			
diff --git a/src/vs/code/electron-sandbox/issue/issueReporterService.ts b/src/vs/code/electron-sandbox/issue/issueReporterService.ts index 2795b676cb4..afb7a654c09 100644 --- a/src/vs/code/electron-sandbox/issue/issueReporterService.ts +++ b/src/vs/code/electron-sandbox/issue/issueReporterService.ts @@ -257,6 +257,7 @@ export class IssueReporter extends Disposable { const data = await this.issueMainService.$getIssueReporterData(extension.id); extension.extensionData = data; this.receivedExtensionData = true; + this.issueReporterModel.update({ extensionData: data }); return data; } catch (e) { extension.hasIssueDataProviders = false; @@ -785,11 +786,10 @@ export class IssueReporter extends Disposable { if (fileOnExtension && selectedExtension?.hasIssueDataProviders) { const data = this.getExtensionData(); if (data) { - (extensionDataTextArea as HTMLTextAreaElement).value = data.toString(); + (extensionDataTextArea as HTMLElement).innerText = data.toString(); } (extensionDataTextArea as HTMLTextAreaElement).readOnly = true; show(extensionDataBlock); - show(extensionDataTextArea); } if (issueType === IssueType.Bug) { @@ -1136,18 +1136,24 @@ export class IssueReporter extends Disposable { } else if (matches[0].hasIssueDataProviders) { const template = await this.getIssueTemplateFromExtension(matches[0]); const descriptionTextArea = this.getElementById('description')!; - const fullTextArea = (descriptionTextArea as HTMLTextAreaElement).value += template; - this.issueReporterModel.update({ issueDescription: fullTextArea }); - + const descriptionText = (descriptionTextArea as HTMLTextAreaElement).value; + if (descriptionText === '' || !descriptionText.includes(template)) { + const fullTextArea = descriptionText + (descriptionText === '' ? '' : '\n') + template; + (descriptionTextArea as HTMLTextAreaElement).value = fullTextArea; + this.issueReporterModel.update({ issueDescription: fullTextArea }); + } const extensionDataBlock = document.querySelector('.block-extension-data')!; show(extensionDataBlock); // Start loading for extension data. - this.setLoading(); + const iconElement = document.createElement('span'); + iconElement.classList.add(...ThemeIcon.asClassNameArray(Codicon.loading), 'codicon-modifier-spin'); + this.setLoading(iconElement); await this.getIssueDataFromExtension(matches[0]); - this.removeLoading(); + this.removeLoading(iconElement); } else { this.validateSelectedExtension(); + this.issueReporterModel.update({ extensionData: undefined }); const title = (this.getElementById('issue-title')).value; this.searchExtensionIssues(title); } @@ -1187,8 +1193,9 @@ export class IssueReporter extends Disposable { } } - private setLoading() { + private setLoading(element: HTMLElement) { // Show loading + this.receivedExtensionData = false; this.updatePreviewButtonState(); const extensionDataCaption = this.getElementById('extension-id')!; @@ -1199,13 +1206,10 @@ export class IssueReporter extends Disposable { const showLoading = this.getElementById('ext-loading')!; show(showLoading); - - const iconElement = document.createElement('span'); - iconElement.classList.add(...ThemeIcon.asClassNameArray(Codicon.loading), 'codicon-modifier-spin'); - showLoading.append(iconElement); + showLoading.append(element); } - private removeLoading() { + private removeLoading(element: HTMLElement) { this.updatePreviewButtonState(); const extensionDataCaption = this.getElementById('extension-id')!; @@ -1216,6 +1220,7 @@ export class IssueReporter extends Disposable { const hideLoading = this.getElementById('ext-loading')!; hide(hideLoading); + hideLoading.removeChild(element); } private setExtensionValidationMessage(): void { From d0bff74298f650761a1e4863fc224907a2b0544a Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 25 Oct 2023 16:20:37 -0700 Subject: [PATCH 107/162] More useful tooltip for agent Fix microsoft/vscode-copilot#2387 --- src/vs/workbench/contrib/chat/browser/chatListRenderer.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 3b3fa1c56d2..61b1628533d 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -342,7 +342,11 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer Date: Wed, 25 Oct 2023 16:39:23 -0700 Subject: [PATCH 108/162] Enable used references by default (#196654) * Add sessionId, agent, and slash command to core telemetry * Enable used references by default --- .../contrib/chat/browser/chatListRenderer.ts | 4 ++-- .../workbench/contrib/chat/common/chatServiceImpl.ts | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 3b3fa1c56d2..3712ff00112 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -143,10 +143,10 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer { if (e.affectsConfiguration('chat.experimental.usedReferences')) { - this._usedReferencesEnabled = configService.getValue('chat.experimental.usedReferences') ?? productService.quality !== 'stable'; + this._usedReferencesEnabled = configService.getValue('chat.experimental.usedReferences') ?? true; } })); } diff --git a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts index d69ac7b7f5a..7b2154ffa31 100644 --- a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts +++ b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts @@ -49,6 +49,8 @@ type ChatProviderInvokedEvent = { totalTime: number | undefined; result: 'success' | 'error' | 'errorWithOutput' | 'cancelled' | 'filtered'; requestType: 'string' | 'followup' | 'slashCommand'; + chatSessionId: string; + agent: string; slashCommand: string | undefined; }; @@ -58,6 +60,8 @@ type ChatProviderInvokedClassification = { totalTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The total time it took to run the provider\'s `provideResponseWithProgress`.' }; result: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether invoking the ChatProvider resulted in an error.' }; requestType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The type of request that the user made.' }; + chatSessionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'A random ID for the session.' }; + agent: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The type of agent used.' }; slashCommand?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The type of slashCommand used.' }; owner: 'roblourens'; comment: 'Provides insight into the performance of Chat providers.'; @@ -492,7 +496,9 @@ export class ChatService extends Disposable implements IChatService { totalTime: stopWatch.elapsed(), result: 'cancelled', requestType, - slashCommand: usedSlashCommand?.command + agent: agentPart?.agent.id ?? '', + slashCommand: agentSlashCommandPart ? agentSlashCommandPart.command.name : usedSlashCommand?.command, + chatSessionId: model.sessionId }); model.cancelRequest(request); @@ -597,7 +603,9 @@ export class ChatService extends Disposable implements IChatService { totalTime: rawResponse.timings?.totalElapsed, result, requestType, - slashCommand: usedSlashCommand?.command + agent: agentPart?.agent.id ?? '', + slashCommand: agentSlashCommandPart ? agentSlashCommandPart.command.name : usedSlashCommand?.command, + chatSessionId: model.sessionId }); model.setResponse(request, rawResponse); this.trace('sendRequest', `Provider returned response for session ${model.sessionId}`); From 1941240420a1974b83462b033c89664c6117db0c Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 25 Oct 2023 16:59:50 -0700 Subject: [PATCH 109/162] Fix used references expand state --- src/vs/workbench/contrib/chat/common/chatViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/common/chatViewModel.ts b/src/vs/workbench/contrib/chat/common/chatViewModel.ts index 3b9cdd2c11f..f5b1cf329c2 100644 --- a/src/vs/workbench/contrib/chat/common/chatViewModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatViewModel.ts @@ -328,7 +328,7 @@ export class ChatResponseViewModel extends Disposable implements IChatResponseVi return this._usedReferencesExpanded; } - return !this.isComplete; + return this.response.value.length === 0; } set usedReferencesExpanded(v: boolean) { From 5ba99f95390f65168c711a7c8789551fe8b9a0d2 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 25 Oct 2023 20:36:55 -0700 Subject: [PATCH 110/162] Add chat agent header animation --- .../contrib/chat/browser/chatListRenderer.ts | 24 +++++++++++++++---- .../contrib/chat/browser/media/chat.css | 16 +++++++++++++ .../contrib/chat/common/chatViewModel.ts | 3 ++- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 56c1426957b..004aead5d1d 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -16,7 +16,7 @@ import { ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree'; import { IAsyncDataSource, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; import { IAction } from 'vs/base/common/actions'; import { distinct } from 'vs/base/common/arrays'; -import { IntervalTimer } from 'vs/base/common/async'; +import { IntervalTimer, disposableTimeout } from 'vs/base/common/async'; import { Codicon } from 'vs/base/common/codicons'; import { Emitter, Event } from 'vs/base/common/event'; import { FuzzyScore } from 'vs/base/common/filters'; @@ -70,6 +70,7 @@ interface IChatListItemTemplate { readonly rowContainer: HTMLElement; readonly titleToolbar: MenuWorkbenchToolBar; readonly avatarContainer: HTMLElement; + readonly agentAvatarContainer: HTMLElement; readonly username: HTMLElement; readonly detail: HTMLElement; readonly value: HTMLElement; @@ -225,6 +226,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer('img.icon'); avatarIcon.src = FileAccess.uriToBrowserUri(icon).toString(true); - templateData.avatarContainer.appendChild(dom.$('.avatar', undefined, avatarIcon)); + templateData.agentAvatarContainer.replaceChildren(dom.$('.avatar', undefined, avatarIcon)); } else if (icon) { const avatarIcon = dom.$(ThemeIcon.asCSSSelector(icon)); - templateData.avatarContainer.appendChild(dom.$('.avatar.codicon-avatar', undefined, avatarIcon)); + templateData.agentAvatarContainer.replaceChildren(dom.$('.avatar.codicon-avatar', undefined, avatarIcon)); } + + templateData.agentAvatarContainer.classList.toggle('complete', element.isComplete); + if (!element.agentAvatarHasBeenRendered && !element.isComplete) { + element.agentAvatarHasBeenRendered = true; + templateData.agentAvatarContainer.classList.remove('loading'); + templateData.elementDisposables.add(disposableTimeout(() => { + templateData.agentAvatarContainer.classList.toggle('loading', !element.isComplete); + }, 100)); + } else { + templateData.agentAvatarContainer.classList.toggle('loading', !element.isComplete); + } + } else { + dom.hide(templateData.agentAvatarContainer); } } diff --git a/src/vs/workbench/contrib/chat/browser/media/chat.css b/src/vs/workbench/contrib/chat/browser/media/chat.css index 58bf33df2a4..519c9564e7c 100644 --- a/src/vs/workbench/contrib/chat/browser/media/chat.css +++ b/src/vs/workbench/contrib/chat/browser/media/chat.css @@ -113,6 +113,22 @@ font-size: 14px; } +.interactive-item-container .header .agent-avatar-container { + margin-left: -30px; + transition: margin 0.15s ease-out; + z-index: -1; +} + +.interactive-item-container .header .agent-avatar-container.loading { + margin-left: 0px; + z-index: 1; +} + +.interactive-item-container .header .agent-avatar-container.complete { + margin-left: -12px; + z-index: 1; +} + .monaco-list-row:not(.focused) .interactive-item-container:not(:hover) .header .monaco-toolbar, .monaco-list:not(:focus-within) .monaco-list-row .interactive-item-container:not(:hover) .header .monaco-toolbar, .monaco-list-row:not(.focused) .interactive-item-container:not(:hover) .header .monaco-toolbar .action-label, diff --git a/src/vs/workbench/contrib/chat/common/chatViewModel.ts b/src/vs/workbench/contrib/chat/common/chatViewModel.ts index f5b1cf329c2..dcaf0343508 100644 --- a/src/vs/workbench/contrib/chat/common/chatViewModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatViewModel.ts @@ -100,6 +100,7 @@ export interface IChatResponseViewModel { readonly errorDetails?: IChatResponseErrorDetails; readonly contentUpdateTimings?: IChatLiveUpdateData; renderData?: IChatResponseRenderData; + agentAvatarHasBeenRendered?: boolean; currentRenderedHeight: number | undefined; setVote(vote: InteractiveSessionVoteDirection): void; usedReferencesExpanded?: boolean; @@ -318,7 +319,7 @@ export class ChatResponseViewModel extends Disposable implements IChatResponseVi } renderData: IChatResponseRenderData | undefined = undefined; - + agentAvatarHasBeenRendered?: boolean; currentRenderedHeight: number | undefined; private _usedReferencesExpanded: boolean | undefined; From 54061768bc1b9ccc0edc911199a365da94872167 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Oct 2023 08:38:42 +0200 Subject: [PATCH 111/162] voice - tweak animation (#196674) --- .../actions/voiceChatActions.ts | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts index 147553488fd..c8fbc962176 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts @@ -679,7 +679,7 @@ registerThemingParticipant((theme, collector) => { let activeRecordingDimmedColor: Color | undefined; if (theme.type === ColorScheme.LIGHT || theme.type === ColorScheme.DARK) { activeRecordingColor = theme.getColor(ACTIVITY_BAR_BADGE_BACKGROUND) ?? theme.getColor(focusBorder); - activeRecordingDimmedColor = activeRecordingColor?.transparent(0.4); + activeRecordingDimmedColor = activeRecordingColor?.transparent(0.2); } else { activeRecordingColor = theme.getColor(contrastBorder); activeRecordingDimmedColor = theme.getColor(contrastBorder); @@ -696,6 +696,28 @@ registerThemingParticipant((theme, collector) => { border-radius: 50%; } + .monaco-workbench:not(.reduce-motion) .interactive-input-part .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled)::before, + .monaco-workbench:not(.reduce-motion) .inline-chat .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled)::before { + position: absolute; + outline: 1px solid ${activeRecordingColor}; + outline-offset: 2px; + border-radius: 50%; + width: 16px; + height: 16px; + } + + .monaco-workbench:not(.reduce-motion) .interactive-input-part .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled)::after, + .monaco-workbench:not(.reduce-motion) .inline-chat .monaco-action-bar .action-label.codicon-loading.codicon-modifier-spin:not(.disabled)::after { + content: ''; + position: absolute; + outline: 1px solid ${activeRecordingDimmedColor}; + outline-offset: 3px; + animation: pulseAnimation 1s infinite; + border-radius: 50%; + width: 16px; + height: 16px; + } + @keyframes pulseAnimation { 0% { outline-width: 1px; From f691df7580a4460944620990a2b7f37db01d6e92 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Oct 2023 09:15:15 +0200 Subject: [PATCH 112/162] Revert "accept chat response when session is released, prevent audio cue loop from continuing" --- .../workbench/contrib/inlineChat/browser/inlineChatSession.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index 0c726ccb581..891b3c02da2 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -27,7 +27,6 @@ import { ISingleEditOperation } from 'vs/editor/common/core/editOperation'; import { raceCancellation } from 'vs/base/common/async'; import { LineRangeMapping } from 'vs/editor/common/diff/rangeMapping'; import { IMarkdownString } from 'vs/base/common/htmlContent'; -import { IChatAccessibilityService } from 'vs/workbench/contrib/chat/browser/chat'; export type Recording = { when: Date; @@ -408,7 +407,6 @@ export class InlineChatSessionService implements IInlineChatSessionService { @IModelService private readonly _modelService: IModelService, @ITextModelService private readonly _textModelService: ITextModelService, @ILogService private readonly _logService: ILogService, - @IChatAccessibilityService private readonly _chatAccessibilityService: IChatAccessibilityService, ) { } dispose() { @@ -487,7 +485,7 @@ export class InlineChatSessionService implements IInlineChatSessionService { } releaseSession(session: Session): void { - this._chatAccessibilityService.acceptResponse(); + const { editor } = session; // cleanup From 70e606d5fce956a27366c2675c8f6b0e0c63bfb8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Oct 2023 09:58:34 +0200 Subject: [PATCH 113/162] Aux window: "Window 1" is a bad label? (fix #196394) (#196682) --- .../workbench/browser/parts/editor/editor.ts | 1 + .../browser/parts/editor/editorGroupView.ts | 15 +++++- .../browser/parts/editor/editorPart.ts | 18 +++++-- .../browser/parts/editor/editorParts.ts | 24 ++++++++- src/vs/workbench/common/editor.ts | 1 + .../common/editor/editorGroupModel.ts | 8 +++ .../files/browser/views/openEditorsView.ts | 1 + .../terminal/browser/terminalActions.ts | 3 +- .../test/browser/editorGroupsService.test.ts | 51 +++++++++++++++++++ .../parts/editor/editorGroupModel.test.ts | 16 ++++++ .../test/browser/workbenchTestServices.ts | 2 + 11 files changed, 132 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editor.ts b/src/vs/workbench/browser/parts/editor/editor.ts index 0ad637398b2..e37f6f54a1f 100644 --- a/src/vs/workbench/browser/parts/editor/editor.ts +++ b/src/vs/workbench/browser/parts/editor/editor.ts @@ -282,6 +282,7 @@ export interface IEditorGroupView extends IDisposable, ISerializableView, IEdito setActive(isActive: boolean): void; notifyIndexChanged(newIndex: number): void; + notifyLabelChanged(newLabel: string): void; openEditor(editor: EditorInput, options?: IEditorOptions, internalOptions?: IInternalEditorOpenOptions): Promise; diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 102b7b988cd..30219f5b97d 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -136,7 +136,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { from: IEditorGroupView | ISerializedEditorGroupModel | null, private readonly editorPartsView: IEditorPartsView, public readonly groupsView: IEditorGroupsView, - private readonly groupsLabel: string, + private groupsLabel: string, private _index: number, @IInstantiationService private readonly instantiationService: IInstantiationService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @@ -449,7 +449,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { if (this.isEmpty) { this.element.classList.add('empty'); this.element.tabIndex = 0; - this.element.setAttribute('aria-label', localize('emptyEditorGroup', "{0} (empty)", this.label)); + this.element.setAttribute('aria-label', localize('emptyEditorGroup', "{0} (empty)", this.ariaLabel)); } // Non-Empty Container: revert empty container attributes @@ -762,6 +762,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } get ariaLabel(): string { + if (this.groupsLabel) { + return localize('groupAriaLabelLong', "{0}: Editor Group {1}", this.groupsLabel, this._index + 1); + } + return localize('groupAriaLabel', "Editor Group {0}", this._index + 1); } @@ -785,6 +789,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } } + notifyLabelChanged(newLabel: string): void { + if (this.groupsLabel !== newLabel) { + this.groupsLabel = newLabel; + this.model.setLabel(newLabel); + } + } + setActive(isActive: boolean): void { this.active = isActive; diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index af7e2d8e0dd..5c4832ccd65 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { localize } from 'vs/nls'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Part } from 'vs/workbench/browser/part'; import { Dimension, isAncestor, $, EventHelper, addDisposableGenericMouseDownListener, getWindow } from 'vs/base/browser/dom'; @@ -99,6 +98,9 @@ export class EditorPart extends Part implements IEditorPart { private readonly _onDidChangeGroupIndex = this._register(new Emitter()); readonly onDidChangeGroupIndex = this._onDidChangeGroupIndex.event; + private readonly _onDidChangeGroupLabel = this._register(new Emitter()); + readonly onDidChangeGroupLabel = this._onDidChangeGroupLabel.event; + private readonly _onDidChangeGroupLocked = this._register(new Emitter()); readonly onDidChangeGroupLocked = this._onDidChangeGroupLocked.event; @@ -643,6 +645,9 @@ export class EditorPart extends Part implements IEditorPart { case GroupModelChangeKind.GROUP_INDEX: this._onDidChangeGroupIndex.fire(groupView); break; + case GroupModelChangeKind.GROUP_LABEL: + this._onDidChangeGroupLabel.fire(groupView); + break; } })); @@ -1222,6 +1227,12 @@ export class EditorPart extends Part implements IEditorPart { this.getGroups(GroupsOrder.GRID_APPEARANCE).forEach((group, index) => group.notifyIndexChanged(index)); } + notifyGroupsLabelChange(newLabel: string) { + for (const group of this.groups) { + group.notifyLabelChanged(newLabel); + } + } + private get isEmpty(): boolean { return this.count === 1 && this._activeGroup.isEmpty; } @@ -1330,13 +1341,14 @@ export class MainEditorPart extends EditorPart { export class AuxiliaryEditorPart extends EditorPart implements IAuxiliaryEditorPart { - private static COUNTER = 0; + private static COUNTER = 1; private readonly _onDidClose = this._register(new Emitter()); readonly onDidClose = this._onDidClose.event; constructor( editorPartsView: IEditorPartsView, + groupsLabel: string, @IInstantiationService instantiationService: IInstantiationService, @IThemeService themeService: IThemeService, @IConfigurationService configurationService: IConfigurationService, @@ -1345,7 +1357,7 @@ export class AuxiliaryEditorPart extends EditorPart implements IAuxiliaryEditorP @IHostService hostService: IHostService ) { const id = AuxiliaryEditorPart.COUNTER++; - super(editorPartsView, `workbench.parts.auxiliaryEditor.${id}`, localize('auxiliaryEditorPartLabel', "Window {0}", id + 1), instantiationService, themeService, configurationService, storageService, layoutService, hostService); + super(editorPartsView, `workbench.parts.auxiliaryEditor.${id}`, groupsLabel, instantiationService, themeService, configurationService, storageService, layoutService, hostService); } protected override saveState(): void { diff --git a/src/vs/workbench/browser/parts/editor/editorParts.ts b/src/vs/workbench/browser/parts/editor/editorParts.ts index 92c96fced43..42bffcb5bb2 100644 --- a/src/vs/workbench/browser/parts/editor/editorParts.ts +++ b/src/vs/workbench/browser/parts/editor/editorParts.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 { EditorGroupLayout, GroupDirection, GroupOrientation, GroupsArrangement, GroupsOrder, IAuxiliaryEditorPart, IEditorDropTargetDelegate, IEditorGroupsService, IEditorSideGroup, IFindGroupScope, IMergeGroupOptions } from 'vs/workbench/services/editor/common/editorGroupsService'; import { Event, Emitter } from 'vs/base/common/event'; import { getActiveDocument } from 'vs/base/browser/dom'; @@ -50,7 +51,7 @@ export class EditorParts extends Disposable implements IEditorGroupsService, IEd partContainer.setAttribute('role', 'main'); auxiliaryWindow.container.appendChild(partContainer); - const editorPart = disposables.add(this.instantiationService.createInstance(AuxiliaryEditorPart, this)); + const editorPart = disposables.add(this.instantiationService.createInstance(AuxiliaryEditorPart, this, this.getGroupsLabel(this.parts.size))); disposables.add(this.registerEditorPart(editorPart)); disposables.add(Event.once(editorPart.onDidClose)(() => disposables.dispose())); @@ -78,13 +79,28 @@ export class EditorParts extends Disposable implements IEditorGroupsService, IEd this.parts.add(part); const disposables = this._register(new DisposableStore()); - disposables.add(toDisposable(() => this.parts.delete(part))); + disposables.add(toDisposable(() => this.unregisterEditorPart(part))); this.registerEditorPartListeners(part, disposables); return disposables; } + private unregisterEditorPart(part: EditorPart): void { + this.parts.delete(part); + + // Notify all parts about a groups label change + // given it is computed based on the index + + Array.from(this.parts).forEach((part, index) => { + if (part === this.mainPart) { + return; + } + + part.notifyGroupsLabelChange(this.getGroupsLabel(index)); + }); + } + private registerEditorPartListeners(part: EditorPart, disposables: DisposableStore): void { disposables.add(part.onDidFocus(() => { if (this.parts.size > 1) { @@ -103,6 +119,10 @@ export class EditorParts extends Disposable implements IEditorGroupsService, IEd disposables.add(part.onDidChangeGroupLocked(group => this._onDidChangeGroupLocked.fire(group))); } + private getGroupsLabel(index: number): string { + return localize('groupLabel', "Window {0}", index + 1); + } + //#endregion //#region Helpers diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index e7854dea7b5..e80c28f88a6 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -1073,6 +1073,7 @@ export const enum GroupModelChangeKind { /* Group Changes */ GROUP_ACTIVE, GROUP_INDEX, + GROUP_LABEL, GROUP_LOCKED, /* Editor Changes */ diff --git a/src/vs/workbench/common/editor/editorGroupModel.ts b/src/vs/workbench/common/editor/editorGroupModel.ts index fc4bb668d21..497ef8daf46 100644 --- a/src/vs/workbench/common/editor/editorGroupModel.ts +++ b/src/vs/workbench/common/editor/editorGroupModel.ts @@ -685,6 +685,14 @@ export class EditorGroupModel extends Disposable implements IEditorGroupModel { this._onDidModelChange.fire({ kind: GroupModelChangeKind.GROUP_INDEX }); } + setLabel(label: string) { + // We do not really keep the `label` in our model because + // it has no special meaning to us here. But for consistency + // we emit a `onDidModelChange` event so that components can + // react. + this._onDidModelChange.fire({ kind: GroupModelChangeKind.GROUP_LABEL }); + } + pin(candidate: EditorInput): EditorInput | undefined { const res = this.findEditor(candidate); if (!res) { diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index 5e970ae0eaf..5a881944d4f 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -131,6 +131,7 @@ export class OpenEditorsView extends ViewPane { this.focusActiveEditor(); break; case GroupModelChangeKind.GROUP_INDEX: + case GroupModelChangeKind.GROUP_LABEL: if (index >= 0) { this.list.splice(index, 1, [group]); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 28a92d78e86..3b98991958d 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -63,6 +63,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { Iterable } from 'vs/base/common/iterator'; import { AccessibleViewProviderId, accessibleViewCurrentProviderId, accessibleViewIsShown, accessibleViewOnLastLine } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration'; import { isKeyboardEvent, isMouseEvent, isPointerEvent } from 'vs/base/browser/dom'; +import { editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn'; export const switchTerminalActionViewItemSeparator = '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'; export const switchTerminalShowTabsTitle = localize('showTerminalTabs', "Show Tabs"); @@ -266,7 +267,7 @@ export function registerTerminalActions() { // called when a terminal is the active editor const editorGroupsService = accessor.get(IEditorGroupsService); const instance = await c.service.createTerminal({ - location: { viewColumn: editorGroupsService.activeGroup.index } + location: { viewColumn: editorGroupToColumn(editorGroupsService, editorGroupsService.activeGroup) } }); await instance.focusWhenReady(); } diff --git a/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts b/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts index 0e8a0e2b313..071e78a9f0e 100644 --- a/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts @@ -316,6 +316,57 @@ suite('EditorGroupsService', () => { groupIndexChangedListener.dispose(); }); + test('groups label', async function () { + const [part] = await createPart(); + + const rootGroup = part.groups[0]; + const rightGroup = part.addGroup(rootGroup, GroupDirection.RIGHT); + + let partLabelChangedCounter = 0; + const groupIndexChangedListener = part.onDidChangeGroupLabel(() => { + partLabelChangedCounter++; + }); + + let rootGroupLabelChangeCounter = 0; + const rootGroupLabelChangeListener = rootGroup.onDidModelChange(e => { + if (e.kind === GroupModelChangeKind.GROUP_LABEL) { + rootGroupLabelChangeCounter++; + } + }); + + let rightGroupLabelChangeCounter = 0; + const rightGroupLabelChangeListener = rightGroup.onDidModelChange(e => { + if (e.kind === GroupModelChangeKind.GROUP_LABEL) { + rightGroupLabelChangeCounter++; + } + }); + + assert.strictEqual(rootGroup.label, 'Group 1'); + assert.strictEqual(rightGroup.label, 'Group 2'); + + part.notifyGroupsLabelChange('Window 2'); + + assert.strictEqual(rootGroup.label, 'Window 2: Group 1'); + assert.strictEqual(rightGroup.label, 'Window 2: Group 2'); + + assert.strictEqual(rootGroupLabelChangeCounter, 1); + assert.strictEqual(rightGroupLabelChangeCounter, 1); + assert.strictEqual(partLabelChangedCounter, 2); + + part.notifyGroupsLabelChange('Window 3'); + + assert.strictEqual(rootGroup.label, 'Window 3: Group 1'); + assert.strictEqual(rightGroup.label, 'Window 3: Group 2'); + + assert.strictEqual(rootGroupLabelChangeCounter, 2); + assert.strictEqual(rightGroupLabelChangeCounter, 2); + assert.strictEqual(partLabelChangedCounter, 4); + + rootGroupLabelChangeListener.dispose(); + rightGroupLabelChangeListener.dispose(); + groupIndexChangedListener.dispose(); + }); + test('copy/merge groups', async () => { const [part] = await createPart(); diff --git a/src/vs/workbench/test/browser/parts/editor/editorGroupModel.test.ts b/src/vs/workbench/test/browser/parts/editor/editorGroupModel.test.ts index 61be5f1243c..04ae587cf56 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorGroupModel.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorGroupModel.test.ts @@ -101,6 +101,7 @@ suite('EditorGroupModel', () => { locked: number[]; active: number[]; index: number[]; + label: number[]; opened: IGroupEditorOpenEvent[]; activated: IGroupEditorChangeEvent[]; closed: IGroupEditorCloseEvent[]; @@ -116,6 +117,7 @@ suite('EditorGroupModel', () => { const groupEvents: GroupEvents = { active: [], index: [], + label: [], locked: [], opened: [], closed: [], @@ -138,6 +140,9 @@ suite('EditorGroupModel', () => { } else if (e.kind === GroupModelChangeKind.GROUP_INDEX) { groupEvents.index.push(group.id); return; + } else if (e.kind === GroupModelChangeKind.GROUP_LABEL) { + groupEvents.label.push(group.id); + return; } if (!e.editor) { return; @@ -807,6 +812,17 @@ suite('EditorGroupModel', () => { assert.strictEqual(events.index.length, 1); }); + test('label', function () { + const group = createEditorGroupModel(); + const events = groupListener(group); + + assert.strictEqual(events.label.length, 0); + + group.setLabel('Window 1'); + + assert.strictEqual(events.label.length, 1); + }); + test('active', function () { const group = createEditorGroupModel(); const events = groupListener(group); diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 76a028b3f0e..6e4e93422e8 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -825,6 +825,7 @@ export class TestEditorGroupsService implements IEditorGroupsService { onDidRemoveGroup: Event = Event.None; onDidMoveGroup: Event = Event.None; onDidChangeGroupIndex: Event = Event.None; + onDidChangeGroupLabel: Event = Event.None; onDidChangeGroupLocked: Event = Event.None; onDidChangeGroupMaximized: Event = Event.None; onDidLayout: Event = Event.None; @@ -943,6 +944,7 @@ export class TestEditorGroupView implements IEditorGroupView { get scopedContextKeyService(): IContextKeyService { throw new Error('not implemented'); } setActive(_isActive: boolean): void { } notifyIndexChanged(_index: number): void { } + notifyLabelChanged(_label: string): void { } dispose(): void { } toJSON(): object { return Object.create(null); } layout(_width: number, _height: number): void { } From ccc965c00c197cf496f3568b620da0713084bdcc Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Oct 2023 10:21:59 +0200 Subject: [PATCH 114/162] Cannot read properties of undefined (reading 'commentThreads') (#196683) Fixes #196668 --- src/vs/workbench/contrib/comments/common/commentModel.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/comments/common/commentModel.ts b/src/vs/workbench/contrib/comments/common/commentModel.ts index 5ee5ab1f657..e47d0253992 100644 --- a/src/vs/workbench/contrib/comments/common/commentModel.ts +++ b/src/vs/workbench/contrib/comments/common/commentModel.ts @@ -119,7 +119,10 @@ export class CommentsModel { changed.forEach(thread => { // Find resource that has the comment thread const matchingResourceIndex = threadsForOwner.findIndex((resourceData) => resourceData.id === thread.resource); - const matchingResourceData = threadsForOwner[matchingResourceIndex]; + const matchingResourceData = matchingResourceIndex >= 0 ? threadsForOwner[matchingResourceIndex] : undefined; + if (!matchingResourceData) { + return; + } // Find comment node on resource that is that thread and replace it const index = matchingResourceData.commentThreads.findIndex((commentThread) => commentThread.threadId === thread.threadId); From 9eeb60b7f286a104f844e99b3a69974bbad72f97 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Oct 2023 10:37:39 +0200 Subject: [PATCH 115/162] Aux window: Chord timeout much smaller in aux window (fix #196184) (#196687) --- .../host/browser/browserHostService.ts | 26 ++++++++------- .../electron-sandbox/nativeHostService.ts | 33 ++++++++++++++----- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts index 008e5065ab3..4f56301f2f9 100644 --- a/src/vs/workbench/services/host/browser/browserHostService.ts +++ b/src/vs/workbench/services/host/browser/browserHostService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Event } from 'vs/base/common/event'; +import { Emitter, Event } from 'vs/base/common/event'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; @@ -14,7 +14,7 @@ import { isResourceEditorInput, pathsToEditors } from 'vs/workbench/common/edito import { whenEditorClosed } from 'vs/workbench/browser/editor'; import { IFileService } from 'vs/platform/files/common/files'; import { ILabelService, Verbosity } from 'vs/platform/label/common/label'; -import { ModifierKeyEmitter, trackFocus } from 'vs/base/browser/dom'; +import { ModifierKeyEmitter, getActiveDocument, getActiveWindow, onDidRegisterWindow, trackFocus } from 'vs/base/browser/dom'; import { Disposable } from 'vs/base/common/lifecycle'; import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; import { memoize } from 'vs/base/common/decorators'; @@ -179,18 +179,22 @@ export class BrowserHostService extends Disposable implements IHostService { @memoize get onDidChangeFocus(): Event { - const focusTracker = this._register(trackFocus(window)); - const onVisibilityChange = this._register(new DomEmitter(window.document, 'visibilitychange')); + const emitter = this._register(new Emitter()); - return Event.latch(Event.any( - Event.map(focusTracker.onDidFocus, () => this.hasFocus), - Event.map(focusTracker.onDidBlur, () => this.hasFocus), - Event.map(onVisibilityChange.event, () => this.hasFocus) - )); + this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => { + const focusTracker = disposables.add(trackFocus(window)); + const onVisibilityChange = disposables.add(new DomEmitter(window.document, 'visibilitychange')); + + disposables.add(focusTracker.onDidFocus(() => emitter.fire(this.hasFocus))); + disposables.add(focusTracker.onDidBlur(() => emitter.fire(this.hasFocus))); + disposables.add(onVisibilityChange.event(() => emitter.fire(this.hasFocus))); + }, { window, disposables: this._store })); + + return emitter.event; } get hasFocus(): boolean { - return document.hasFocus(); + return getActiveDocument().hasFocus(); } async hadLastFocus(): Promise { @@ -198,7 +202,7 @@ export class BrowserHostService extends Disposable implements IHostService { } async focus(): Promise { - window.focus(); + getActiveWindow().focus(); } //#endregion diff --git a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts index 66d55f33f98..47b619b855f 100644 --- a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts +++ b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Event } from 'vs/base/common/event'; +import { Emitter, Event } from 'vs/base/common/event'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { INativeHostService } from 'vs/platform/native/common/native'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -15,7 +15,9 @@ import { NativeHostService } from 'vs/platform/native/electron-sandbox/nativeHos import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; import { IMainProcessService } from 'vs/platform/ipc/common/mainProcessService'; import { isAuxiliaryWindow } from 'vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService'; -import { getActiveWindow } from 'vs/base/browser/dom'; +import { getActiveDocument, getActiveWindow, onDidRegisterWindow, trackFocus } from 'vs/base/browser/dom'; +import { DomEmitter } from 'vs/base/browser/event'; +import { memoize } from 'vs/base/common/decorators'; class WorkbenchNativeHostService extends NativeHostService { @@ -41,14 +43,29 @@ class WorkbenchHostService extends Disposable implements IHostService { //#region Focus - get onDidChangeFocus(): Event { return this._onDidChangeFocus; } - private _onDidChangeFocus: Event = Event.latch(Event.any( - Event.map(Event.filter(this.nativeHostService.onDidFocusWindow, id => id === this.nativeHostService.windowId), () => this.hasFocus), - Event.map(Event.filter(this.nativeHostService.onDidBlurWindow, id => id === this.nativeHostService.windowId), () => this.hasFocus) - ), undefined, this._store); + @memoize + get onDidChangeFocus(): Event { + const emitter = this._register(new Emitter()); + + // Main window: track via native API + this._register(Event.filter(this.nativeHostService.onDidFocusWindow, id => id === this.nativeHostService.windowId, this._store)(() => emitter.fire(this.hasFocus))); + this._register(Event.filter(this.nativeHostService.onDidBlurWindow, id => id === this.nativeHostService.windowId, this._store)(() => emitter.fire(this.hasFocus))); + + // Aux windows: track via DOM APIs + this._register(onDidRegisterWindow(({ window, disposables }) => { + const focusTracker = disposables.add(trackFocus(window)); + const onVisibilityChange = disposables.add(new DomEmitter(window.document, 'visibilitychange')); + + disposables.add(focusTracker.onDidFocus(() => emitter.fire(this.hasFocus))); + disposables.add(focusTracker.onDidBlur(() => emitter.fire(this.hasFocus))); + disposables.add(onVisibilityChange.event(() => emitter.fire(this.hasFocus))); + })); + + return emitter.event; + } get hasFocus(): boolean { - return document.hasFocus(); + return getActiveDocument().hasFocus(); } async hadLastFocus(): Promise { From e7df45ad51cbc96fc8e89c5b1d529cfe6bf9f5d6 Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Thu, 26 Oct 2023 10:31:12 +0100 Subject: [PATCH 116/162] Centre numbers vertically in top activity bar badges (fix #196691) --- src/vs/workbench/browser/parts/media/paneCompositePart.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/media/paneCompositePart.css b/src/vs/workbench/browser/parts/media/paneCompositePart.css index 428d7ea596f..d946011d356 100644 --- a/src/vs/workbench/browser/parts/media/paneCompositePart.css +++ b/src/vs/workbench/browser/parts/media/paneCompositePart.css @@ -172,13 +172,13 @@ .monaco-workbench .pane-composite-part > .title > .composite-bar-container > .composite-bar > .monaco-action-bar .action-item.icon .badge.compact .badge-content { position: absolute; - top: 12px; + top: 11px; right: 0px; font-size: 9px; font-weight: 600; min-width: 12px; - height: 12px; - line-height: 12px; + height: 13px; + line-height: 13px; padding: 0 2px; border-radius: 16px; text-align: center; From 29cbf57374f33a0a1ab111eac12650891aad1a94 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Oct 2023 13:56:37 +0200 Subject: [PATCH 117/162] aux window - disable main menu (#196697) * aux window - disable main menu * :lipstick: --- .../electron-main/auxiliaryWindow.ts | 30 +++++++++++++++---- .../electron-main/auxiliaryWindows.ts | 2 ++ .../auxiliaryWindowsMainService.ts | 30 ++++++++++++++++--- .../platform/menubar/electron-main/menubar.ts | 23 +++++++++++--- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts index 28cb3aafdd0..1b1271068a4 100644 --- a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts +++ b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts @@ -30,11 +30,7 @@ export class AuxiliaryWindow extends BaseWindow implements IAuxiliaryWindow { private _win: BrowserWindow | null = null; get win() { if (!this._win) { - const window = BrowserWindow.fromWebContents(this.contents); - if (window) { - this._win = window; - this.registerWindowListeners(window); - } + this.tryClaimWindow(); } return this._win; @@ -62,6 +58,30 @@ export class AuxiliaryWindow extends BaseWindow implements IAuxiliaryWindow { if (this.environmentMainService.args['open-devtools'] === true) { this.contents.openDevTools({ mode: 'bottom' }); } + + // Try to claim now + this.tryClaimWindow(); + } + + tryClaimWindow(): void { + if (this._win) { + return; // already claimed + } + + if (this._store.isDisposed || this.contents.isDestroyed()) { + return; // already disposed + } + + const window = BrowserWindow.fromWebContents(this.contents); + if (window) { + this._win = window; + + // Disable Menu + window.setMenu(null); + + // Listeners + this.registerWindowListeners(window); + } } private registerWindowListeners(window: BrowserWindow): void { diff --git a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindows.ts b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindows.ts index 8effe598041..70783086269 100644 --- a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindows.ts +++ b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindows.ts @@ -20,4 +20,6 @@ export interface IAuxiliaryWindowsMainService { getFocusedWindow(): IAuxiliaryWindow | undefined; getLastActiveWindow(): IAuxiliaryWindow | undefined; + + getWindows(): readonly IAuxiliaryWindow[]; } diff --git a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts index a85937cf5da..01718d334cc 100644 --- a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts +++ b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { BrowserWindow, BrowserWindowConstructorOptions, WebContents } from 'electron'; +import { BrowserWindow, BrowserWindowConstructorOptions, WebContents, app } from 'electron'; import { Event } from 'vs/base/common/event'; import { FileAccess } from 'vs/base/common/network'; import { AuxiliaryWindow, IAuxiliaryWindow } from 'vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow'; @@ -15,11 +15,29 @@ export class AuxiliaryWindowsMainService implements IAuxiliaryWindowsMainService declare readonly _serviceBrand: undefined; - private readonly windows = new Map(); + private readonly windows = new Map(); constructor( @IInstantiationService private readonly instantiationService: IInstantiationService - ) { } + ) { + this.registerListeners(); + } + + private registerListeners(): void { + + // We have to ensure that an auxiliary window gets to know its + // parent `BrowserWindow` so that it can apply listeners to it + // Unfortunately we cannot rely on static `BrowserWindow` methods + // because we might call the methods too early before the window + // is created. + + app.on('browser-window-created', (_event, browserWindow) => { + const auxiliaryWindow = this.getWindowById(browserWindow.id); + if (auxiliaryWindow) { + auxiliaryWindow.tryClaimWindow(); + } + }); + } createWindow(): BrowserWindowConstructorOptions { return this.instantiationService.invokeFunction(defaultBrowserWindowOptions, undefined, { @@ -36,7 +54,7 @@ export class AuxiliaryWindowsMainService implements IAuxiliaryWindowsMainService Event.once(auxiliaryWindow.onDidClose)(() => this.windows.delete(auxiliaryWindow.id)); } - getWindowById(windowId: number): IAuxiliaryWindow | undefined { + getWindowById(windowId: number): AuxiliaryWindow | undefined { return this.windows.get(windowId); } @@ -52,4 +70,8 @@ export class AuxiliaryWindowsMainService implements IAuxiliaryWindowsMainService getLastActiveWindow(): IAuxiliaryWindow | undefined { return getLastFocused(Array.from(this.windows.values())); } + + getWindows(): readonly IAuxiliaryWindow[] { + return Array.from(this.windows.values()); + } } diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index e928d0bb273..0ef12205389 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -11,6 +11,7 @@ import { mnemonicMenuLabel } from 'vs/base/common/labels'; import { isMacintosh, language } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import * as nls from 'vs/nls'; +import { IAuxiliaryWindowsMainService } from 'vs/platform/auxiliaryWindow/electron-main/auxiliaryWindows'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; @@ -74,7 +75,8 @@ export class Menubar { @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, @ILogService private readonly logService: ILogService, @INativeHostMainService private readonly nativeHostMainService: INativeHostMainService, - @IProductService private readonly productService: IProductService + @IProductService private readonly productService: IProductService, + @IAuxiliaryWindowsMainService private readonly auxiliaryWindowsMainService: IAuxiliaryWindowsMainService ) { this.menuUpdater = new RunOnceScheduler(() => this.doUpdateMenu(), 0); @@ -255,7 +257,7 @@ export class Menubar { // If we don't have a menu yet, set it to null to avoid the electron menu. // This should only happen on the first launch ever if (Object.keys(this.menubarMenus).length === 0) { - Menu.setApplicationMenu(isMacintosh ? new Menu() : null); + this.doSetApplicationMenu(isMacintosh ? new Menu() : null); return; } @@ -358,15 +360,28 @@ export class Menubar { } if (menubar.items && menubar.items.length > 0) { - Menu.setApplicationMenu(menubar); + this.doSetApplicationMenu(menubar); } else { - Menu.setApplicationMenu(null); + this.doSetApplicationMenu(null); } // Dispose of older menus after some time this.menuGC.schedule(); } + private doSetApplicationMenu(menu: (Menu) | (null)): void { + + // Setting the application menu sets it to all opened windows, + // but we currently do not support a menu in auxiliary windows, + // so we need to unset it there. + + Menu.setApplicationMenu(menu); + + for (const window of this.auxiliaryWindowsMainService.getWindows()) { + window.win?.setMenu(null); + } + } + private setMacApplicationMenu(macApplicationMenu: Menu): void { const about = this.createMenuItem(nls.localize('mAbout', "About {0}", this.productService.nameLong), 'workbench.action.showAboutDialog'); const checkForUpdates = this.getUpdateMenuItems(); From 33b2e4a29c4ff7f8e7c988f19add209bd53ed55e Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Thu, 26 Oct 2023 15:08:05 +0200 Subject: [PATCH 118/162] canceliing the scheduler and hiding the widget on model change and model content change --- src/vs/editor/contrib/hover/browser/hover.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/contrib/hover/browser/hover.ts b/src/vs/editor/contrib/hover/browser/hover.ts index 890613ed9c0..ba97e8c0dc9 100644 --- a/src/vs/editor/contrib/hover/browser/hover.ts +++ b/src/vs/editor/contrib/hover/browser/hover.ts @@ -83,14 +83,13 @@ export class ModesHoverController extends Disposable implements IEditorContribut this._hookEvents(); } })); - this._register(this._editor.onMouseLeave(() => { - this._mouseMoveEvent = undefined; - this._reactToEditorMouseMoveRunner.cancel(); - })); } private _hookEvents(): void { - const hideWidgetsEventHandler = () => this._hideWidgets(); + const hideWidgetsCancelSchedulerEventHandler = () => { + this._cancelScheduler(); + this._hideWidgets(); + }; const hoverOpts = this._editor.getOption(EditorOption.hover); this._isHoverEnabled = hoverOpts.enabled; @@ -107,10 +106,16 @@ export class ModesHoverController extends Disposable implements IEditorContribut } this._toUnhook.add(this._editor.onMouseLeave((e) => this._onEditorMouseLeave(e))); - this._toUnhook.add(this._editor.onDidChangeModel(hideWidgetsEventHandler)); + this._toUnhook.add(this._editor.onDidChangeModel(hideWidgetsCancelSchedulerEventHandler)); + this._toUnhook.add(this._editor.onDidChangeModelContent(hideWidgetsCancelSchedulerEventHandler)); this._toUnhook.add(this._editor.onDidScrollChange((e: IScrollEvent) => this._onEditorScrollChanged(e))); } + private _cancelScheduler() { + this._mouseMoveEvent = undefined; + this._reactToEditorMouseMoveRunner.cancel(); + } + private _unhookEvents(): void { this._toUnhook.clear(); } @@ -150,6 +155,7 @@ export class ModesHoverController extends Disposable implements IEditorContribut } private _onEditorMouseLeave(mouseEvent: IPartialEditorMouseEvent): void { + this._cancelScheduler(); const targetEm = (mouseEvent.event.browserEvent.relatedTarget) as HTMLElement; if (this._contentWidget?.widget.isResizing || this._contentWidget?.containsNode(targetEm)) { // When the content widget is resizing From 9f627c21f64a27a75ee3a4e348d424daff892455 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 26 Oct 2023 15:21:08 +0200 Subject: [PATCH 119/162] no undoStops between streaming edits, esp not between last and second to last round (#196708) fixes https://github.com/microsoft/vscode-copilot/issues/2403 --- .../browser/inlineChatController.ts | 3 +- .../browser/inlineChatStrategies.ts | 10 +++-- .../test/browser/inlineChatController.test.ts | 44 ++++++++++++++++++- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 03629d3a888..789680b02d9 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -596,7 +596,6 @@ export class InlineChatController implements IEditorContribution { const progressiveEditsCts = new CancellationTokenSource(requestCts.token); const progressiveEditsClock = StopWatch.create(); const progressiveEditsQueue = new Queue(); - let round = 0; const progress = new AsyncProgress(async data => { this._log('received chunk', data, request); @@ -632,7 +631,7 @@ export class InlineChatController implements IEditorContribution { // become infinitely fast await this._makeChanges(data.edits!, data.editsShouldBeInstant ? undefined - : { duration: progressiveEditsAvgDuration.value, round: round++, token: progressiveEditsCts.token } + : { duration: progressiveEditsAvgDuration.value, token: progressiveEditsCts.token } ); // reshow the widget if the start position changed or shows at the wrong position diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index db5e23fdd89..31359f738a2 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -225,7 +225,6 @@ class InlineDiffDecorations { export interface ProgressingEditsOptions { duration: number; - round: number; token: CancellationToken; } @@ -328,8 +327,9 @@ export class LiveStrategy extends EditModeStrategy { override async makeProgressiveChanges(edits: ISingleEditOperation[], opts: ProgressingEditsOptions): Promise { - if (opts.round === 0) { - this._session.textModelN.pushStackElement(); + // push undo stop before first edit + if (++this._editCount === 1) { + this._editor.pushUndoStop(); } const durationInSec = opts.duration / 1000; @@ -591,14 +591,16 @@ export function asProgressiveEdit(edit: IIdentifiedSingleEditOperation, wordsPer if (r.isFullString) { clearInterval(handle); stream.resolve(); + d.dispose(); } }, 1000 / wordsPerSec); // cancel ASAP - token.onCancellationRequested(() => { + const d = token.onCancellationRequested(() => { clearTimeout(handle); stream.resolve(); + d.dispose(); }); return { 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 822c5f8064c..bc8f99f4408 100644 --- a/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts +++ b/src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts @@ -10,7 +10,7 @@ import { DisposableStore } from 'vs/base/common/lifecycle'; import { mock } from 'vs/base/test/common/mock'; import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; import { TestDiffProviderFactoryService } from 'vs/editor/browser/diff/testDiffProviderFactoryService'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { IActiveCodeEditor } from 'vs/editor/browser/editorBrowser'; import { IDiffProviderFactoryService } from 'vs/editor/browser/widget/diffEditor/diffProviderFactoryService'; import { Range } from 'vs/editor/common/core/range'; import { ITextModel } from 'vs/editor/common/model'; @@ -81,7 +81,7 @@ suite('InteractiveChatController', function () { } const store = new DisposableStore(); - let editor: ICodeEditor; + let editor: IActiveCodeEditor; let model: ITextModel; let ctrl: TestController; // let contextKeys: MockContextKeyService; @@ -327,4 +327,44 @@ suite('InteractiveChatController', function () { await r; assert.strictEqual(ctrl.getWidgetPosition(), undefined); }); + + test('[Bug] Inline Chat\'s streaming pushed broken iterations to the undo stack #2403', async function () { + + const d = inlineChatService.addProvider({ + debugName: 'Unit Test', + label: 'Unit Test', + prepareInlineChatSession() { + return { + id: Math.random(), + wholeRange: new Range(3, 1, 3, 3) + }; + }, + async provideResponse(session, request, progress) { + + progress.report({ edits: [{ range: new Range(1, 1, 1, 1), text: 'hEllo1\n' }] }); + progress.report({ edits: [{ range: new Range(2, 1, 2, 1), text: 'hEllo2\n' }] }); + + return { + id: Math.random(), + type: InlineChatResponseType.EditorEdit, + edits: [{ range: new Range(1, 1, 1000, 1), text: 'Hello1\nHello2\n' }] + }; + } + }); + + const valueThen = editor.getModel().getValue(); + + store.add(d); + ctrl = instaService.createInstance(TestController, editor); + const p = ctrl.waitFor([...TestController.INIT_SEQUENCE, State.MAKE_REQUEST, State.APPLY_RESPONSE, State.SHOW_RESPONSE, State.WAIT_FOR_INPUT]); + const r = ctrl.run({ message: 'Hello', autoSend: true }); + await p; + ctrl.acceptSession(); + await r; + + assert.strictEqual(editor.getModel().getValue(), 'Hello1\nHello2\n'); + + editor.getModel().undo(); + assert.strictEqual(editor.getModel().getValue(), valueThen); + }); }); From 755b12c68a6adb19f2842a88379990f27ff1173f Mon Sep 17 00:00:00 2001 From: Benjamin Simmonds <44439583+benibenj@users.noreply.github.com> Date: Thu, 26 Oct 2023 15:37:18 +0200 Subject: [PATCH 120/162] Update tab bar group and order in layoutActions.ts (#196706) Update tab bar group and order in layoutActions.ts. --- src/vs/workbench/browser/actions/layoutActions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 8040b6a2167..32f43a19837 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -553,8 +553,8 @@ registerAction2(ShowSingleEditorTabAction); MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { submenu: MenuId.EditorTabsBarShowTabsSubmenu, title: localize('tabBar', "Tab Bar"), - group: '4_editor', - order: 6 + group: '3_workbench_layout_move', + order: 10 }); // --- Toggle Pinned Tabs On Separate Row From 5407b94ec6ec98005e27031df71d544607d40be9 Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Thu, 26 Oct 2023 14:37:39 +0100 Subject: [PATCH 121/162] Correct the #196696 fix which caused oval badges --- src/vs/workbench/browser/parts/media/paneCompositePart.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/media/paneCompositePart.css b/src/vs/workbench/browser/parts/media/paneCompositePart.css index d946011d356..4f55e904f65 100644 --- a/src/vs/workbench/browser/parts/media/paneCompositePart.css +++ b/src/vs/workbench/browser/parts/media/paneCompositePart.css @@ -176,7 +176,7 @@ right: 0px; font-size: 9px; font-weight: 600; - min-width: 12px; + min-width: 13px; height: 13px; line-height: 13px; padding: 0 2px; From 10a184f69bc99b4aad5f5633c7cc5ba54c65c6dc Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 26 Oct 2023 07:31:22 -0700 Subject: [PATCH 122/162] debug: update js-debug to 1.84 (#196717) --- product.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/product.json b/product.json index f44b078d728..605d8f117ee 100644 --- a/product.json +++ b/product.json @@ -50,8 +50,8 @@ }, { "name": "ms-vscode.js-debug", - "version": "1.83.1", - "sha256": "1452fdbab8d0d83ca5765bb66170d50b005c97ca4dcd13e154c3401d842a92d4", + "version": "1.84.0", + "sha256": "a57691eb4440e549edba7472c0313e94f24d46ebe1ede18784b552fc5d11e596", "repo": "https://github.com/microsoft/vscode-js-debug", "metadata": { "id": "25629058-ddac-4e17-abba-74678e126c5d", From 624bafc28055ba16ad0cb42e24d4f089ea5e1a9a Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Thu, 26 Oct 2023 15:46:36 +0100 Subject: [PATCH 123/162] Upsize progress badge on top activity bar to match #196696 change --- src/vs/workbench/browser/parts/media/paneCompositePart.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/media/paneCompositePart.css b/src/vs/workbench/browser/parts/media/paneCompositePart.css index 4f55e904f65..c39e25cde76 100644 --- a/src/vs/workbench/browser/parts/media/paneCompositePart.css +++ b/src/vs/workbench/browser/parts/media/paneCompositePart.css @@ -185,8 +185,8 @@ } .monaco-workbench .pane-composite-part > .title > .composite-bar-container > .composite-bar > .monaco-action-bar .action-item.icon .badge.compact.progress-badge .badge-content::before { - mask-size: 12px; - -webkit-mask-size: 12px; + mask-size: 13px; + -webkit-mask-size: 13px; top: 2px; } From 7eec26f0f530e3daa3f5bb0b3d12df9725b030f6 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 26 Oct 2023 16:56:13 +0200 Subject: [PATCH 124/162] Fix checkbox state management in tree view (#196721) `manageCheckboxStateManually` has no effect on tree view Fixes #196607 --- src/vs/workbench/browser/parts/views/treeView.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index 23d37b96047..09a5a5895eb 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -643,7 +643,7 @@ abstract class AbstractTreeView extends Disposable implements ITreeView { const dataSource = this.instantiationService.createInstance(TreeDataSource, this, (task: Promise) => this.progressService.withProgress({ location: this.id }, () => task)); const aligner = new Aligner(this.themeService); const checkboxStateHandler = this._register(new CheckboxStateHandler()); - const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, treeMenus, this.treeLabels, actionViewItemProvider, aligner, checkboxStateHandler, this.manuallyManageCheckboxes); + const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, treeMenus, this.treeLabels, actionViewItemProvider, aligner, checkboxStateHandler, () => this.manuallyManageCheckboxes); this._register(renderer.onDidChangeCheckboxState(e => this._onDidChangeCheckboxState.fire(e))); const widgetAriaLabel = this._title; @@ -1102,7 +1102,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer boolean, @IThemeService private readonly themeService: IThemeService, @IConfigurationService private readonly configurationService: IConfigurationService, @ILabelService private readonly labelService: ILabelService, @@ -1351,7 +1351,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer Date: Thu, 26 Oct 2023 18:30:26 +0200 Subject: [PATCH 125/162] local usage of _chatAccessibilityService, don't spread it around the state machine (#196737) https://github.com/microsoft/vscode/issues/194424 --- .../browser/inlineChatController.ts | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 789680b02d9..ac8682ce0ef 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -43,6 +43,7 @@ import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { IModelDeltaDecoration } from 'vs/editor/common/model'; import { IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents'; import { chatAgentLeader, chatSubcommandLeader } from 'vs/workbench/contrib/chat/common/chatParserTypes'; +import { renderMarkdownAsPlaintext } from 'vs/base/browser/markdownRenderer'; export const enum State { CREATE_SESSION = 'CREATE_SESSION', @@ -564,6 +565,7 @@ export class InlineChatController implements IEditorContribution { private async [State.MAKE_REQUEST](): Promise { assertType(this._editor.hasModel()); assertType(this._activeSession); + assertType(this._strategy); assertType(this._activeSession.lastInput); const requestCts = new CancellationTokenSource(); @@ -586,7 +588,6 @@ export class InlineChatController implements IEditorContribution { wholeRange: this._activeSession.wholeRange.value, live: this._activeSession.editMode !== EditMode.Preview // TODO@jrieken let extension know what document is used for previewing }; - this._chatAccessibilityService.acceptRequest(); const modelAltVersionIdNow = this._activeSession.textModelN.getAlternativeVersionId(); const progressEdits: TextEdit[][] = []; @@ -646,6 +647,11 @@ export class InlineChatController implements IEditorContribution { this._zone.value.widget.updateMarkdownMessage(markdownContents); } }); + + let a11yResponse: string | undefined; + const a11yVerboseInlineChat = this._configurationService.getValue('accessibility.verbosity.inlineChat') === true; + this._chatAccessibilityService.acceptRequest(); + const task = this._activeSession.provider.provideResponse(this._activeSession.session, request, progress, requestCts.token); this._log('request started', this._activeSession.provider.debugName, this._activeSession.session, request); @@ -666,24 +672,32 @@ export class InlineChatController implements IEditorContribution { if (reply?.type === InlineChatResponseType.Message) { markdownContents.appendMarkdown(reply.message.value); response = new MarkdownResponse(this._activeSession.textModelN.uri, reply, markdownContents); + a11yResponse = renderMarkdownAsPlaintext(markdownContents); } else if (reply) { const editResponse = new EditResponse(this._activeSession.textModelN.uri, modelAltVersionIdNow, reply, progressEdits); for (let i = progressEdits.length; i < editResponse.allLocalEdits.length; i++) { await this._makeChanges(editResponse.allLocalEdits[i], undefined); } response = editResponse; + a11yResponse = this._strategy.checkChanges(editResponse) && a11yVerboseInlineChat + ? localize('editResponseMessage', "Review proposed changes in the diff editor.") + : ''; } else { response = new EmptyResponse(); + a11yResponse = localize('empty', "No results, please refine your input and try again"); } } catch (e) { response = new ErrorResponse(e); + a11yResponse = (response).message; + } finally { this._ctxHasActiveRequest.set(false); this._zone.value.widget.updateProgress(false); this._zone.value.widget.updateInfo(''); this._zone.value.widget.updateToolbar(true); this._log('request took', requestClock.elapsed(), this._activeSession.provider.debugName); + this._chatAccessibilityService.acceptResponse(a11yResponse); } progressiveEditsCts.dispose(true); @@ -760,8 +774,6 @@ export class InlineChatController implements IEditorContribution { const { response } = this._activeSession.lastExchange!; - let status: string | undefined; - this._ctxLastResponseType.set(response instanceof EditResponse || response instanceof MarkdownResponse ? response.raw.type : undefined); @@ -785,27 +797,22 @@ export class InlineChatController implements IEditorContribution { if (response instanceof EmptyResponse) { // show status message - status = localize('empty', "No results, please refine your input and try again"); + const status = localize('empty', "No results, please refine your input and try again"); this._zone.value.widget.updateStatus(status, { classes: ['warn'] }); - this._chatAccessibilityService.acceptResponse(status); return State.WAIT_FOR_INPUT; } else if (response instanceof ErrorResponse) { // show error if (!response.isCancellation) { - status = response.message; - this._zone.value.widget.updateStatus(status, { classes: ['error'] }); + this._zone.value.widget.updateStatus(response.message, { classes: ['error'] }); } } else if (response instanceof MarkdownResponse) { // clear status, show MD message this._zone.value.widget.updateStatus(''); - const content = this._zone.value.widget.updateMarkdownMessage(response.mdContent); + this._zone.value.widget.updateMarkdownMessage(response.mdContent); this._zone.value.widget.updateToolbar(true); - if (content) { - status = localize('markdownResponseMessage', "{0}", content); - } this._activeSession.lastExpansionState = this._zone.value.widget.expansionState; } else if (response instanceof EditResponse) { @@ -815,13 +822,10 @@ export class InlineChatController implements IEditorContribution { const canContinue = this._strategy.checkChanges(response); if (!canContinue) { - this._chatAccessibilityService.acceptResponse(); return State.CANCEL; } - status = this._configurationService.getValue('accessibility.verbosity.inlineChat') === true ? localize('editResponseMessage', "Review proposed changes in the diff editor.") : ''; await this._strategy.renderChanges(response); } - this._chatAccessibilityService.acceptResponse(status); this._showWidget(false); return State.WAIT_FOR_INPUT; From a7ad1bf68652fe74aa0ffc242f9104e33701fbca Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 26 Oct 2023 18:39:35 +0200 Subject: [PATCH 126/162] fix #196640 (#196738) --- .../extensions/browser/fileBasedRecommendations.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts index c77b79f07cc..47de97ba803 100644 --- a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts +++ b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts @@ -149,6 +149,7 @@ export class FileBasedRecommendations extends ExtensionRecommendations { const matchedRecommendations: IStringDictionary = {}; const unmatchedRecommendations: IStringDictionary = {}; let listenOnLanguageChange = false; + const languageId = model.getLanguageId(); for (const [extensionId, conditions] of extensionRecommendationEntries) { const conditionsByPattern: IFileOpenCondition[] = []; @@ -165,7 +166,7 @@ export class FileBasedRecommendations extends ExtensionRecommendations { } if (isLanguageCondition) { - if ((condition).languages.includes(model.getLanguageId())) { + if ((condition).languages.includes(languageId)) { languageMatched = true; } } @@ -178,12 +179,13 @@ export class FileBasedRecommendations extends ExtensionRecommendations { processedPathGlobs.set(pathGlob, pathGlobMatched); } - if (!languageMatched && !pathGlobMatched) { - // If the language is not matched and the path glob is not matched, then we don't need to check the other conditions + let matched = languageMatched || pathGlobMatched; + + // If the resource has pattern (extension) and not matched, then we don't need to check the other conditions + if (pattern && !matched) { continue; } - let matched = true; if (matched && condition.whenInstalled) { if (!condition.whenInstalled.every(id => installed.some(local => areSameExtensions({ id }, local.identifier)))) { matched = false; @@ -226,7 +228,9 @@ export class FileBasedRecommendations extends ExtensionRecommendations { } } - this.recommendationsByPattern.set(pattern, recommendationsByPattern); + if (pattern) { + this.recommendationsByPattern.set(pattern, recommendationsByPattern); + } if (Object.keys(unmatchedRecommendations).length) { if (listenOnLanguageChange) { const disposables = new DisposableStore(); From f1de3fc78021b9632d401397e7581106dccb045b Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Thu, 26 Oct 2023 19:16:47 +0200 Subject: [PATCH 127/162] Add query to find recently closed issues without a milestone (#196741) --- .vscode/notebooks/verification.github-issues | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.vscode/notebooks/verification.github-issues b/.vscode/notebooks/verification.github-issues index 72779d54da7..f0b318a28d1 100644 --- a/.vscode/notebooks/verification.github-issues +++ b/.vscode/notebooks/verification.github-issues @@ -12,7 +12,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels\n$milestone=milestone:\"October 2023\"\n" + "value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels\n$milestone=milestone:\"October 2023\"\n$closedRecently=closed:>2023-09-29\n" }, { "kind": 1, @@ -43,5 +43,15 @@ "kind": 2, "language": "github-issues", "value": "$repos $milestone is:closed reason:completed -assignee:@me label:bug -label:verified -label:*duplicate\n" + }, + { + "kind": 1, + "language": "markdown", + "value": "### Issues recently closed via PR without a milestone" + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repos is:closed linked:pr $closedRecently no:milestone -label:verified -label:*duplicate\n" } ] \ No newline at end of file From f40755c6994b16dacc145eda887d76e5783d7489 Mon Sep 17 00:00:00 2001 From: Joyce Er Date: Thu, 26 Oct 2023 10:26:15 -0700 Subject: [PATCH 128/162] fix: render chat history after signing in (#196742) * fix: render chat history after signing in * docs: add comment about using `height` param --- .../workbench/contrib/chat/browser/chatListRenderer.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 004aead5d1d..c1811430075 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -255,7 +255,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer, index: number, templateData: IChatListItemTemplate): void { + renderElement(node: ITreeNode, index: number, templateData: IChatListItemTemplate, height?: number): void { const { element } = node; const kind = isRequestVM(element) ? 'request' : isResponseVM(element) ? 'response' : @@ -322,7 +322,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer Date: Thu, 26 Oct 2023 20:02:04 +0200 Subject: [PATCH 129/162] do not initialise if disposed (#196745) --- src/vs/workbench/browser/parts/globalCompositeBar.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/browser/parts/globalCompositeBar.ts b/src/vs/workbench/browser/parts/globalCompositeBar.ts index 808ffa8645d..0a3a8b7931f 100644 --- a/src/vs/workbench/browser/parts/globalCompositeBar.ts +++ b/src/vs/workbench/browser/parts/globalCompositeBar.ts @@ -351,6 +351,9 @@ export class AccountsActivityActionViewItem extends AbstractGlobalActivityAction // Resolving the menu doesn't need to happen immediately, so we can wait until after the workbench has been restored // and only run this when the system is idle. await this.lifecycleService.when(LifecyclePhase.Restored); + if (this._store.isDisposed) { + return; + } const disposable = this._register(runWhenIdle(async () => { await this.doInitialize(); disposable.dispose(); From 540180098a63d237a10dad7a806be30af6cf298e Mon Sep 17 00:00:00 2001 From: Benjamin Simmonds <44439583+benibenj@users.noreply.github.com> Date: Thu, 26 Oct 2023 20:03:59 +0200 Subject: [PATCH 130/162] Remove un/maximize editor group commands (#196732) Refactor editor commands and actions --- .../parts/editor/editor.contribution.ts | 12 ++-- .../browser/parts/editor/editorActions.ts | 61 +++++-------------- .../browser/parts/editor/editorCommands.ts | 4 +- 3 files changed, 20 insertions(+), 57 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index d07d2581a31..b6ee8991056 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -27,7 +27,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { CloseEditorsInOtherGroupsAction, CloseAllEditorsAction, MoveGroupLeftAction, MoveGroupRightAction, SplitEditorAction, JoinTwoGroupsAction, RevertAndCloseEditorAction, - NavigateBetweenGroupsAction, FocusActiveGroupAction, FocusFirstGroupAction, ResetGroupSizesAction, MaximizeGroupAction, MinimizeOtherGroupsAction, FocusPreviousGroup, FocusNextGroup, + NavigateBetweenGroupsAction, FocusActiveGroupAction, FocusFirstGroupAction, ResetGroupSizesAction, MinimizeOtherGroupsAction, FocusPreviousGroup, FocusNextGroup, CloseLeftEditorsInGroupAction, OpenNextEditor, OpenPreviousEditor, NavigateBackwardsAction, NavigateForwardAction, NavigatePreviousAction, ReopenClosedEditorAction, QuickAccessPreviousRecentlyUsedEditorInGroupAction, QuickAccessPreviousEditorFromHistoryAction, ShowAllEditorsByAppearanceAction, ClearEditorHistoryAction, MoveEditorRightInGroupAction, OpenNextEditorInGroup, OpenPreviousEditorInGroup, OpenNextRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorAction, MoveEditorToPreviousGroupAction, @@ -41,13 +41,13 @@ import { ReOpenInTextEditorAction, DuplicateGroupDownAction, DuplicateGroupLeftAction, DuplicateGroupRightAction, DuplicateGroupUpAction, ToggleEditorTypeAction, SplitEditorToAboveGroupAction, SplitEditorToBelowGroupAction, SplitEditorToFirstGroupAction, SplitEditorToLastGroupAction, SplitEditorToLeftGroupAction, SplitEditorToNextGroupAction, SplitEditorToPreviousGroupAction, SplitEditorToRightGroupAction, NavigateForwardInEditsAction, NavigateBackwardsInEditsAction, NavigateForwardInNavigationsAction, NavigateBackwardsInNavigationsAction, NavigatePreviousInNavigationsAction, NavigatePreviousInEditsAction, NavigateToLastNavigationLocationAction, - MaximizeGroupHideSidebarAction, UnmaximizeEditorGroupAction, ExperimentalMoveEditorIntoNewWindowAction, ToggleMaximizeEditorGroupAction + MaximizeGroupHideSidebarAction, ExperimentalMoveEditorIntoNewWindowAction, ToggleMaximizeEditorGroupAction } from 'vs/workbench/browser/parts/editor/editorActions'; import { CLOSE_EDITORS_AND_GROUP_COMMAND_ID, CLOSE_EDITORS_IN_GROUP_COMMAND_ID, CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID, CLOSE_EDITOR_COMMAND_ID, CLOSE_EDITOR_GROUP_COMMAND_ID, CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID, CLOSE_PINNED_EDITOR_COMMAND_ID, CLOSE_SAVED_EDITORS_COMMAND_ID, GOTO_NEXT_CHANGE, GOTO_PREVIOUS_CHANGE, KEEP_EDITOR_COMMAND_ID, PIN_EDITOR_COMMAND_ID, SHOW_EDITORS_IN_GROUP, SPLIT_EDITOR_DOWN, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE, TOGGLE_DIFF_SIDE_BY_SIDE, TOGGLE_KEEP_EDITORS_COMMAND_ID, UNPIN_EDITOR_COMMAND_ID, setup as registerEditorCommands, REOPEN_WITH_COMMAND_ID, - TOGGLE_LOCK_GROUP_COMMAND_ID, UNLOCK_GROUP_COMMAND_ID, SPLIT_EDITOR_IN_GROUP, JOIN_EDITOR_IN_GROUP, FOCUS_FIRST_SIDE_EDITOR, FOCUS_SECOND_SIDE_EDITOR, TOGGLE_SPLIT_EDITOR_IN_GROUP_LAYOUT, SPLIT_EDITOR, MAXIMIZE_EDITOR_GROUP, UNMAXIMIZE_EDITOR_GROUP + TOGGLE_LOCK_GROUP_COMMAND_ID, UNLOCK_GROUP_COMMAND_ID, SPLIT_EDITOR_IN_GROUP, JOIN_EDITOR_IN_GROUP, FOCUS_FIRST_SIDE_EDITOR, FOCUS_SECOND_SIDE_EDITOR, TOGGLE_SPLIT_EDITOR_IN_GROUP_LAYOUT, SPLIT_EDITOR, TOGGLE_MAXIMIZE_EDITOR_GROUP, } from 'vs/workbench/browser/parts/editor/editorCommands'; import { inQuickPickContext, getQuickNavigateHandler } from 'vs/workbench/browser/quickaccess'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -214,9 +214,7 @@ registerAction2(NavigateBetweenGroupsAction); registerAction2(ResetGroupSizesAction); registerAction2(ToggleGroupSizesAction); -registerAction2(MaximizeGroupAction); registerAction2(MaximizeGroupHideSidebarAction); -registerAction2(UnmaximizeEditorGroupAction); registerAction2(ToggleMaximizeEditorGroupAction); registerAction2(MinimizeOtherGroupsAction); @@ -386,8 +384,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: SHOW_EDITORS_IN MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: localize('closeAll', "Close All") }, group: '5_close', order: 10 }); MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CLOSE_SAVED_EDITORS_COMMAND_ID, title: localize('closeAllSaved', "Close Saved") }, group: '5_close', order: 20 }); MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_KEEP_EDITORS_COMMAND_ID, title: localize('togglePreviewMode', "Enable Preview Editors"), toggled: ContextKeyExpr.has('config.workbench.editor.enablePreview') }, group: '7_settings', order: 10 }); -MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: MAXIMIZE_EDITOR_GROUP, title: localize('maximizeGroup', "Maximize Group") }, group: '8_group_operations', order: 5, when: ContextKeyExpr.and(MaximizedEditorGroupContext.negate(), MultipleEditorGroupsContext) }); -MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: UNMAXIMIZE_EDITOR_GROUP, title: localize('unmaximizeGroup', "Unmaximize Group") }, group: '8_group_operations', order: 5, when: MaximizedEditorGroupContext }); +MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('maximizeGroup', "Maximize Group") }, group: '8_group_operations', order: 5, when: ContextKeyExpr.and(MaximizedEditorGroupContext.negate(), MultipleEditorGroupsContext) }); +MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('unmaximizeGroup', "Unmaximize Group") }, group: '8_group_operations', order: 5, when: MaximizedEditorGroupContext }); MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_LOCK_GROUP_COMMAND_ID, title: localize('lockGroup', "Lock Group"), toggled: ActiveEditorGroupLockedContext }, group: '8_group_operations', order: 10, when: MultipleEditorGroupsContext }); function appendEditorToolItem(primary: ICommandAction, when: ContextKeyExpression | undefined, order: number, alternative?: ICommandAction, precondition?: ContextKeyExpression | undefined): void { diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index add5520299d..1016fcc0e19 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -13,7 +13,7 @@ import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/bro import { GoFilter, IHistoryService } from 'vs/workbench/services/history/common/history'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { CLOSE_EDITOR_COMMAND_ID, MOVE_ACTIVE_EDITOR_COMMAND_ID, ActiveEditorMoveCopyArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, UNPIN_EDITOR_COMMAND_ID, COPY_ACTIVE_EDITOR_COMMAND_ID, SPLIT_EDITOR, UNMAXIMIZE_EDITOR_GROUP, MAXIMIZE_EDITOR_GROUP, resolveCommandsContext, getCommandsContext, TOGGLE_MAXIMIZE_EDITOR_GROUP } from 'vs/workbench/browser/parts/editor/editorCommands'; +import { CLOSE_EDITOR_COMMAND_ID, MOVE_ACTIVE_EDITOR_COMMAND_ID, ActiveEditorMoveCopyArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, UNPIN_EDITOR_COMMAND_ID, COPY_ACTIVE_EDITOR_COMMAND_ID, SPLIT_EDITOR, resolveCommandsContext, getCommandsContext, TOGGLE_MAXIMIZE_EDITOR_GROUP } from 'vs/workbench/browser/parts/editor/editorCommands'; import { IEditorGroupsService, IEditorGroup, GroupsArrangement, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -1064,23 +1064,6 @@ export class ToggleGroupSizesAction extends Action2 { } } -export class MaximizeGroupAction extends Action2 { - - constructor() { - super({ - id: MAXIMIZE_EDITOR_GROUP, - title: { value: localize('maximizeEditor', "Maximize Editor Group"), original: 'Maximize Editor Group' }, - category: Categories.View, - precondition: ContextKeyExpr.and(MaximizedEditorGroupContext.negate(), MultipleEditorGroupsContext) - }); - } - - override async run(accessor: ServicesAccessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext): Promise { - const editorsGroupService = accessor.get(IEditorGroupsService); - const { group } = resolveCommandsContext(editorsGroupService, getCommandsContext(resourceOrContext, context)); - editorsGroupService.arrangeGroups(GroupsArrangement.MAXIMIZE, group); - } -} export class MaximizeGroupHideSidebarAction extends Action2 { @@ -1107,14 +1090,19 @@ export class MaximizeGroupHideSidebarAction extends Action2 { } } -export class UnmaximizeEditorGroupAction extends Action2 { +export class ToggleMaximizeEditorGroupAction extends Action2 { constructor() { super({ - id: UNMAXIMIZE_EDITOR_GROUP, - title: { value: localize('UnmaximizeEditorGroup', "Unmaximize Editor Group"), original: 'Unmaximize Editor Group' }, + id: TOGGLE_MAXIMIZE_EDITOR_GROUP, + title: { value: localize('toggleMaximizeEditorGroup', "Toggle Maximize Editor Group"), original: 'Toggle Maximize Editor Group' }, + f1: true, category: Categories.View, - precondition: MaximizedEditorGroupContext, + precondition: ContextKeyExpr.or(MultipleEditorGroupsContext, MaximizedEditorGroupContext), + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyM), + }, menu: [{ id: MenuId.EditorTitle, order: -10000, // towards the front @@ -1132,31 +1120,10 @@ export class UnmaximizeEditorGroupAction extends Action2 { }); } - override async run(accessor: ServicesAccessor): Promise { - const editorGroupService = accessor.get(IEditorGroupsService); - editorGroupService.toggleMaximizeGroup(); - } -} - -export class ToggleMaximizeEditorGroupAction extends Action2 { - - constructor() { - super({ - id: TOGGLE_MAXIMIZE_EDITOR_GROUP, - title: { value: localize('toggleMaximizeEditorGroup', "Toggle Maximize Editor Group"), original: 'Toggle Maximize Editor Group' }, - f1: true, - category: Categories.View, - precondition: ContextKeyExpr.or(MultipleEditorGroupsContext, MaximizedEditorGroupContext), - keybinding: { - weight: KeybindingWeight.WorkbenchContrib, - primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyM), - } - }); - } - - override async run(accessor: ServicesAccessor): Promise { - const editorGroupService = accessor.get(IEditorGroupsService); - editorGroupService.toggleMaximizeGroup(); + override async run(accessor: ServicesAccessor, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext): Promise { + const editorGroupsService = accessor.get(IEditorGroupsService); + const { group } = resolveCommandsContext(editorGroupsService, getCommandsContext(resourceOrContext, context)); + editorGroupsService.toggleMaximizeGroup(group); } } diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 61ed3664e64..f8c4178a374 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -80,8 +80,6 @@ export const SPLIT_EDITOR_DOWN = 'workbench.action.splitEditorDown'; export const SPLIT_EDITOR_LEFT = 'workbench.action.splitEditorLeft'; export const SPLIT_EDITOR_RIGHT = 'workbench.action.splitEditorRight'; -export const MAXIMIZE_EDITOR_GROUP = 'workbench.action.maximizeEditorGroup'; -export const UNMAXIMIZE_EDITOR_GROUP = 'workbench.action.unmaximizeEditorGroup'; export const TOGGLE_MAXIMIZE_EDITOR_GROUP = 'workbench.action.toggleMaximizeEditorGroup'; export const SPLIT_EDITOR_IN_GROUP = 'workbench.action.splitEditorInGroup'; @@ -109,7 +107,7 @@ export const EDITOR_CORE_NAVIGATION_COMMANDS = [ CLOSE_EDITOR_COMMAND_ID, UNPIN_EDITOR_COMMAND_ID, UNLOCK_GROUP_COMMAND_ID, - UNMAXIMIZE_EDITOR_GROUP + TOGGLE_MAXIMIZE_EDITOR_GROUP ]; export interface ActiveEditorMoveCopyArguments { From a3f0a14e681d04eb2f3e0dd8458f6579a890badd Mon Sep 17 00:00:00 2001 From: David Dossett Date: Thu, 26 Oct 2023 11:50:30 -0700 Subject: [PATCH 131/162] Add transition delay to avatar --- src/vs/workbench/contrib/chat/browser/media/chat.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/chat/browser/media/chat.css b/src/vs/workbench/contrib/chat/browser/media/chat.css index 519c9564e7c..2d524d8172d 100644 --- a/src/vs/workbench/contrib/chat/browser/media/chat.css +++ b/src/vs/workbench/contrib/chat/browser/media/chat.css @@ -116,6 +116,7 @@ .interactive-item-container .header .agent-avatar-container { margin-left: -30px; transition: margin 0.15s ease-out; + transition-delay: 0.5s; z-index: -1; } From e44dc17a5621783a26065d0a74a03fcb992d07a0 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:54:21 -0700 Subject: [PATCH 132/162] Update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e6fb8906f49..6cf45cda4a6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.84.0", - "distro": "9cdc4175a8604751edba6baf46edfdf56d93173f", + "distro": "9bdd7b6f3973e91fb4dc2d6875dc95095cc7ebc6", "author": { "name": "Microsoft Corporation" }, From 1986bdaa0e3bfc58ff4e73289ca9dec7d9f4ac51 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Oct 2023 20:57:33 +0200 Subject: [PATCH 133/162] Aux window: windows moved to the top stay on top over focused window (fix #196473) (#196751) * Aux window: windows moved to the top stay on top over focused window (fix #196473) * :lipstick: --- src/vs/base/browser/dom.ts | 5 ++++- src/vs/workbench/browser/parts/editor/editorPanes.ts | 7 ++----- src/vs/workbench/electron-sandbox/window.ts | 10 ++++------ .../electron-sandbox/auxiliaryWindowService.ts | 8 +++----- .../host/electron-sandbox/nativeHostService.ts | 6 +++--- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 764008eaf58..c893e9ef1bd 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -17,7 +17,7 @@ import { FileAccess, RemoteAuthorities, Schemas } from 'vs/base/common/network'; import * as platform from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; -export const { registerWindow, getWindows, onDidRegisterWindow, onWillUnregisterWindow, onDidUnregisterWindow } = (function () { +export const { registerWindow, getWindows, getWindowsCount, onDidRegisterWindow, onWillUnregisterWindow, onDidUnregisterWindow } = (function () { const windows = new Set([window]); const onDidRegisterWindow = new event.Emitter<{ window: Window & typeof globalThis; disposables: DisposableStore }>(); const onDidUnregisterWindow = new event.Emitter(); @@ -51,6 +51,9 @@ export const { registerWindow, getWindows, onDidRegisterWindow, onWillUnregister }, getWindows(): Iterable { return windows; + }, + getWindowsCount(): number { + return windows.size; } }; })(); diff --git a/src/vs/workbench/browser/parts/editor/editorPanes.ts b/src/vs/workbench/browser/parts/editor/editorPanes.ts index ff42c12e1f4..571f0224217 100644 --- a/src/vs/workbench/browser/parts/editor/editorPanes.ts +++ b/src/vs/workbench/browser/parts/editor/editorPanes.ts @@ -10,7 +10,7 @@ import Severity from 'vs/base/common/severity'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { EditorExtensions, EditorInputCapabilities, IEditorOpenContext, IVisibleEditorPane, createEditorOpenError, isEditorOpenError } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; -import { Dimension, show, hide, IDomNodePagePosition, isAncestor, getWindow, getActiveWindow } from 'vs/base/browser/dom'; +import { Dimension, show, hide, IDomNodePagePosition, isAncestor, getWindow } from 'vs/base/browser/dom'; import { Registry } from 'vs/platform/registry/common/platform'; import { IEditorPaneRegistry, IEditorPaneDescriptor } from 'vs/workbench/browser/editor'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; @@ -277,10 +277,7 @@ export class EditorPanes extends Disposable { if (focus && this.shouldRestoreFocus(activeElement)) { pane.focus(); } else if (!internalOptions?.preserveWindowOrder) { - const paneWindow = getWindow(pane.getContainer()); - if (paneWindow !== getActiveWindow()) { - this.hostService.moveTop(paneWindow); - } + this.hostService.moveTop(getWindow(pane.getContainer())); } } diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts index dbdae46a49f..0c606c68a2c 100644 --- a/src/vs/workbench/electron-sandbox/window.ts +++ b/src/vs/workbench/electron-sandbox/window.ts @@ -679,14 +679,12 @@ export class NativeWindow extends Disposable { // https://github.com/electron/electron/issues/25578 const that = this; const originalWindowFocus = window.focus.bind(window); - window.focus = async function () { - if (getActiveWindow() === window) { - return; - } - + window.focus = function () { originalWindowFocus(); - await that.nativeHostService.focusWindow(); + if (getActiveWindow() !== window) { + that.nativeHostService.focusWindow(); + } }; } diff --git a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts index dc2bd94711a..39137a1de06 100644 --- a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts +++ b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts @@ -69,13 +69,11 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService const that = this; const originalWindowFocus = auxiliaryWindow.focus.bind(auxiliaryWindow); auxiliaryWindow.focus = async function () { - if (getActiveWindow() === auxiliaryWindow) { - return; - } - originalWindowFocus(); - await that.nativeHostService.focusWindow({ targetWindowId: await windowId.p }); + if (getActiveWindow() === auxiliaryWindow) { + that.nativeHostService.focusWindow({ targetWindowId: await windowId.p }); + } }; } } diff --git a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts index 47b619b855f..9c1cd113aaf 100644 --- a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts +++ b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts @@ -15,7 +15,7 @@ import { NativeHostService } from 'vs/platform/native/electron-sandbox/nativeHos import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; import { IMainProcessService } from 'vs/platform/ipc/common/mainProcessService'; import { isAuxiliaryWindow } from 'vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService'; -import { getActiveDocument, getActiveWindow, onDidRegisterWindow, trackFocus } from 'vs/base/browser/dom'; +import { getActiveDocument, getWindowsCount, onDidRegisterWindow, trackFocus } from 'vs/base/browser/dom'; import { DomEmitter } from 'vs/base/browser/event'; import { memoize } from 'vs/base/common/decorators'; @@ -134,8 +134,8 @@ class WorkbenchHostService extends Disposable implements IHostService { } async moveTop(window: Window & typeof globalThis): Promise { - if (getActiveWindow() === window) { - return; + if (getWindowsCount() <= 1) { + return; // does not apply when only one window is opened } return this.nativeHostService.moveWindowTop(isAuxiliaryWindow(window) ? { targetWindowId: await window.vscodeWindowId } : undefined); From 7ad1fb31dc002f0aab1ec0b9d800aac0df26f9f6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Oct 2023 21:03:45 +0200 Subject: [PATCH 134/162] Aux window: Alt+f4 closes the workspace instead of the aux window (fix #196239) (#196752) --- src/vs/workbench/electron-sandbox/actions/windowActions.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/electron-sandbox/actions/windowActions.ts b/src/vs/workbench/electron-sandbox/actions/windowActions.ts index b174c469230..d7471d3cd8f 100644 --- a/src/vs/workbench/electron-sandbox/actions/windowActions.ts +++ b/src/vs/workbench/electron-sandbox/actions/windowActions.ts @@ -62,6 +62,11 @@ export class CloseWindowAction extends Action2 { override async run(accessor: ServicesAccessor): Promise { const nativeHostService = accessor.get(INativeHostService); + const window = getActiveWindow(); + if (isAuxiliaryWindow(window)) { + return nativeHostService.closeWindowById(await window.vscodeWindowId); + } + return nativeHostService.closeWindow(); } } From 041313bea584743ae251e79ff0cc2bce34ec1c7e Mon Sep 17 00:00:00 2001 From: Bhavya U Date: Thu, 26 Oct 2023 12:06:26 -0700 Subject: [PATCH 135/162] Ask for confirmation before performing entitlement command (#196750) --- src/vs/base/common/product.ts | 3 +- .../accountsEntitlements.contribution.ts | 48 ++++++------------- 2 files changed, 17 insertions(+), 34 deletions(-) diff --git a/src/vs/base/common/product.ts b/src/vs/base/common/product.ts index 379e47bb719..61a1623d76d 100644 --- a/src/vs/base/common/product.ts +++ b/src/vs/base/common/product.ts @@ -293,8 +293,9 @@ export interface IAiGeneratedWorkspaceTrust { export interface IGitHubEntitlement { providerId: string; command: { title: string; titleWithoutPlaceHolder: string; action: string; when: string }; - altCommand: { title: string; action: string; when: string }; entitlementUrl: string; extensionId: string; enablementKey: string; + confirmationMessage: string; + confirmationAction: string; } diff --git a/src/vs/workbench/contrib/accountEntitlements/browser/accountsEntitlements.contribution.ts b/src/vs/workbench/contrib/accountEntitlements/browser/accountsEntitlements.contribution.ts index 6013c1c2af2..15ba6dea7e1 100644 --- a/src/vs/workbench/contrib/accountEntitlements/browser/accountsEntitlements.contribution.ts +++ b/src/vs/workbench/contrib/accountEntitlements/browser/accountsEntitlements.contribution.ts @@ -7,11 +7,10 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; -import { ContextKeyExpr, ContextKeyTrueExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { ContextKeyExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IOpenerService } from 'vs/platform/opener/common/opener'; import { AuthenticationSession, IAuthenticationService } from 'vs/workbench/services/authentication/common/authentication'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; @@ -26,6 +25,7 @@ import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IRequestService, asText } from 'vs/platform/request/common/request'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; const configurationKey = 'workbench.accounts.experimental.showEntitlements'; @@ -35,10 +35,8 @@ class AccountsEntitlement extends Disposable implements IWorkbenchContribution { constructor( @IContextKeyService readonly contextService: IContextKeyService, - @IInstantiationService readonly instantiationService: IInstantiationService, @ICommandService readonly commandService: ICommandService, @ITelemetryService readonly telemetryService: ITelemetryService, - @IOpenerService readonly openerService: IOpenerService, @IAuthenticationService readonly authenticationService: IAuthenticationService, @IProductService readonly productService: IProductService, @IStorageService readonly storageService: IStorageService, @@ -168,40 +166,24 @@ class AccountsEntitlement extends Disposable implements IWorkbenchContribution { const commandService = accessor.get(ICommandService); const contextKeyService = accessor.get(IContextKeyService); const storageService = accessor.get(IStorageService); - commandService.executeCommand(productService.gitHubEntitlement!.command.action, productService.gitHubEntitlement!.extensionId!); + const dialogService = accessor.get(IDialogService); + + const confirmation = await dialogService.confirm({ + type: 'question', + message: productService.gitHubEntitlement!.confirmationMessage, + primaryButton: productService.gitHubEntitlement!.confirmationAction, + }); + + if (confirmation.confirmed) { + commandService.executeCommand(productService.gitHubEntitlement!.command.action, productService.gitHubEntitlement!.extensionId!); + } + accountsMenuBadgeDisposable.clear(); const contextKey = new RawContextKey(configurationKey, true).bindTo(contextKeyService); contextKey.set(false); storageService.store(configurationKey, false, StorageScope.APPLICATION, StorageTarget.MACHINE); } }); - - const altMenuTitle = this.productService.gitHubEntitlement!.altCommand.title!; - const altContextKey = this.productService.gitHubEntitlement!.altCommand.when; - - registerAction2(class extends Action2 { - constructor() { - super({ - id: 'workbench.action.entitlementAltAction', - title: altMenuTitle, - f1: false, - toggled: ContextKeyTrueExpr.INSTANCE, - menu: { - id: MenuId.AccountsContext, - group: '5_AccountsEntitlements', - when: ContextKeyExpr.equals(altContextKey, true), - } - }); - } - - public async run( - accessor: ServicesAccessor - ) { - const productService = accessor.get(IProductService); - const commandService = accessor.get(ICommandService); - commandService.executeCommand(productService.gitHubEntitlement!.altCommand.action, productService.gitHubEntitlement!.extensionId!); - } - }); } } From d8a9938fc226008c3ca21f351198eebbf0c918de Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 26 Oct 2023 13:12:59 -0700 Subject: [PATCH 136/162] Improve styling of terminal dev mode text box Fixes #196757 --- .../terminal/browser/media/terminal.css | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index c222df0deb8..5c30094e8b9 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -53,14 +53,26 @@ outline: 0 !important; } -.xterm.dev-mode .xterm-helper-textarea { +.monaco-workbench .xterm.dev-mode .xterm-helper-textarea { z-index: 36 !important; - opacity: 1 !important; - left: 0 !important; - width: fit-content !important; + opacity: 0.8 !important; + right: 0 !important; + left: initial !important; + width: 50% !important; + background-color: var(--vscode-terminal-background, var(--vscode-panel-background)); + color: var(--vscode-terminal-foreground); + transform: translateY(-100%); } .monaco-workbench .xterm.dev-mode .xterm-helper-textarea:focus { - opacity: 1 !important; + opacity: 0.8 !important; +} +.monaco-workbench .xterm.dev-mode .xterm-helpers { + /* This could maybe be done outside of .dev-mode, but I'm scared to break something */ + left: 0; + right: 0; +} +.monaco-workbench .xterm.dev-mode .xterm-helper-textarea:hover { + opacity: 0.25 !important; } .monaco-workbench .xterm .xterm-helper-textarea:focus { From f4408924cbc2a2da28c65e0b438eb9eebe6aae11 Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Thu, 26 Oct 2023 21:18:02 +0100 Subject: [PATCH 137/162] Show outer ring of progress clock on top activity bar badges --- src/vs/workbench/browser/parts/media/paneCompositePart.css | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/media/paneCompositePart.css b/src/vs/workbench/browser/parts/media/paneCompositePart.css index c39e25cde76..c4c160fcfe6 100644 --- a/src/vs/workbench/browser/parts/media/paneCompositePart.css +++ b/src/vs/workbench/browser/parts/media/paneCompositePart.css @@ -185,9 +185,10 @@ } .monaco-workbench .pane-composite-part > .title > .composite-bar-container > .composite-bar > .monaco-action-bar .action-item.icon .badge.compact.progress-badge .badge-content::before { - mask-size: 13px; - -webkit-mask-size: 13px; - top: 2px; + mask-size: 11px; + -webkit-mask-size: 11px; + top: 3px; + left: 1px; } /* active item indicator */ From 161abae7c76a8fe392b63344e17417640e8f0fde Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 26 Oct 2023 15:25:17 -0700 Subject: [PATCH 138/162] fix #194672 --- src/vs/workbench/contrib/search/browser/searchView.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 6bc3f38e680..593545994a1 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -30,7 +30,7 @@ import { IEditor } from 'vs/editor/common/editorCommon'; import { CommonFindController } from 'vs/editor/contrib/find/browser/findController'; import { MultiCursorSelectionController } from 'vs/editor/contrib/multicursor/browser/multicursor'; import * as nls from 'vs/nls'; -import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; +import { AccessibleNotificationEvent, IAccessibilityService, IAccessibleNotificationService } from 'vs/platform/accessibility/common/accessibility'; import { MenuId } from 'vs/platform/actions/common/actions'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -189,6 +189,7 @@ export class SearchView extends ViewPane { @ITelemetryService telemetryService: ITelemetryService, @INotebookService private readonly notebookService: INotebookService, @ILogService private readonly logService: ILogService, + @IAccessibleNotificationService private readonly accessibleNotificationService: IAccessibleNotificationService ) { super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService); @@ -1245,7 +1246,7 @@ export class SearchView extends ViewPane { this.viewModel.cancelSearch(); this.tree.ariaLabel = nls.localize('emptySearch', "Empty Search"); - aria.status(nls.localize('ariaSearchResultsClearStatus', "The search results have been cleared")); + this.accessibleNotificationService.notify(AccessibleNotificationEvent.Clear); this.reLayout(); } From 1bb06e81e49467aa89a58539dcd33a9632de47fc Mon Sep 17 00:00:00 2001 From: meganrogge Date: Thu, 26 Oct 2023 15:46:03 -0700 Subject: [PATCH 139/162] never alert if audio cue is set --- .../accessibility/browser/accessibleNotificationService.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleNotificationService.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleNotificationService.ts index 407af81c487..5afd59cd2e3 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleNotificationService.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleNotificationService.ts @@ -57,6 +57,10 @@ export class AccessibleNotificationService extends Disposable implements IAccess this._audioCueService.playSound(audioCue.sound.getSound(), true); return; } + if (audioCueSetting !== 'never') { + // Never do both sound and alert + return; + } const alertSettingValue: NotificationSetting = this._configurationService.getValue(alertSetting); if (this._shouldNotify(alertSettingValue, userGesture)) { this._logService.debug('AccessibleNotificationService alerting: ', alertMessage); From 89e6f7ec9e1bbd0a51b9c646acecef18b1157ba2 Mon Sep 17 00:00:00 2001 From: Raymond Zhao <7199958+rzhao271@users.noreply.github.com> Date: Thu, 26 Oct 2023 15:54:27 -0700 Subject: [PATCH 140/162] Remove assignment service from toggle data fetch (#196767) --- .../contrib/preferences/browser/settingsEditor2.ts | 4 +--- src/vs/workbench/contrib/preferences/common/preferences.ts | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 190ae19245f..ee6eb4c4a98 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -62,7 +62,6 @@ import { ISettingOverrideClickEvent } from 'vs/workbench/contrib/preferences/bro import { ConfigurationScope, Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; import { defaultButtonStyles } from 'vs/platform/theme/browser/defaultStyles'; -import { IWorkbenchAssignmentService } from 'vs/workbench/services/assignment/common/assignmentService'; import { IProductService } from 'vs/platform/product/common/productService'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { registerNavigableContainer } from 'vs/workbench/browser/actions/widgetNavigationCommands'; @@ -237,7 +236,6 @@ export class SettingsEditor2 extends EditorPane { @IExtensionService private readonly extensionService: IExtensionService, @ILanguageService private readonly languageService: ILanguageService, @IExtensionManagementService extensionManagementService: IExtensionManagementService, - @IWorkbenchAssignmentService private readonly workbenchAssignmentService: IWorkbenchAssignmentService, @IProductService private readonly productService: IProductService, @IEnvironmentService private readonly environmentService: IEnvironmentService, @IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService, @@ -1291,7 +1289,7 @@ export class SettingsEditor2 extends EditorPane { } const additionalGroups: ISettingsGroup[] = []; - const toggleData = await getExperimentalExtensionToggleData(this.extensionGalleryService, this.workbenchAssignmentService, this.environmentService, this.productService); + const toggleData = await getExperimentalExtensionToggleData(this.extensionGalleryService, this.environmentService, this.productService); if (toggleData && groups.filter(g => g.extensionInfo).length) { for (const key in toggleData.settingsEditorRecommendedExtensions) { const extension = toggleData.recommendedExtensionsGalleryInfo[key]; diff --git a/src/vs/workbench/contrib/preferences/common/preferences.ts b/src/vs/workbench/contrib/preferences/common/preferences.ts index 589a55cad97..c741a93849d 100644 --- a/src/vs/workbench/contrib/preferences/common/preferences.ts +++ b/src/vs/workbench/contrib/preferences/common/preferences.ts @@ -11,7 +11,6 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IExtensionGalleryService, IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IProductService } from 'vs/platform/product/common/productService'; -import { IWorkbenchAssignmentService } from 'vs/workbench/services/assignment/common/assignmentService'; import { ISearchResult, ISettingsEditorModel } from 'vs/workbench/services/preferences/common/preferences'; export interface IWorkbenchSettingsConfiguration { @@ -108,7 +107,7 @@ export type ExtensionToggleData = { let cachedExtensionToggleData: ExtensionToggleData | undefined; -export async function getExperimentalExtensionToggleData(extensionGalleryService: IExtensionGalleryService, workbenchAssignmentService: IWorkbenchAssignmentService, environmentService: IEnvironmentService, productService: IProductService): Promise { +export async function getExperimentalExtensionToggleData(extensionGalleryService: IExtensionGalleryService, environmentService: IEnvironmentService, productService: IProductService): Promise { if (!ENABLE_EXTENSION_TOGGLE_SETTINGS) { return undefined; } @@ -121,8 +120,7 @@ export async function getExperimentalExtensionToggleData(extensionGalleryService return cachedExtensionToggleData; } - const isTreatment = await workbenchAssignmentService.getTreatment('ExtensionToggleSettings'); - if ((isTreatment || !environmentService.isBuilt) && productService.extensionRecommendations && productService.commonlyUsedSettings) { + if (!environmentService.isBuilt && productService.extensionRecommendations && productService.commonlyUsedSettings) { const settingsEditorRecommendedExtensions: IStringDictionary = {}; Object.keys(productService.extensionRecommendations).forEach(extensionId => { const extensionInfo = productService.extensionRecommendations![extensionId]; From e07a64278e3de2f01e4f13cf4cc4376279e4aeb4 Mon Sep 17 00:00:00 2001 From: Bhavya U Date: Thu, 26 Oct 2023 18:00:11 -0700 Subject: [PATCH 141/162] Add telemetry for account entitlement (#196772) * Add telemetry for account entitlements * Fix badge display --- .../accountsEntitlements.contribution.ts | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/accountEntitlements/browser/accountsEntitlements.contribution.ts b/src/vs/workbench/contrib/accountEntitlements/browser/accountsEntitlements.contribution.ts index 15ba6dea7e1..44169a00242 100644 --- a/src/vs/workbench/contrib/accountEntitlements/browser/accountsEntitlements.contribution.ts +++ b/src/vs/workbench/contrib/accountEntitlements/browser/accountsEntitlements.contribution.ts @@ -29,6 +29,18 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; const configurationKey = 'workbench.accounts.experimental.showEntitlements'; +type EntitlementEnablementClassification = { + enabled: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'Flag indicating if the account entitlement is enabled' }; + owner: 'bhavyaus'; + comment: 'Reporting when the account entitlement is shown'; +}; + +type EntitlementActionClassification = { + command: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comment: 'The command being executed by the entitlement action' }; + owner: 'bhavyaus'; + comment: 'Reporting the account entitlement action'; +}; + class AccountsEntitlement extends Disposable implements IWorkbenchContribution { private isInitialized = false; private contextKey = new RawContextKey(configurationKey, true).bindTo(this.contextService); @@ -136,15 +148,17 @@ class AccountsEntitlement extends Disposable implements IWorkbenchContribution { return; } - const accountsMenuBadgeDisposable = this._register(new MutableDisposable()); - this.contextKey.set(true); - const badge = new NumberBadge(1, () => menuTitle); - accountsMenuBadgeDisposable.value = this.activityService.showAccountsActivity({ badge, }); + this.telemetryService.publicLog2<{ enabled: boolean }, EntitlementEnablementClassification>(configurationKey, { enabled: true }); const orgs = parsedResult['organization_login_list'] as any[]; const menuTitle = orgs ? this.productService.gitHubEntitlement!.command.title.replace('{{org}}', orgs[orgs.length - 1]) : this.productService.gitHubEntitlement!.command.titleWithoutPlaceHolder; + const badge = new NumberBadge(1, () => menuTitle); + const accountsMenuBadgeDisposable = this._register(new MutableDisposable()); + accountsMenuBadgeDisposable.value = this.activityService.showAccountsActivity({ badge, }); + + registerAction2(class extends Action2 { constructor() { super({ @@ -167,6 +181,7 @@ class AccountsEntitlement extends Disposable implements IWorkbenchContribution { const contextKeyService = accessor.get(IContextKeyService); const storageService = accessor.get(IStorageService); const dialogService = accessor.get(IDialogService); + const telemetryService = accessor.get(ITelemetryService); const confirmation = await dialogService.confirm({ type: 'question', @@ -176,6 +191,13 @@ class AccountsEntitlement extends Disposable implements IWorkbenchContribution { if (confirmation.confirmed) { commandService.executeCommand(productService.gitHubEntitlement!.command.action, productService.gitHubEntitlement!.extensionId!); + telemetryService.publicLog2<{ command: string }, EntitlementActionClassification>('accountsEntitlements.action', { + command: productService.gitHubEntitlement!.command.action, + }); + } else { + telemetryService.publicLog2<{ command: string }, EntitlementActionClassification>('accountsEntitlements.action', { + command: productService.gitHubEntitlement!.command.action + '-dismissed', + }); } accountsMenuBadgeDisposable.clear(); From df99ffae5391beb4cc2f947d4dfc37cb85fe3ede Mon Sep 17 00:00:00 2001 From: Bhavya U Date: Thu, 26 Oct 2023 18:27:33 -0700 Subject: [PATCH 142/162] Update distro (#196778) Bump distro --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6cf45cda4a6..42feba8d1d1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.84.0", - "distro": "9bdd7b6f3973e91fb4dc2d6875dc95095cc7ebc6", + "distro": "ff0198cd90b25ba7ca853279cea9b8bb3cf5164d", "author": { "name": "Microsoft Corporation" }, @@ -227,4 +227,4 @@ "optionalDependencies": { "windows-foreground-love": "0.5.0" } -} +} \ No newline at end of file From 1403feed24bd2ad8d1ab2edb91cd0419275713ef Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 26 Oct 2023 20:52:21 -0700 Subject: [PATCH 143/162] Fix empty chat icons after upgrade Don't fall back on the persisted icon if the current session doesn't have one --- src/vs/workbench/contrib/chat/common/chatModel.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/chat/common/chatModel.ts b/src/vs/workbench/contrib/chat/common/chatModel.ts index 373065274f9..471764b058f 100644 --- a/src/vs/workbench/contrib/chat/common/chatModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatModel.ts @@ -522,12 +522,12 @@ export class ChatModel extends Disposable implements IChatModel { private readonly _initialRequesterAvatarIconUri: URI | undefined; get requesterAvatarIconUri(): URI | undefined { - return this._session?.requesterAvatarIconUri ?? this._initialRequesterAvatarIconUri; + return this._session ? this._session.requesterAvatarIconUri : this._initialRequesterAvatarIconUri; } private readonly _initialResponderAvatarIconUri: URI | undefined; get responderAvatarIconUri(): URI | undefined { - return this._session?.responderAvatarIconUri ?? this._initialResponderAvatarIconUri; + return this._session ? this._session.responderAvatarIconUri : this._initialResponderAvatarIconUri; } get initState(): ChatModelInitState { From 47a0ab66a0310544896158f3f519bea13a31bdd7 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Oct 2023 08:10:39 +0200 Subject: [PATCH 144/162] aux window - fix CSS cloning (#196788) * aux window - fix CSS cloning * :lipstick: --- src/vs/base/browser/dom.ts | 28 ++++++++++++------- .../unfocusedViewDimmingContribution.ts | 4 +-- .../contrib/tasks/browser/taskQuickPick.ts | 5 ++-- .../contrib/terminal/browser/terminalIcon.ts | 8 ++++-- .../terminal/browser/terminalInstance.ts | 7 ++--- .../browser/terminalProfileQuickpick.ts | 7 ++--- .../terminal/browser/terminalService.ts | 3 +- .../contrib/terminal/browser/terminalView.ts | 8 ++---- .../browser/auxiliaryWindowService.ts | 6 ++-- .../themes/browser/workbenchThemeService.ts | 4 +-- 10 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index c893e9ef1bd..30a25285bc5 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -798,12 +798,11 @@ export function createStyleSheet(container: HTMLElement = document.head, beforeA continue; // main window is already tracked } - const clone = cloneGlobalStyleSheet(style, targetWindow); - clonedGlobalStylesheets.add(clone); + const disposable = cloneGlobalStyleSheet(style, targetWindow); event.Event.once(onDidUnregisterWindow)(unregisteredWindow => { if (unregisteredWindow === targetWindow) { - clonedGlobalStylesheets.delete(clone); + disposable.dispose(); } }); } @@ -819,17 +818,14 @@ export function isGlobalStylesheet(node: Node): boolean { export function cloneGlobalStylesheets(targetWindow: Window & typeof globalThis): IDisposable { const disposables = new DisposableStore(); - for (const [globalStylesheet, clonedGlobalStylesheets] of globalStylesheets) { - const clone = cloneGlobalStyleSheet(globalStylesheet, targetWindow); - - clonedGlobalStylesheets.add(clone); - disposables.add(toDisposable(() => clonedGlobalStylesheets.delete(clone))); + for (const [globalStylesheet] of globalStylesheets) { + disposables.add(cloneGlobalStyleSheet(globalStylesheet, targetWindow)); } return disposables; } -function cloneGlobalStyleSheet(globalStylesheet: HTMLStyleElement, targetWindow: Window & typeof globalThis): HTMLStyleElement { +function cloneGlobalStyleSheet(globalStylesheet: HTMLStyleElement, targetWindow: Window & typeof globalThis): IDisposable { const clone = globalStylesheet.cloneNode(true) as HTMLStyleElement; targetWindow.document.head.appendChild(clone); @@ -837,7 +833,19 @@ function cloneGlobalStyleSheet(globalStylesheet: HTMLStyleElement, targetWindow: clone.sheet?.insertRule(rule.cssText, clone.sheet?.cssRules.length); } - return clone; + const observer = new MutationObserver(() => { + clone.textContent = globalStylesheet.textContent; + }); + observer.observe(globalStylesheet, { childList: true }); + + globalStylesheets.get(globalStylesheet)?.add(clone); + + return toDisposable(() => { + observer.disconnect(); + targetWindow.document.head.removeChild(clone); + + globalStylesheets.get(globalStylesheet)?.delete(clone); + }); } export function createMetaElement(container: HTMLElement = document.head): HTMLMetaElement { diff --git a/src/vs/workbench/contrib/accessibility/browser/unfocusedViewDimmingContribution.ts b/src/vs/workbench/contrib/accessibility/browser/unfocusedViewDimmingContribution.ts index 0cd7d898147..9319c21af7f 100644 --- a/src/vs/workbench/contrib/accessibility/browser/unfocusedViewDimmingContribution.ts +++ b/src/vs/workbench/contrib/accessibility/browser/unfocusedViewDimmingContribution.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { createStyleSheet } from 'vs/base/browser/dom'; import { Event } from 'vs/base/common/event'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { clamp } from 'vs/base/common/numbers'; @@ -73,9 +74,8 @@ export class UnfocusedViewDimmingContribution extends Disposable implements IWor private _getStyleElement(): HTMLStyleElement { if (!this._styleElement) { - this._styleElement = document.createElement('style'); + this._styleElement = createStyleSheet(); this._styleElement.className = 'accessibilityUnfocusedViewOpacity'; - document.head.appendChild(this._styleElement); } return this._styleElement; } diff --git a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts index 3ae4804392e..3c15935f60a 100644 --- a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts +++ b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts @@ -19,7 +19,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ThemeIcon } from 'vs/base/common/themables'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { getColorClass, getColorStyleElement } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; +import { getColorClass, createColorStyleElement } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; import { TaskQuickPickEntryType } from 'vs/workbench/contrib/tasks/browser/abstractTaskService'; import { showWithPinnedItems } from 'vs/platform/quickinput/browser/quickPickPin'; import { IStorageService } from 'vs/platform/storage/common/storage'; @@ -93,9 +93,8 @@ export class TaskQuickPick extends Disposable { public static applyColorStyles(task: Task | ConfiguringTask, entry: TaskQuickPickEntryType | ITaskTwoLevelQuickPickEntry, themeService: IThemeService): void { if (task.configurationProperties.icon?.color) { const colorTheme = themeService.getColorTheme(); - const styleElement = getColorStyleElement(colorTheme); + createColorStyleElement(colorTheme); entry.iconClasses = [getColorClass(task.configurationProperties.icon.color)]; - document.body.appendChild(styleElement); } } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalIcon.ts b/src/vs/workbench/contrib/terminal/browser/terminalIcon.ts index 178224f230c..07b474a831f 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalIcon.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalIcon.ts @@ -14,6 +14,8 @@ import { ThemeIcon } from 'vs/base/common/themables'; import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; import { ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal'; import { ansiColorMap } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; +import { createStyleSheet } from 'vs/base/browser/dom'; +import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; export function getColorClass(colorKey: string): string; @@ -47,9 +49,9 @@ export function getStandardColors(colorTheme: IColorTheme): string[] { return standardColors; } -export function getColorStyleElement(colorTheme: IColorTheme): HTMLElement { +export function createColorStyleElement(colorTheme: IColorTheme): IDisposable { const standardColors = getStandardColors(colorTheme); - const styleElement = document.createElement('style'); + const styleElement = createStyleSheet(); let css = ''; for (const colorKey of standardColors) { const colorClass = getColorClass(colorKey); @@ -62,7 +64,7 @@ export function getColorStyleElement(colorTheme: IColorTheme): HTMLElement { } } styleElement.textContent = css; - return styleElement; + return toDisposable(() => styleElement.remove()); } export function getColorStyleContent(colorTheme: IColorTheme, editor?: boolean): string { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 751c368ded3..1b001ae9433 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -63,7 +63,7 @@ import { TerminalLaunchHelpAction } from 'vs/workbench/contrib/terminal/browser/ import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput'; import { TerminalExtensionsRegistry } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; -import { getColorClass, getColorStyleElement, getStandardColors } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; +import { getColorClass, createColorStyleElement, getStandardColors } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/terminalProcessManager'; import { showRunRecentQuickPick } from 'vs/workbench/contrib/terminal/browser/terminalRunRecentQuickPick'; import { ITerminalStatusList, TerminalStatus, TerminalStatusList } from 'vs/workbench/contrib/terminal/browser/terminalStatusList'; @@ -2200,7 +2200,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } const colorTheme = this._themeService.getColorTheme(); const standardColors: string[] = getStandardColors(colorTheme); - const styleElement = getColorStyleElement(colorTheme); + const colorStyleDisposable = createColorStyleElement(colorTheme); const items: QuickPickItem[] = []; for (const colorKey of standardColors) { const colorClass = getColorClass(colorKey); @@ -2211,7 +2211,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { items.push({ type: 'separator' }); const showAllColorsItem = { label: 'Reset to default' }; items.push(showAllColorsItem); - document.body.appendChild(styleElement); const quickPick = this._quickInputService.createQuickPick(); quickPick.items = items; @@ -2231,7 +2230,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } quickPick.hide(); - document.body.removeChild(styleElement); + colorStyleDisposable.dispose(); } selectPreviousSuggestion(): void { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProfileQuickpick.ts b/src/vs/workbench/contrib/terminal/browser/terminalProfileQuickpick.ts index 5701de1746e..b7afa342a67 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProfileQuickpick.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProfileQuickpick.ts @@ -7,7 +7,7 @@ import { Codicon } from 'vs/base/common/codicons'; import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IQuickInputService, IKeyMods, IPickOptions, IQuickPickSeparator, IQuickInputButton, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { IExtensionTerminalProfile, ITerminalProfile, ITerminalProfileObject, TerminalSettingPrefix } from 'vs/platform/terminal/common/terminal'; -import { getUriClasses, getColorClass, getColorStyleElement } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; +import { getUriClasses, getColorClass, createColorStyleElement } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; import { configureTerminalProfileIcon } from 'vs/workbench/contrib/terminal/browser/terminalIcons'; import * as nls from 'vs/nls'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -196,11 +196,10 @@ export class TerminalProfileQuickpick { quickPickItems.push({ type: 'separator', label: nls.localize('terminalProfiles.detected', "detected") }); quickPickItems.push(...this._sortProfileQuickPickItems(autoDetectedProfiles.map(e => this._createProfileQuickPickItem(e)), defaultProfileName!)); } - const styleElement = getColorStyleElement(this._themeService.getColorTheme()); - document.body.appendChild(styleElement); + const colorStyleDisposable = createColorStyleElement(this._themeService.getColorTheme()); const result = await this._quickInputService.pick(quickPickItems, options); - document.body.removeChild(styleElement); + colorStyleDisposable.dispose(); if (!result) { return undefined; } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index e8c703a704d..0b03a49122d 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -1195,8 +1195,7 @@ class TerminalEditorStyle extends Themable { ) { super(_themeService); this._registerListeners(); - this._styleElement = document.createElement('style'); - container.appendChild(this._styleElement); + this._styleElement = dom.createStyleSheet(container); this._register(toDisposable(() => container.removeChild(this._styleElement))); this.updateStyles(); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalView.ts b/src/vs/workbench/contrib/terminal/browser/terminalView.ts index c96ffb835c4..2c775e39639 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalView.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalView.ts @@ -49,7 +49,6 @@ import { IHoverService } from 'vs/workbench/services/hover/browser/hover'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; export class TerminalViewPane extends ViewPane { - private _fontStyleElement: HTMLElement | undefined; private _parentDomElement: HTMLElement | undefined; private _terminalTabbedView?: TerminalTabbedView; get terminalTabbedView(): TerminalTabbedView | undefined { return this._terminalTabbedView; } @@ -178,15 +177,13 @@ export class TerminalViewPane extends ViewPane { } this._parentDomElement = container; this._parentDomElement.classList.add('integrated-terminal'); - this._fontStyleElement = document.createElement('style'); + dom.createStyleSheet(this._parentDomElement); this._instantiationService.createInstance(TerminalThemeIconStyle, this._parentDomElement); if (!this.shouldShowWelcome()) { this._createTabsView(); } - this._parentDomElement.appendChild(this._fontStyleElement); - this._register(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(TerminalSettingId.FontFamily) || e.affectsConfiguration('editor.fontFamily')) { const configHelper = this._terminalService.configHelper; @@ -558,8 +555,7 @@ class TerminalThemeIconStyle extends Themable { ) { super(_themeService); this._registerListeners(); - this._styleElement = document.createElement('style'); - container.appendChild(this._styleElement); + this._styleElement = dom.createStyleSheet(container); this._register(toDisposable(() => container.removeChild(this._styleElement))); this.updateStyles(); } diff --git a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts index c91995c436a..6cf0b30d30c 100644 --- a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts +++ b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts @@ -5,7 +5,7 @@ import { localize } from 'vs/nls'; import { Emitter, Event } from 'vs/base/common/event'; -import { Dimension, EventHelper, EventType, addDisposableListener, cloneGlobalStylesheets, copyAttributes, getActiveWindow, getClientArea, isGlobalStylesheet, position, registerWindow, size, trackAttributes } from 'vs/base/browser/dom'; +import { Dimension, EventHelper, EventType, addDisposableListener, cloneGlobalStylesheets, copyAttributes, createMetaElement, getActiveWindow, getClientArea, isGlobalStylesheet, position, registerWindow, size, trackAttributes } from 'vs/base/browser/dom'; 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'; @@ -135,12 +135,12 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili } private applyMeta(auxiliaryWindow: AuxiliaryWindow): void { - const metaCharset = auxiliaryWindow.document.head.appendChild(document.createElement('meta')); + const metaCharset = createMetaElement(auxiliaryWindow.document.head); metaCharset.setAttribute('charset', 'utf-8'); const originalCSPMetaTag = document.querySelector('meta[http-equiv="Content-Security-Policy"]'); if (originalCSPMetaTag) { - const csp = auxiliaryWindow.document.head.appendChild(document.createElement('meta')); + const csp = createMetaElement(auxiliaryWindow.document.head); copyAttributes(originalCSPMetaTag, csp); const content = csp.getAttribute('content'); diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index e82e03d208a..102ed180103 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -873,11 +873,9 @@ class ThemeFileWatcher { function _applyRules(styleSheetContent: string, rulesClassName: string) { const themeStyles = document.head.getElementsByClassName(rulesClassName); if (themeStyles.length === 0) { - const elStyle = document.createElement('style'); - elStyle.type = 'text/css'; + const elStyle = createStyleSheet(); elStyle.className = rulesClassName; elStyle.textContent = styleSheetContent; - document.head.appendChild(elStyle); } else { (themeStyles[0]).textContent = styleSheetContent; } From 2ff3e98d7747f922188bb4c7eca2c28733f3ae51 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Oct 2023 08:40:53 +0200 Subject: [PATCH 145/162] Aux window: `window.focus` is broken (fix #196790) (#196791) --- .../auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts index 39137a1de06..4787b33d38a 100644 --- a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts +++ b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts @@ -71,7 +71,7 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService auxiliaryWindow.focus = async function () { originalWindowFocus(); - if (getActiveWindow() === auxiliaryWindow) { + if (getActiveWindow() !== auxiliaryWindow) { that.nativeHostService.focusWindow({ targetWindowId: await windowId.p }); } }; From 54ef00ba0e8d06202459c2af78df1d9ea4a4e73f Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 27 Oct 2023 09:47:24 +0200 Subject: [PATCH 146/162] checking providers exist before showing the context menu entry --- .../contrib/inlineChat/browser/inlineChatDecorations.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts index 53ecd4bd9ae..ce5f2d62178 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts @@ -145,6 +145,12 @@ export class InlineChatDecorationsContribution extends Disposable implements IEd } GutterActionsRegistry.registerGutterActionsGenerator(({ lineNumber, editor, accessor }, result) => { + console.log('Inside of registerGutterActionsGenerator'); + const inlineChatService = accessor.get(IInlineChatService); + const hasProviders = !Iterable.isEmpty(inlineChatService.getAllProvider()); + if (!hasProviders) { + return; + } const configurationService = accessor.get(IConfigurationService); result.push(new Action( 'inlineChat.toggleShowGutterIcon', From 871d93af8ce60cb3f185d87b3afd2e11ee5508af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 27 Oct 2023 10:54:43 +0200 Subject: [PATCH 147/162] make nps urgent (#196800) --- src/vs/workbench/contrib/surveys/browser/nps.contribution.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/surveys/browser/nps.contribution.ts b/src/vs/workbench/contrib/surveys/browser/nps.contribution.ts index f3cea74430c..170b8e82ff0 100644 --- a/src/vs/workbench/contrib/surveys/browser/nps.contribution.ts +++ b/src/vs/workbench/contrib/surveys/browser/nps.contribution.ts @@ -11,7 +11,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IProductService } from 'vs/platform/product/common/productService'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { Severity, INotificationService } from 'vs/platform/notification/common/notification'; +import { Severity, INotificationService, NotificationPriority } from 'vs/platform/notification/common/notification'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { URI } from 'vs/base/common/uri'; import { platform } from 'vs/base/common/process'; @@ -85,7 +85,7 @@ class NPSContribution implements IWorkbenchContribution { storageService.store(SKIP_VERSION_KEY, productService.version, StorageScope.APPLICATION, StorageTarget.USER); } }], - { sticky: true } + { sticky: true, priority: NotificationPriority.URGENT } ); } } From f3a0fe06bf15695863e7325750abf5a1a47c2ed9 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 27 Oct 2023 11:22:36 +0200 Subject: [PATCH 148/162] do not show the setting if there are no providers --- .../contrib/inlineChat/browser/inlineChatDecorations.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts index ce5f2d62178..a5aa54bb1e5 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts @@ -145,10 +145,9 @@ export class InlineChatDecorationsContribution extends Disposable implements IEd } GutterActionsRegistry.registerGutterActionsGenerator(({ lineNumber, editor, accessor }, result) => { - console.log('Inside of registerGutterActionsGenerator'); const inlineChatService = accessor.get(IInlineChatService); - const hasProviders = !Iterable.isEmpty(inlineChatService.getAllProvider()); - if (!hasProviders) { + const noProviders = Iterable.isEmpty(inlineChatService.getAllProvider()); + if (noProviders) { return; } const configurationService = accessor.get(IConfigurationService); From 6ab14d3a954f87fe4c1b4e48846527d107f57ec1 Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 27 Oct 2023 11:55:06 +0200 Subject: [PATCH 149/162] polishing the code --- .../browser/inlineChatDecorations.ts | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts index a5aa54bb1e5..d74fd891582 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts @@ -66,6 +66,18 @@ export class InlineChatDecorationsContribution extends Disposable implements IEd private _onEnablementOrModelChanged(): void { // cancels the scheduler, removes editor listeners / removes decoration this._localToDispose.clear(); + if (this._editor.hasModel() && this._hasProvider()) { + this._localToDispose.add(GutterActionsRegistry.registerGutterActionsGenerator(({ lineNumber, editor, accessor }, result) => { + const configurationService = accessor.get(IConfigurationService); + result.push(new Action( + 'inlineChat.toggleShowGutterIcon', + this._isSettingEnabled() ? localize('toggleHideGutterIcon', "Hide Inline Chat Icon") : localize('toggleShowGutterIcon', "Show Inline Chat Icon"), + undefined, + true, + () => { configurationService.updateValue(InlineChatDecorationsContribution.GUTTER_SETTING_ID, !configurationService.getValue(InlineChatDecorationsContribution.GUTTER_SETTING_ID)); } + )); + })); + } if (!this._editor.hasModel() || !this._isSettingEnabled() || !this._hasProvider()) { return; } @@ -143,19 +155,3 @@ export class InlineChatDecorationsContribution extends Disposable implements IEd this._localToDispose.dispose(); } } - -GutterActionsRegistry.registerGutterActionsGenerator(({ lineNumber, editor, accessor }, result) => { - const inlineChatService = accessor.get(IInlineChatService); - const noProviders = Iterable.isEmpty(inlineChatService.getAllProvider()); - if (noProviders) { - return; - } - const configurationService = accessor.get(IConfigurationService); - result.push(new Action( - 'inlineChat.toggleShowGutterIcon', - localize('toggleShowGutterIcon', "Toggle Inline Chat Icon"), - undefined, - true, - () => { configurationService.updateValue(InlineChatDecorationsContribution.GUTTER_SETTING_ID, !configurationService.getValue(InlineChatDecorationsContribution.GUTTER_SETTING_ID)); } - )); -}); From 4b5d53842e17a3c53088b2119f8ff82bd14eff4b Mon Sep 17 00:00:00 2001 From: Aiday Marlen Kyzy Date: Fri, 27 Oct 2023 11:59:18 +0200 Subject: [PATCH 150/162] resetting back the value --- .../browser/inlineChatDecorations.ts | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts index d74fd891582..a5aa54bb1e5 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatDecorations.ts @@ -66,18 +66,6 @@ export class InlineChatDecorationsContribution extends Disposable implements IEd private _onEnablementOrModelChanged(): void { // cancels the scheduler, removes editor listeners / removes decoration this._localToDispose.clear(); - if (this._editor.hasModel() && this._hasProvider()) { - this._localToDispose.add(GutterActionsRegistry.registerGutterActionsGenerator(({ lineNumber, editor, accessor }, result) => { - const configurationService = accessor.get(IConfigurationService); - result.push(new Action( - 'inlineChat.toggleShowGutterIcon', - this._isSettingEnabled() ? localize('toggleHideGutterIcon', "Hide Inline Chat Icon") : localize('toggleShowGutterIcon', "Show Inline Chat Icon"), - undefined, - true, - () => { configurationService.updateValue(InlineChatDecorationsContribution.GUTTER_SETTING_ID, !configurationService.getValue(InlineChatDecorationsContribution.GUTTER_SETTING_ID)); } - )); - })); - } if (!this._editor.hasModel() || !this._isSettingEnabled() || !this._hasProvider()) { return; } @@ -155,3 +143,19 @@ export class InlineChatDecorationsContribution extends Disposable implements IEd this._localToDispose.dispose(); } } + +GutterActionsRegistry.registerGutterActionsGenerator(({ lineNumber, editor, accessor }, result) => { + const inlineChatService = accessor.get(IInlineChatService); + const noProviders = Iterable.isEmpty(inlineChatService.getAllProvider()); + if (noProviders) { + return; + } + const configurationService = accessor.get(IConfigurationService); + result.push(new Action( + 'inlineChat.toggleShowGutterIcon', + localize('toggleShowGutterIcon', "Toggle Inline Chat Icon"), + undefined, + true, + () => { configurationService.updateValue(InlineChatDecorationsContribution.GUTTER_SETTING_ID, !configurationService.getValue(InlineChatDecorationsContribution.GUTTER_SETTING_ID)); } + )); +}); From 846215d35340044f6a0f744d3d2c0ba21bd1f2cb Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 27 Oct 2023 12:15:53 +0200 Subject: [PATCH 151/162] Forcefully kill extension host processes if they still exist (#196809) Forcefully kill extension host processes if they still exist (fixes #194477) --- .../electron-main/extensionHostStarter.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/vs/platform/extensions/electron-main/extensionHostStarter.ts b/src/vs/platform/extensions/electron-main/extensionHostStarter.ts index 2d5a39fa1da..19fcb4dd70a 100644 --- a/src/vs/platform/extensions/electron-main/extensionHostStarter.ts +++ b/src/vs/platform/extensions/electron-main/extensionHostStarter.ts @@ -78,6 +78,21 @@ export class ExtensionHostStarter implements IDisposable, IExtensionHostStarter extHost.dispose(); this._extHosts.delete(id); }); + + // See https://github.com/microsoft/vscode/issues/194477 + // We have observed that sometimes the process sends an exit + // event, but does not really exit and is stuck in an endless + // loop. In these cases we kill the process forcefully after + // a certain timeout. + setTimeout(() => { + try { + process.kill(pid, 0); // will throw if the process doesn't exist anymore. + this._logService.error(`Extension host with pid ${pid} still exists, forcefully killing it...`); + process.kill(pid); + } catch (er) { + // ignore, as the process is already gone + } + }, 1000); }); return { id }; } From 6cfa0900534841ceb3d3da088de048d1d124cb80 Mon Sep 17 00:00:00 2001 From: Ulugbek Abdullaev Date: Fri, 27 Oct 2023 12:31:47 +0200 Subject: [PATCH 152/162] Bump version to 1.85 (#196813) --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 42feba8d1d1..714bf79209e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "code-oss-dev", - "version": "1.84.0", + "version": "1.85.0", "distro": "ff0198cd90b25ba7ca853279cea9b8bb3cf5164d", "author": { "name": "Microsoft Corporation" @@ -227,4 +227,4 @@ "optionalDependencies": { "windows-foreground-love": "0.5.0" } -} \ No newline at end of file +} From f0fad066a3c3070fb8a2053e00fddf3f21b6621d Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Fri, 27 Oct 2023 12:34:22 +0200 Subject: [PATCH 153/162] Engineering - Rename .git-blame-ignore to .git-blame-ignore-revs (#196816) --- .git-blame-ignore => .git-blame-ignore-revs | 2 +- build/npm/postinstall.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename .git-blame-ignore => .git-blame-ignore-revs (86%) diff --git a/.git-blame-ignore b/.git-blame-ignore-revs similarity index 86% rename from .git-blame-ignore rename to .git-blame-ignore-revs index 457d2604f3c..c0c9a544148 100644 --- a/.git-blame-ignore +++ b/.git-blame-ignore-revs @@ -1,4 +1,5 @@ # https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt +# https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignore-commits-in-the-blame-view # mjbvz: Fix spacing 13f4f052582bcec3d6c6c6a70d995c9dee2cac13 @@ -23,6 +24,5 @@ ae1452eea678f5266ef513f22dacebb90955d6c9 a3cb14be7f2cceadb17adf843675b1a59537dbbd ee1655a82ebdfd38bf8792088a6602c69f7bbd94 - # jrieken: new eslint-rule 4a130c40ed876644ed8af2943809d08221375408 diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index 09df602a3bf..07b4412c458 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -112,4 +112,4 @@ for (let dir of dirs) { } cp.execSync('git config pull.rebase merges'); -cp.execSync('git config blame.ignoreRevsFile .git-blame-ignore'); +cp.execSync('git config blame.ignoreRevsFile .git-blame-ignore-revs'); From e17336d6cfc0e945d5d4d321fd469ba6a109c000 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 27 Oct 2023 15:09:01 +0200 Subject: [PATCH 154/162] - only update/reposition inline widget when showing again (#196829) - when hiding the first view port line, don't restore previous view port again fixes https://github.com/microsoft/vscode-copilot/issues/2288 --- src/vs/editor/common/viewModel/viewModelImpl.ts | 7 ++++++- .../editor/contrib/zoneWidget/browser/zoneWidget.ts | 13 +++++++++++++ .../inlineChat/browser/inlineChatController.ts | 8 ++++++-- .../browser/inlineChatLivePreviewWidget.ts | 6 +++--- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index eb18dced3c1..00e3ffb0de0 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -491,7 +491,12 @@ export class ViewModel extends Disposable implements IViewModel { this.viewLayout.onFlushed(this.getLineCount()); this.viewLayout.onHeightMaybeChanged(); } - stableViewport.recoverViewportStart(this.coordinatesConverter, this.viewLayout); + + const firstModelLineInViewPort = stableViewport.viewportStartModelPosition?.lineNumber; + const firstModelLineIsHidden = firstModelLineInViewPort && mergedRanges.some(range => range.startLineNumber <= firstModelLineInViewPort && firstModelLineInViewPort <= range.endLineNumber); + if (!firstModelLineIsHidden) { + stableViewport.recoverViewportStart(this.coordinatesConverter, this.viewLayout); + } } finally { this._eventDispatcher.endEmitViewEvents(); } diff --git a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts index a003de17958..a1e82f322d5 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts @@ -321,6 +321,19 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { this._positionMarkerId.set([{ range, options: ModelDecorationOptions.EMPTY }]); } + updatePositionAndHeight(rangeOrPos: IRange | IPosition, heightInLines?: number): void { + if (this._viewZone) { + rangeOrPos = Range.isIRange(rangeOrPos) ? Range.getStartPosition(rangeOrPos) : rangeOrPos; + this._viewZone.afterLineNumber = rangeOrPos.lineNumber; + this._viewZone.afterColumn = rangeOrPos.column; + this._viewZone.heightInLines = heightInLines ?? this._viewZone.heightInLines; + + this.editor.changeViewZones(accessor => { + accessor.layoutZone(this._viewZone!.id); + }); + } + } + hide(): void { if (this._viewZone) { this.editor.changeViewZones(accessor => { diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index ac8682ce0ef..9f620df3117 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -273,8 +273,12 @@ export class InlineChatController implements IEditorContribution { if (this._strategy) { needsMargin = this._strategy.needsMargin(); } - this._zone.value.setWidgetMargins(widgetPosition, !needsMargin ? 0 : undefined); - this._zone.value.show(widgetPosition); + if (!this._zone.value.position) { + this._zone.value.setWidgetMargins(widgetPosition, !needsMargin ? 0 : undefined); + this._zone.value.show(widgetPosition); + } else { + this._zone.value.updatePositionAndHeight(widgetPosition); + } } protected async _nextState(state: State, options: InlineChatRunOptions): Promise { diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget.ts index c1081af9cb1..31bf2d50717 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget.ts @@ -21,7 +21,7 @@ import { LineRange } from 'vs/editor/common/core/lineRange'; import { LineRangeMapping } from 'vs/editor/common/diff/rangeMapping'; import { Position } from 'vs/editor/common/core/position'; import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions'; -import { IEditorDecorationsCollection, ScrollType } from 'vs/editor/common/editorCommon'; +import { IEditorDecorationsCollection } from 'vs/editor/common/editorCommon'; import { ILogService } from 'vs/platform/log/common/log'; import { lineRangeAsRange, invertLineRange } from 'vs/workbench/contrib/inlineChat/browser/utils'; import { ResourceLabel } from 'vs/workbench/browser/labels'; @@ -57,7 +57,7 @@ export class InlineChatLivePreviewWidget extends ZoneWidget { @ILogService private readonly _logService: ILogService, @IAccessibilityService private readonly accessibilityService: IAccessibilityService, ) { - super(editor, { showArrow: false, showFrame: false, isResizeable: false, isAccessible: true, allowUnlimitedHeight: true, showInHiddenAreas: true, ordinal: 10000 + 1 }); + super(editor, { showArrow: false, showFrame: false, isResizeable: false, isAccessible: true, allowUnlimitedHeight: true, showInHiddenAreas: true, keepEditorSelection: true, ordinal: 10000 + 1 }); super.create(); assertType(editor.hasModel()); @@ -203,7 +203,7 @@ export class InlineChatLivePreviewWidget extends ZoneWidget { this._hideEditorRanges(this._diffEditor.getOriginalEditor(), ranges.originalDiffHidden); this._hideEditorRanges(this._diffEditor.getModifiedEditor(), ranges.modifiedDiffHidden); - this._diffEditor.revealLine(ranges.modifiedHidden.startLineNumber, ScrollType.Immediate); + // this._diffEditor.revealLine(ranges.modifiedHidden.startLineNumber, ScrollType.Immediate); const lineCountModified = ranges.modifiedHidden.length; const lineCountOriginal = ranges.originalHidden.length; From 9e0bd20b88f922b999163e03f56bd4d63f62d770 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Oct 2023 15:40:33 +0200 Subject: [PATCH 155/162] aux window - introduce active'ness to layout service and adopt (#196824) * aux window - introduce active'ness to layout service and adopt * :lipstick: * :lipstick: --- src/vs/base/browser/dom.ts | 7 ++ .../quickInput/standaloneQuickInputService.ts | 13 ++- .../browser/standaloneLayoutService.ts | 13 ++- .../contextview/browser/contextViewService.ts | 2 +- .../platform/layout/browser/layoutService.ts | 35 +++++-- .../browser/quickInputController.ts | 36 +++---- .../quickinput/browser/quickInputService.ts | 16 +++- src/vs/workbench/browser/layout.ts | 93 ++++++++++++++----- .../parts/auxiliarybar/auxiliaryBarPart.ts | 2 +- .../browser/parts/editor/editorParts.ts | 2 +- .../notifications/notificationsCenter.ts | 2 +- .../notifications/notificationsToasts.ts | 2 +- .../browser/parts/panel/panelPart.ts | 2 +- .../parts/titlebar/commandCenterControl.ts | 6 +- .../accessibility/browser/accessibleView.ts | 6 +- .../contrib/chat/browser/chatQuick.ts | 4 +- .../contrib/debug/browser/debugToolBar.ts | 6 +- .../contrib/splash/browser/partsSplash.ts | 2 +- .../browser/auxiliaryWindowService.ts | 20 ++-- .../test/browser/workbenchTestServices.ts | 10 +- 20 files changed, 189 insertions(+), 90 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 30a25285bc5..aaf950b4c1f 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -740,6 +740,13 @@ export function isAncestorOfActiveElement(ancestor: Element): boolean { return isAncestor(ancestor.ownerDocument.activeElement, ancestor); } +/** + * Returns whether the element is in the active `document`. + */ +export function isActiveDocument(element: Element): boolean { + return element.ownerDocument === getActiveDocument(); +} + /** * Returns the active document across all child windows. * Use this instead of `document` when reacting to dom events to handle multiple windows. diff --git a/src/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.ts b/src/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.ts index 549a1d85c77..2c45263ca24 100644 --- a/src/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.ts +++ b/src/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./standaloneQuickInput'; +import { Event } from 'vs/base/common/event'; import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser'; import { EditorContributionInstantiation, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; @@ -42,10 +43,14 @@ class EditorScopedQuickInputService extends QuickInputService { get container() { return widget.getDomNode(); }, get containers() { return [widget.getDomNode()]; }, get activeContainer() { return widget.getDomNode(); }, - get dimension() { return editor.getLayoutInfo(); }, - get onDidLayout() { return editor.onDidLayoutChange; }, - focus: () => editor.focus(), - offset: { top: 0, quickPickTop: 0 } + get mainContainerDimension() { return editor.getLayoutInfo(); }, + get activeContainerDimension() { return editor.getLayoutInfo(); }, + get onDidLayoutMainContainer() { return editor.onDidLayoutChange; }, + get onDidLayoutActiveContainer() { return editor.onDidLayoutChange; }, + get onDidChangeActiveContainer() { return Event.None; }, + get mainContainerOffset() { return { top: 0, quickPickTop: 0 }; }, + get activeContainerOffset() { return { top: 0, quickPickTop: 0 }; }, + focus: () => editor.focus() }; } else { this.host = undefined; diff --git a/src/vs/editor/standalone/browser/standaloneLayoutService.ts b/src/vs/editor/standalone/browser/standaloneLayoutService.ts index 361d84f2357..86aeb14e2ab 100644 --- a/src/vs/editor/standalone/browser/standaloneLayoutService.ts +++ b/src/vs/editor/standalone/browser/standaloneLayoutService.ts @@ -13,10 +13,12 @@ import { coalesce } from 'vs/base/common/arrays'; class StandaloneLayoutService implements ILayoutService { declare readonly _serviceBrand: undefined; - public onDidLayout = Event.None; + readonly onDidLayoutMainContainer = Event.None; + readonly onDidLayoutActiveContainer = Event.None; + readonly onDidChangeActiveContainer = Event.None; private _dimension?: dom.IDimension; - get dimension(): dom.IDimension { + get mainContainerDimension(): dom.IDimension { if (!this._dimension) { this._dimension = dom.getClientArea(window.document.body); } @@ -24,6 +26,11 @@ class StandaloneLayoutService implements ILayoutService { return this._dimension; } + get activeContainerDimension() { return this.mainContainerDimension; } + + readonly mainContainerOffset: ILayoutOffsetInfo = { top: 0, quickPickTop: 0 }; + readonly activeContainerOffset: ILayoutOffsetInfo = { top: 0, quickPickTop: 0 }; + get hasContainer(): boolean { return false; } @@ -51,8 +58,6 @@ class StandaloneLayoutService implements ILayoutService { this._codeEditorService.getFocusedCodeEditor()?.focus(); } - readonly offset: ILayoutOffsetInfo = { top: 0, quickPickTop: 0 }; - constructor( @ICodeEditorService private _codeEditorService: ICodeEditorService ) { } diff --git a/src/vs/platform/contextview/browser/contextViewService.ts b/src/vs/platform/contextview/browser/contextViewService.ts index ed305ef3881..beb879021a0 100644 --- a/src/vs/platform/contextview/browser/contextViewService.ts +++ b/src/vs/platform/contextview/browser/contextViewService.ts @@ -25,7 +25,7 @@ export class ContextViewService extends Disposable implements IContextViewServic this.contextView = this._register(new ContextView(this.container, ContextViewDOMPosition.ABSOLUTE)); this.layout(); - this._register(layoutService.onDidLayout(() => this.layout())); + this._register(layoutService.onDidLayoutMainContainer(() => this.layout())); } // ContextView diff --git a/src/vs/platform/layout/browser/layoutService.ts b/src/vs/platform/layout/browser/layoutService.ts index e84f9f3107f..74d4ef4b801 100644 --- a/src/vs/platform/layout/browser/layoutService.ts +++ b/src/vs/platform/layout/browser/layoutService.ts @@ -10,10 +10,12 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' export const ILayoutService = createDecorator('layoutService'); export interface ILayoutOffsetInfo { + /** * Generic top offset */ readonly top: number; + /** * Quick pick specific top offset. */ @@ -25,15 +27,29 @@ export interface ILayoutService { readonly _serviceBrand: undefined; /** - * An event that is emitted when the container is layed out. The - * event carries the dimensions of the container as part of it. + * An event that is emitted when the main container is layed out. */ - readonly onDidLayout: Event; + readonly onDidLayoutMainContainer: Event; /** - * The dimensions of the container. + * An event that is emitted when the active container is layed out. */ - readonly dimension: IDimension; + readonly onDidLayoutActiveContainer: Event; + + /** + * An event that is emitted when the active container changes. + */ + readonly onDidChangeActiveContainer: Event; + + /** + * The dimensions of the main container. + */ + readonly mainContainerDimension: IDimension; + + /** + * The dimensions of the active container. + */ + readonly activeContainerDimension: IDimension; /** * Does the application have a single container? @@ -41,7 +57,7 @@ export interface ILayoutService { readonly hasContainer: boolean; /** - * Container of the application. + * Main container of the application. * * **NOTE**: In the standalone editor case, multiple editors can be created on a page. * Therefore, in the standalone editor case, there are multiple containers, not just @@ -65,10 +81,15 @@ export interface ILayoutService { */ readonly containers: Iterable; + /** + * An offset to use for positioning elements inside the main container. + */ + readonly mainContainerOffset: ILayoutOffsetInfo; + /** * An offset to use for positioning elements inside the container. */ - readonly offset: ILayoutOffsetInfo; + readonly activeContainerOffset: ILayoutOffsetInfo; /** * Focus the primary component of the container. diff --git a/src/vs/platform/quickinput/browser/quickInputController.ts b/src/vs/platform/quickinput/browser/quickInputController.ts index 86976df649f..a2f2e4cb1b9 100644 --- a/src/vs/platform/quickinput/browser/quickInputController.ts +++ b/src/vs/platform/quickinput/browser/quickInputController.ts @@ -81,12 +81,14 @@ export class QuickInputController extends Disposable { } } - private getUI() { + private getUI(showInActiveContainer?: boolean) { if (this.ui) { // In order to support aux windows, re-parent the controller // if the original event is from a different document - if (this.parentElement.ownerDocument !== this.layoutService.activeContainer.ownerDocument) { - this.reparentUI(this.layoutService.activeContainer); + if (showInActiveContainer) { + if (this.parentElement.ownerDocument !== this.layoutService.activeContainer.ownerDocument) { + this.reparentUI(this.layoutService.activeContainer); + } } return this.ui; @@ -506,22 +508,22 @@ export class QuickInputController extends Disposable { backButton = backButton; createQuickPick(): IQuickPick { - const ui = this.getUI(); + const ui = this.getUI(true); return new QuickPick(ui); } createInputBox(): IInputBox { - const ui = this.getUI(); + const ui = this.getUI(true); return new InputBox(ui); } createQuickWidget(): IQuickWidget { - const ui = this.getUI(); + const ui = this.getUI(true); return new QuickWidget(ui); } private show(controller: IQuickInput) { - const ui = this.getUI(); + const ui = this.getUI(true); this.onShowEmitter.fire(); const oldController = this.controller; this.controller = controller; @@ -559,6 +561,10 @@ export class QuickInputController extends Disposable { ui.inputBox.setFocus(); } + isVisible(): boolean { + return !!this.ui && this.ui.container.style.display !== 'none'; + } + private setVisibilities(visibilities: Visibilities) { const ui = this.getUI(); ui.title.style.display = visibilities.title ? '' : 'none'; @@ -605,7 +611,9 @@ export class QuickInputController extends Disposable { const focusChanged = container && !dom.isAncestorOfActiveElement(container); this.controller = null; this.onHideEmitter.fire(); - this.getUI().container.style.display = 'none'; + if (container) { + container.style.display = 'none'; + } if (!focusChanged) { let currentElement = this.previousFocusElement; while (currentElement && !currentElement.offsetParent) { @@ -622,7 +630,7 @@ export class QuickInputController extends Disposable { } focus() { - if (this.isDisplayed()) { + if (this.isVisible()) { const ui = this.getUI(); if (ui.inputBox.enabled) { ui.inputBox.setFocus(); @@ -633,13 +641,13 @@ export class QuickInputController extends Disposable { } toggle() { - if (this.isDisplayed() && this.controller instanceof QuickPick && this.controller.canSelectMany) { + if (this.isVisible() && this.controller instanceof QuickPick && this.controller.canSelectMany) { this.getUI().list.toggleCheckbox(); } } navigate(next: boolean, quickNavigate?: IQuickNavigateConfiguration) { - if (this.isDisplayed() && this.getUI().list.isDisplayed()) { + if (this.isVisible() && this.getUI().list.isDisplayed()) { this.getUI().list.focus(next ? QuickInputListFocus.Next : QuickInputListFocus.Previous); if (quickNavigate && this.controller instanceof QuickPick) { this.controller.quickNavigate = quickNavigate; @@ -673,7 +681,7 @@ export class QuickInputController extends Disposable { } private updateLayout() { - if (this.ui && this.isDisplayed()) { + if (this.ui && this.isVisible()) { this.ui.container.style.top = `${this.titleBarOffset}px`; const style = this.ui.container.style; @@ -745,10 +753,6 @@ export class QuickInputController extends Disposable { } } } - - private isDisplayed() { - return this.ui && this.ui.container.style.display !== 'none'; - } } export interface IQuickInputControllerHost extends ILayoutService { } diff --git a/src/vs/platform/quickinput/browser/quickInputService.ts b/src/vs/platform/quickinput/browser/quickInputService.ts index a5892ba0281..0d6884730e1 100644 --- a/src/vs/platform/quickinput/browser/quickInputService.ts +++ b/src/vs/platform/quickinput/browser/quickInputService.ts @@ -67,7 +67,7 @@ export class QuickInputService extends Themable implements IQuickInputService { protected createController(host: IQuickInputControllerHost = this.layoutService, options?: Partial): QuickInputController { const defaultOptions: IQuickInputOptions = { idPrefix: 'quickInput_', - container: host.container, + container: host.activeContainer, ignoreFocusOut: () => false, backKeybindingLabel: () => undefined, setContextKey: (id?: string) => this.setContextKey(id), @@ -94,12 +94,20 @@ export class QuickInputService extends Themable implements IQuickInputService { ...options }, this.themeService, - this.layoutService)); + this.layoutService + )); - controller.layout(host.dimension, host.offset.quickPickTop); + controller.layout(host.activeContainerDimension, host.activeContainerOffset.quickPickTop); // Layout changes - this._register(host.onDidLayout(dimension => controller.layout(dimension, host.offset.quickPickTop))); + this._register(host.onDidLayoutActiveContainer(dimension => controller.layout(dimension, host.activeContainerOffset.quickPickTop))); + this._register(host.onDidChangeActiveContainer(() => { + if (controller.isVisible()) { + return; + } + + controller.layout(host.activeContainerDimension, host.activeContainerOffset.quickPickTop); + })); // Context keys this._register(controller.onShow(() => { diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index a3adccf5491..1554dfade7b 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -5,7 +5,7 @@ import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; -import { EventType, addDisposableListener, getClientArea, Dimension, position, size, IDimension, isAncestorUsingFlowTo, computeScreenAwareSize, getActiveDocument, getWindows, getActiveWindow, focusWindow } from 'vs/base/browser/dom'; +import { EventType, addDisposableListener, getClientArea, Dimension, position, size, IDimension, isAncestorUsingFlowTo, computeScreenAwareSize, getActiveDocument, getWindows, getActiveWindow, focusWindow, isActiveDocument } from 'vs/base/browser/dom'; import { onDidChangeFullscreen, isFullscreen, isWCOEnabled } from 'vs/base/browser/browser'; import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup'; import { isWindows, isLinux, isMacintosh, isWeb, isNative, isIOS } from 'vs/base/common/platform'; @@ -145,8 +145,11 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi private readonly _onDidChangeNotificationsVisibility = this._register(new Emitter()); readonly onDidChangeNotificationsVisibility = this._onDidChangeNotificationsVisibility.event; - private readonly _onDidLayout = this._register(new Emitter()); - readonly onDidLayout = this._onDidLayout.event; + private readonly _onDidLayoutMainContainer = this._register(new Emitter()); + readonly onDidLayoutMainContainer = this._onDidLayoutMainContainer.event; + + private readonly _onDidLayoutActiveContainer = this._register(new Emitter()); + readonly onDidLayoutActiveContainer = this._onDidLayoutActiveContainer.event; private readonly _onDidAddContainer = this._register(new Emitter()); readonly onDidAddContainer = this._onDidAddContainer.event; @@ -154,6 +157,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi private readonly _onDidRemoveContainer = this._register(new Emitter()); readonly onDidRemoveContainer = this._onDidRemoveContainer.event; + private readonly _onDidChangeActiveContainer = this._register(new Emitter()); + readonly onDidChangeActiveContainer = this._onDidChangeActiveContainer.event; + //#endregion //#region Properties @@ -180,27 +186,54 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi } } - private _dimension!: IDimension; - get dimension(): IDimension { return this._dimension; } + private _mainContainerDimension!: IDimension; + get mainContainerDimension(): IDimension { return this._mainContainerDimension; } - get offset() { + get activeContainerDimension(): IDimension { + const activeContainer = this.activeContainer; + if (activeContainer === this.container) { + // main window + return this.mainContainerDimension; + } else { + // auxiliary window + return getClientArea(activeContainer); + } + } + + get mainContainerOffset() { let top = 0; let quickPickTop = 0; + if (this.isVisible(Parts.BANNER_PART)) { top = this.getPart(Parts.BANNER_PART).maximumHeight; quickPickTop = top; } + if (this.isVisible(Parts.TITLEBAR_PART)) { top += this.getPart(Parts.TITLEBAR_PART).maximumHeight; quickPickTop = top; } - // If the command center is visible then the quickinput should go over the title bar and the banner + if (this.titleService.isCommandCenterVisible) { + // If the command center is visible then the quickinput + // should go over the title bar and the banner quickPickTop = 6; } + return { top, quickPickTop }; } + get activeContainerOffset() { + const activeContainer = this.activeContainer; + if (activeContainer === this.container) { + // main window + return this.mainContainerOffset; + } else { + // TODO@bpasero auxiliary window: no support for custom title bar or banner yet + return { top: 0, quickPickTop: 0 }; + } + } + //#endregion private readonly parts = new Map(); @@ -346,6 +379,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this._register(this.auxiliaryWindowService.onDidOpenAuxiliaryWindow(({ window, disposables }) => { this._onDidAddContainer.fire(window.container); + disposables.add(window.onDidLayout(dimension => this.handleContainerDidLayout(window.container, dimension))); disposables.add(toDisposable(() => this._onDidRemoveContainer.fire(window.container))); })); } @@ -369,7 +403,17 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi // Move layout call to any time the menubar // is toggled to update consumers of offset // see issue #115267 - this._onDidLayout.fire(this._dimension); + this.handleContainerDidLayout(this.container, this._mainContainerDimension); + } + } + + private handleContainerDidLayout(container: HTMLElement, dimension: IDimension): void { + if (container === this.container) { + this._onDidLayoutMainContainer.fire(dimension); + } + + if (isActiveDocument(container)) { + this._onDidLayoutActiveContainer.fire(dimension); } } @@ -406,12 +450,17 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi } private onWindowFocusChanged(hasFocus: boolean): void { - if (this.state.runtime.hasFocus === hasFocus) { - return; + if (hasFocus) { + // This is a bit simplified: we assume that the active container + // has changed when receiving focus, but we might end up with + // the same active container as before... + this._onDidChangeActiveContainer.fire(); } - this.state.runtime.hasFocus = hasFocus; - this.updateWindowBorder(); + if (this.state.runtime.hasFocus !== hasFocus) { + this.state.runtime.hasFocus = hasFocus; + this.updateWindowBorder(); + } } private doUpdateLayoutConfiguration(skipLayout?: boolean): void { @@ -1187,8 +1236,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi (this.isVisible(Parts.STATUSBAR_PART) ? this.statusBarPartView.minimumHeight : 0) + (this.isVisible(Parts.PANEL_PART) && !isColumn ? this.panelPartView.minimumHeight : 0); - const availableWidth = this.dimension.width - takenWidth; - const availableHeight = this.dimension.height - takenHeight; + const availableWidth = this._mainContainerDimension.width - takenWidth; + const availableHeight = this._mainContainerDimension.height - takenHeight; return new Dimension(availableWidth, availableHeight); } @@ -1401,7 +1450,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.setEditorHidden(!visible, true); } this._onDidChangePartVisibility.fire(); - this._onDidLayout.fire(this._dimension); + this.handleContainerDidLayout(this.container, this._mainContainerDimension); })); } @@ -1430,24 +1479,20 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi })); } - private getClientArea(): Dimension { - return getClientArea(this.parent); - } - layout(): void { if (!this.disposed) { - this._dimension = this.getClientArea(); - this.logService.trace(`Layout#layout, height: ${this._dimension.height}, width: ${this._dimension.width}`); + this._mainContainerDimension = getClientArea(this.parent); + this.logService.trace(`Layout#layout, height: ${this._mainContainerDimension.height}, width: ${this._mainContainerDimension.width}`); position(this.container, 0, 0, 0, 0, 'relative'); - size(this.container, this._dimension.width, this._dimension.height); + size(this.container, this._mainContainerDimension.width, this._mainContainerDimension.height); // Layout the grid widget - this.workbenchGrid.layout(this._dimension.width, this._dimension.height); + this.workbenchGrid.layout(this._mainContainerDimension.width, this._mainContainerDimension.height); this.initialized = true; // Emit as event - this._onDidLayout.fire(this._dimension); + this.handleContainerDidLayout(this.container, this._mainContainerDimension); } } diff --git a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts index 684c704ffc3..5ad1c648d6f 100644 --- a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts +++ b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts @@ -46,7 +46,7 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart { get preferredHeight(): number | undefined { // Don't worry about titlebar or statusbar visibility // The difference is minimal and keeps this function clean - return this.layoutService.dimension.height * 0.4; + return this.layoutService.mainContainerDimension.height * 0.4; } get preferredWidth(): number | undefined { diff --git a/src/vs/workbench/browser/parts/editor/editorParts.ts b/src/vs/workbench/browser/parts/editor/editorParts.ts index 42bffcb5bb2..7b52a57a303 100644 --- a/src/vs/workbench/browser/parts/editor/editorParts.ts +++ b/src/vs/workbench/browser/parts/editor/editorParts.ts @@ -61,7 +61,7 @@ export class EditorParts extends Disposable implements IEditorGroupsService, IEd disposables.add(this.instantiationService.createInstance(WindowTitle, auxiliaryWindow.window, editorPart)); - disposables.add(auxiliaryWindow.onWillLayout(dimension => editorPart.layout(dimension.width, dimension.height, 0, 0))); + disposables.add(auxiliaryWindow.onDidLayout(dimension => editorPart.layout(dimension.width, dimension.height, 0, 0))); auxiliaryWindow.layout(); this._onDidAddGroup.fire(editorPart.activeGroup); diff --git a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts index 51115350f94..8ff0cdd81d1 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts @@ -65,7 +65,7 @@ export class NotificationsCenter extends Themable implements INotificationsCente private registerListeners(): void { this._register(this.model.onDidChangeNotification(e => this.onDidChangeNotification(e))); - this._register(this.layoutService.onDidLayout(dimension => this.layout(Dimension.lift(dimension)))); + this._register(this.layoutService.onDidLayoutMainContainer(dimension => this.layout(Dimension.lift(dimension)))); this._register(this.notificationService.onDidChangeDoNotDisturbMode(() => this.onDidChangeDoNotDisturbMode())); } diff --git a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts index f6fa63e49f2..c3f0490bedd 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts @@ -93,7 +93,7 @@ export class NotificationsToasts extends Themable implements INotificationsToast private registerListeners(): void { // Layout - this._register(this.layoutService.onDidLayout(dimension => this.layout(Dimension.lift(dimension)))); + this._register(this.layoutService.onDidLayoutMainContainer(dimension => this.layout(Dimension.lift(dimension)))); // Delay some tasks until after we have restored // to reduce UI pressure from the startup phase diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 05e15a7698b..00b10081e8a 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -42,7 +42,7 @@ export class PanelPart extends AbstractPaneCompositePart { get preferredHeight(): number | undefined { // Don't worry about titlebar or statusbar visibility // The difference is minimal and keeps this function clean - return this.layoutService.dimension.height * 0.4; + return this.layoutService.mainContainerDimension.height * 0.4; } get preferredWidth(): number | undefined { diff --git a/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts b/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts index e9b53aef62e..8b2176b6466 100644 --- a/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { reset } from 'vs/base/browser/dom'; +import { isActiveDocument, reset } from 'vs/base/browser/dom'; import { BaseActionViewItem, IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { IHoverDelegate } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate'; import { setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover'; @@ -57,8 +57,8 @@ export class CommandCenterControl { } }); - this._disposables.add(quickInputService.onShow(this._setVisibility.bind(this, false))); - this._disposables.add(quickInputService.onHide(this._setVisibility.bind(this, true))); + this._disposables.add(Event.filter(quickInputService.onShow, () => isActiveDocument(this.element), this._disposables)(this._setVisibility.bind(this, false))); + this._disposables.add(Event.filter(quickInputService.onHide, () => isActiveDocument(this.element), this._disposables)(this._setVisibility.bind(this, true))); this._disposables.add(titleToolbar); } diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index a844abc4607..3757bda1c58 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -265,7 +265,7 @@ export class AccessibleView extends Disposable { return; } const delegate: IContextViewDelegate = { - getAnchor: () => { return { x: (getActiveWindow().innerWidth / 2) - ((Math.min(this._layoutService.dimension.width * 0.62 /* golden cut */, DIMENSIONS.MAX_WIDTH)) / 2), y: this._layoutService.offset.quickPickTop }; }, + 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'); return this._render(provider!, container, showAccessibleViewHelp); @@ -531,7 +531,7 @@ export class AccessibleView extends Disposable { } })); disposableStore.add(this._editorWidget.onDidContentSizeChange(() => this._layout())); - disposableStore.add(this._layoutService.onDidLayout(() => this._layout())); + disposableStore.add(this._layoutService.onDidLayoutActiveContainer(() => this._layout())); return disposableStore; } @@ -552,7 +552,7 @@ export class AccessibleView extends Disposable { } private _layout(): void { - const dimension = this._layoutService.dimension; + const dimension = this._layoutService.activeContainerDimension; const maxHeight = dimension.height && dimension.height * .4; const height = Math.min(maxHeight, this._editorWidget.getContentHeight()); const width = Math.min(dimension.width * 0.62 /* golden cut */, DIMENSIONS.MAX_WIDTH); diff --git a/src/vs/workbench/contrib/chat/browser/chatQuick.ts b/src/vs/workbench/contrib/chat/browser/chatQuick.ts index 18e04b21280..170c2ae89e6 100644 --- a/src/vs/workbench/contrib/chat/browser/chatQuick.ts +++ b/src/vs/workbench/contrib/chat/browser/chatQuick.ts @@ -236,11 +236,11 @@ class QuickChat extends Disposable { } private get maxHeight(): number { - return this.layoutService.dimension.height - QuickChat.DEFAULT_HEIGHT_OFFSET; + return this.layoutService.mainContainerDimension.height - QuickChat.DEFAULT_HEIGHT_OFFSET; } private registerListeners(parent: HTMLElement): void { - this._register(this.layoutService.onDidLayout(() => { + this._register(this.layoutService.onDidLayoutMainContainer(() => { if (this.widget.visible) { this.widget.updateDynamicChatTreeItemLayout(2, this.maxHeight); } else { diff --git a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts index fec7dc3a786..83372ce9637 100644 --- a/src/vs/workbench/contrib/debug/browser/debugToolBar.ts +++ b/src/vs/workbench/contrib/debug/browser/debugToolBar.ts @@ -72,7 +72,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { super(themeService); this.$el = dom.$('div.debug-toolbar'); - this.$el.style.top = `${layoutService.offset.top}px`; + this.$el.style.top = `${layoutService.mainContainerOffset.top}px`; this.dragArea = dom.append(this.$el, dom.$('div.drag-area' + ThemeIcon.asCSSSelector(icons.debugGripper))); @@ -163,7 +163,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { // Prevent default to stop editor selecting text #8524 mouseMoveEvent.preventDefault(); // Reduce x by width of drag handle to reduce jarring #16604 - this.setCoordinates(mouseMoveEvent.posx - 14, mouseMoveEvent.posy - (this.layoutService.offset.top)); + this.setCoordinates(mouseMoveEvent.posx - 14, mouseMoveEvent.posy - (this.layoutService.mainContainerOffset.top)); }); const mouseUpListener = dom.addDisposableGenericMouseUpListener(window, (e: MouseEvent) => { @@ -209,7 +209,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution { } private setYCoordinate(y = this.yCoordinate): void { - const titlebarOffset = this.layoutService.offset.top; + const titlebarOffset = this.layoutService.mainContainerOffset.top; this.$el.style.top = `${titlebarOffset + y}px`; this.yCoordinate = y; } diff --git a/src/vs/workbench/contrib/splash/browser/partsSplash.ts b/src/vs/workbench/contrib/splash/browser/partsSplash.ts index d8a0657f0f0..08fd7e5a8d5 100644 --- a/src/vs/workbench/contrib/splash/browser/partsSplash.ts +++ b/src/vs/workbench/contrib/splash/browser/partsSplash.ts @@ -37,7 +37,7 @@ export class PartsSplash { @IConfigurationService private readonly _configService: IConfigurationService, @ISplashStorageService private readonly _partSplashService: ISplashStorageService ) { - Event.once(_layoutService.onDidLayout)(() => { + Event.once(_layoutService.onDidLayoutMainContainer)(() => { this._removePartsSplash(); perf.mark('code/didRemovePartsSplash'); }, undefined, this._disposables); diff --git a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts index 6cf0b30d30c..8c1a57c8aa8 100644 --- a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts +++ b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts @@ -34,7 +34,7 @@ export interface IAuxiliaryWindowService { export interface IAuxiliaryWindow extends IDisposable { - readonly onWillLayout: Event; + readonly onDidLayout: Event; readonly onDidClose: Event; readonly window: Window & typeof globalThis; @@ -72,14 +72,14 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili disposables.add(registerWindow(auxiliaryWindow)); disposables.add(toDisposable(() => auxiliaryWindow.close())); - const { container, onWillLayout, onDidClose } = this.create(auxiliaryWindow, disposables); + const { container, onDidLayout, onDidClose } = this.create(auxiliaryWindow, disposables); - const result = { + const result: IAuxiliaryWindow = { window: auxiliaryWindow, container, - onWillLayout: onWillLayout.event, + onDidLayout: onDidLayout.event, onDidClose: onDidClose.event, - layout: () => onWillLayout.fire(getClientArea(container)), + layout: () => onDidLayout.fire(getClientArea(container)), dispose: () => disposables.dispose() }; @@ -129,9 +129,9 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili const container = this.applyHTML(auxiliaryWindow, disposables); - const { onWillLayout, onDidClose } = this.registerListeners(auxiliaryWindow, container, disposables); + const { onDidLayout, onDidClose } = this.registerListeners(auxiliaryWindow, container, disposables); - return { container, onWillLayout, onDidClose }; + return { container, onDidLayout, onDidClose }; } private applyMeta(auxiliaryWindow: AuxiliaryWindow): void { @@ -240,13 +240,13 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili e.preventDefault(); })); - const onWillLayout = disposables.add(new Emitter()); + const onDidLayout = disposables.add(new Emitter()); disposables.add(addDisposableListener(auxiliaryWindow, EventType.RESIZE, () => { const dimension = getClientArea(auxiliaryWindow.document.body); position(container, 0, 0, 0, 0, 'relative'); size(container, dimension.width, dimension.height); - onWillLayout.fire(dimension); + onDidLayout.fire(dimension); })); this._register(addDisposableListener(container, EventType.SCROLL, () => container.scrollTop = 0)); // // Prevent container from scrolling (#55456) @@ -260,7 +260,7 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili disposables.add(addDisposableListener(auxiliaryWindow.document.body, EventType.DROP, (e: DragEvent) => EventHelper.stop(e))); // Prevent default navigation on drop } - return { onWillLayout, onDidClose }; + return { onDidLayout, onDidClose }; } protected patchMethods(auxiliaryWindow: AuxiliaryWindow): void { diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 6e4e93422e8..c2253938025 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -588,8 +588,10 @@ export class TestLayoutService implements IWorkbenchLayoutService { openedDefaultEditors = false; - dimension: IDimension = { width: 800, height: 600 }; - offset: ILayoutOffsetInfo = { top: 0, quickPickTop: 0 }; + mainContainerDimension: IDimension = { width: 800, height: 600 }; + activeContainerDimension: IDimension = { width: 800, height: 600 }; + mainContainerOffset: ILayoutOffsetInfo = { top: 0, quickPickTop: 0 }; + activeContainerOffset: ILayoutOffsetInfo = { top: 0, quickPickTop: 0 }; hasContainer = true; container: HTMLElement = window.document.body; @@ -603,10 +605,12 @@ export class TestLayoutService implements IWorkbenchLayoutService { onDidChangePanelPosition: Event = Event.None; onDidChangePanelAlignment: Event = Event.None; onDidChangePartVisibility: Event = Event.None; - onDidLayout = Event.None; + onDidLayoutMainContainer = Event.None; + onDidLayoutActiveContainer = Event.None; onDidChangeNotificationsVisibility = Event.None; onDidAddContainer = Event.None; onDidRemoveContainer = Event.None; + onDidChangeActiveContainer = Event.None; layout(): void { } isRestored(): boolean { return true; } From 56088b01d985ad1b868e3c01b7c4e1ad9247f9e9 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Fri, 27 Oct 2023 15:42:08 +0200 Subject: [PATCH 156/162] Git - fix issue related to opening parent repositories (#196822) --- extensions/git/src/model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index 250008ee311..4632cd83bb3 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -602,8 +602,8 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi } async openParentRepository(repoPath: string): Promise { - await this.openRepository(repoPath); this._parentRepositoriesManager.openRepository(repoPath); + await this.openRepository(repoPath); } private async getRepositoryRoot(repoPath: string): Promise<{ repositoryRoot: string; unsafeRepositoryMatch: RegExpMatchArray | null }> { From 62fdec2defe2d41d5eb06c45b7b185c7df3abbb3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Oct 2023 16:42:45 +0200 Subject: [PATCH 157/162] aux window - cleanup preloads (#196832) * aux window - cleanup preloads * :lipstick: * :lipstick: --- build/gulpfile.vscode.js | 2 +- .../parts/sandbox/electron-sandbox/globals.ts | 30 ++------- .../{preload-slim.js => preload-aux.js} | 8 +-- .../parts/sandbox/electron-sandbox/preload.js | 65 +++++++++---------- .../auxiliaryWindowsMainService.ts | 2 +- .../window/electron-sandbox/window.ts | 17 ++++- .../electron-sandbox/actions/windowActions.ts | 4 +- .../auxiliaryWindowService.ts | 23 +++---- .../electron-sandbox/nativeHostService.ts | 2 +- 9 files changed, 72 insertions(+), 81 deletions(-) rename src/vs/base/parts/sandbox/electron-sandbox/{preload-slim.js => preload-aux.js} (93%) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 4ae98a95577..857114fea15 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -64,7 +64,7 @@ const vscodeResources = [ 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}', 'out-build/vs/base/browser/ui/codicons/codicon/**', 'out-build/vs/base/parts/sandbox/electron-sandbox/preload.js', - 'out-build/vs/base/parts/sandbox/electron-sandbox/preload-slim.js', + 'out-build/vs/base/parts/sandbox/electron-sandbox/preload-aux.js', 'out-build/vs/workbench/browser/media/*-theme.css', 'out-build/vs/workbench/contrib/debug/**/*.json', 'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt', diff --git a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts index d0ae5a5ff0e..2fd7a08808a 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts +++ b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts @@ -121,31 +121,11 @@ export const webFrame: WebFrame = globals.vscode.webFrame; export const process: ISandboxNodeProcess = globals.vscode.process; export const context: ISandboxContext = globals.vscode.context; -export interface IGlobalsSlim { +/** + * A set of globals that are available in all windows that either + * depend on `preload.js` or `preload-aux.js`. + */ +export interface ISandboxGlobals { readonly ipcRenderer: Pick; readonly webFrame: import('vs/base/parts/sandbox/electron-sandbox/electronTypes').WebFrame; } - -/** - * Get the globals that are available in the given window. Since - * this method supports auxiliary windows, only a subset of globals - * is returned. - */ -export function getGlobals(win: Window): IGlobalsSlim | undefined { - if (win === window) { - return { ipcRenderer, webFrame }; - } - - const auxiliaryWindowCandidate = win as unknown as { - vscode: { - ipcRenderer: Pick; - webFrame: import('vs/base/parts/sandbox/electron-sandbox/electronTypes').WebFrame; - }; - }; - - if (auxiliaryWindowCandidate?.vscode?.ipcRenderer && auxiliaryWindowCandidate?.vscode?.webFrame) { - return auxiliaryWindowCandidate.vscode; - } - - return undefined; -} diff --git a/src/vs/base/parts/sandbox/electron-sandbox/preload-slim.js b/src/vs/base/parts/sandbox/electron-sandbox/preload-aux.js similarity index 93% rename from src/vs/base/parts/sandbox/electron-sandbox/preload-slim.js rename to src/vs/base/parts/sandbox/electron-sandbox/preload-aux.js index 7b6256756ac..c73cabcdfa5 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/preload-slim.js +++ b/src/vs/base/parts/sandbox/electron-sandbox/preload-aux.js @@ -46,12 +46,12 @@ /** * @param {string} channel * @param {any[]} args - * @returns {Promise | never} + * @returns {Promise} */ invoke(channel, ...args) { - if (validateIPC(channel)) { - return ipcRenderer.invoke(channel, ...args); - } + validateIPC(channel); + + return ipcRenderer.invoke(channel, ...args); } }, diff --git a/src/vs/base/parts/sandbox/electron-sandbox/preload.js b/src/vs/base/parts/sandbox/electron-sandbox/preload.js index 0494b7ddda7..90ac940861f 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/preload.js +++ b/src/vs/base/parts/sandbox/electron-sandbox/preload.js @@ -56,24 +56,23 @@ } try { - if (validateIPC(windowConfigIpcChannel)) { + validateIPC(windowConfigIpcChannel); - // Resolve configuration from electron-main - configuration = await ipcRenderer.invoke(windowConfigIpcChannel); + // Resolve configuration from electron-main + const resolvedConfiguration = configuration = await ipcRenderer.invoke(windowConfigIpcChannel); - // Apply `userEnv` directly - Object.assign(process.env, configuration.userEnv); + // Apply `userEnv` directly + Object.assign(process.env, resolvedConfiguration.userEnv); - // Apply zoom level early before even building the - // window DOM elements to avoid UI flicker. We always - // have to set the zoom level from within the window - // because Chrome has it's own way of remembering zoom - // settings per origin (if vscode-file:// is used) and - // we want to ensure that the user configuration wins. - webFrame.setZoomLevel(configuration.zoomLevel ?? 0); + // Apply zoom level early before even building the + // window DOM elements to avoid UI flicker. We always + // have to set the zoom level from within the window + // because Chrome has it's own way of remembering zoom + // settings per origin (if vscode-file:// is used) and + // we want to ensure that the user configuration wins. + webFrame.setZoomLevel(resolvedConfiguration.zoomLevel ?? 0); - return configuration; - } + return resolvedConfiguration; } catch (error) { throw new Error(`Preload: unable to fetch vscode-window-config: ${error}`); } @@ -145,51 +144,51 @@ /** * @param {string} channel * @param {any[]} args - * @returns {Promise | never} + * @returns {Promise} */ invoke(channel, ...args) { - if (validateIPC(channel)) { - return ipcRenderer.invoke(channel, ...args); - } + validateIPC(channel); + + return ipcRenderer.invoke(channel, ...args); }, /** * @param {string} channel * @param {(event: IpcRendererEvent, ...args: any[]) => void} listener - * @returns {IpcRenderer | never} + * @returns {IpcRenderer} */ on(channel, listener) { - if (validateIPC(channel)) { - ipcRenderer.on(channel, listener); + validateIPC(channel); - return this; - } + ipcRenderer.on(channel, listener); + + return this; }, /** * @param {string} channel * @param {(event: IpcRendererEvent, ...args: any[]) => void} listener - * @returns {IpcRenderer | never} + * @returns {IpcRenderer} */ once(channel, listener) { - if (validateIPC(channel)) { - ipcRenderer.once(channel, listener); + validateIPC(channel); - return this; - } + ipcRenderer.once(channel, listener); + + return this; }, /** * @param {string} channel * @param {(event: IpcRendererEvent, ...args: any[]) => void} listener - * @returns {IpcRenderer | never} + * @returns {IpcRenderer} */ removeListener(channel, listener) { - if (validateIPC(channel)) { - ipcRenderer.removeListener(channel, listener); + validateIPC(channel); - return this; - } + ipcRenderer.removeListener(channel, listener); + + return this; } }, diff --git a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts index 01718d334cc..983494e1cf6 100644 --- a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts +++ b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts @@ -42,7 +42,7 @@ export class AuxiliaryWindowsMainService implements IAuxiliaryWindowsMainService createWindow(): BrowserWindowConstructorOptions { return this.instantiationService.invokeFunction(defaultBrowserWindowOptions, undefined, { webPreferences: { - preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-sandbox/preload-slim.js').fsPath + preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-sandbox/preload-aux.js').fsPath } }); } diff --git a/src/vs/platform/window/electron-sandbox/window.ts b/src/vs/platform/window/electron-sandbox/window.ts index b4c27b676f0..28968b4f9cc 100644 --- a/src/vs/platform/window/electron-sandbox/window.ts +++ b/src/vs/platform/window/electron-sandbox/window.ts @@ -5,7 +5,7 @@ import { getZoomLevel, setZoomFactor, setZoomLevel } from 'vs/base/browser/browser'; import { getWindows } from 'vs/base/browser/dom'; -import { getGlobals } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import { ISandboxGlobals, ipcRenderer, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { zoomLevelToZoomFactor } from 'vs/platform/window/common/window'; /** @@ -20,6 +20,21 @@ export function applyZoom(zoomLevel: number): void { setZoomLevel(zoomLevel); } +function getGlobals(win: Window): ISandboxGlobals | undefined { + if (win === window) { + // main window + return { ipcRenderer, webFrame }; + } else { + // auxiliary window + const auxiliaryWindow = win as unknown as { vscode: ISandboxGlobals }; + if (auxiliaryWindow?.vscode?.ipcRenderer && auxiliaryWindow?.vscode?.webFrame) { + return auxiliaryWindow.vscode; + } + } + + return undefined; +} + export function zoomIn(): void { applyZoom(getZoomLevel() + 1); } diff --git a/src/vs/workbench/electron-sandbox/actions/windowActions.ts b/src/vs/workbench/electron-sandbox/actions/windowActions.ts index d7471d3cd8f..6535966e5b9 100644 --- a/src/vs/workbench/electron-sandbox/actions/windowActions.ts +++ b/src/vs/workbench/electron-sandbox/actions/windowActions.ts @@ -64,7 +64,7 @@ export class CloseWindowAction extends Action2 { const window = getActiveWindow(); if (isAuxiliaryWindow(window)) { - return nativeHostService.closeWindowById(await window.vscodeWindowId); + return nativeHostService.closeWindowById(window.vscodeWindowId); } return nativeHostService.closeWindow(); @@ -368,7 +368,7 @@ export class ExperimentalSplitWindowAction extends Action2 { let activeWindowId: number; const activeWindow = getActiveWindow(); if (isAuxiliaryWindow(activeWindow)) { - activeWindowId = await activeWindow.vscodeWindowId; + activeWindowId = activeWindow.vscodeWindowId; } else { activeWindowId = environmentService.window.id; } diff --git a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts index 4787b33d38a..717e29eabd9 100644 --- a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts +++ b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts @@ -6,23 +6,23 @@ import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { BrowserAuxiliaryWindowService, IAuxiliaryWindowService, AuxiliaryWindow as BaseAuxiliaryWindow } from 'vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService'; -import { getGlobals } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import { ISandboxGlobals } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWindowsConfiguration } from 'vs/platform/window/common/window'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { INativeHostService } from 'vs/platform/native/common/native'; -import { DeferredPromise } from 'vs/base/common/async'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { getActiveWindow } from 'vs/base/browser/dom'; type AuxiliaryWindow = BaseAuxiliaryWindow & { - readonly vscodeWindowId: Promise; + readonly vscode: ISandboxGlobals; + readonly vscodeWindowId: number; }; export function isAuxiliaryWindow(obj: unknown): obj is AuxiliaryWindow { const candidate = obj as AuxiliaryWindow | undefined; - return candidate?.vscodeWindowId instanceof Promise; + return !!candidate?.vscode && Object.hasOwn(candidate, 'vscodeWindowId'); } export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService { @@ -41,7 +41,7 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService // Zoom level const windowConfig = this.configurationService.getValue(); const windowZoomLevel = typeof windowConfig.window?.zoomLevel === 'number' ? windowConfig.window.zoomLevel : 0; - getGlobals(auxiliaryWindow)?.webFrame?.setZoomLevel(windowZoomLevel); + auxiliaryWindow.vscode.webFrame.setZoomLevel(windowZoomLevel); return super.create(auxiliaryWindow, disposables); } @@ -50,17 +50,14 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService super.patchMethods(auxiliaryWindow); // Obtain window identifier - const windowId = new DeferredPromise(); + let resolvedWindowId: number; (async () => { - windowId.complete(await getGlobals(auxiliaryWindow)?.ipcRenderer.invoke('vscode:getWindowId')); + resolvedWindowId = await auxiliaryWindow.vscode.ipcRenderer.invoke('vscode:getWindowId'); })(); // Add a `windowId` property Object.defineProperty(auxiliaryWindow, 'vscodeWindowId', { - value: windowId.p, - writable: false, - enumerable: false, - configurable: false + get: () => resolvedWindowId }); // Enable `window.focus()` to work in Electron by @@ -68,11 +65,11 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService // https://github.com/electron/electron/issues/25578 const that = this; const originalWindowFocus = auxiliaryWindow.focus.bind(auxiliaryWindow); - auxiliaryWindow.focus = async function () { + auxiliaryWindow.focus = function () { originalWindowFocus(); if (getActiveWindow() !== auxiliaryWindow) { - that.nativeHostService.focusWindow({ targetWindowId: await windowId.p }); + that.nativeHostService.focusWindow({ targetWindowId: resolvedWindowId }); } }; } diff --git a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts index 9c1cd113aaf..8909c6bd0f5 100644 --- a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts +++ b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts @@ -138,7 +138,7 @@ class WorkbenchHostService extends Disposable implements IHostService { return; // does not apply when only one window is opened } - return this.nativeHostService.moveWindowTop(isAuxiliaryWindow(window) ? { targetWindowId: await window.vscodeWindowId } : undefined); + return this.nativeHostService.moveWindowTop(isAuxiliaryWindow(window) ? { targetWindowId: window.vscodeWindowId } : undefined); } //#endregion From fa22e9ac36d5d37ef096679927179091ba7f6966 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 27 Oct 2023 18:35:46 +0200 Subject: [PATCH 158/162] Update grammars (#196839) Co-authored-by: Martin Aeschlimann --- extensions/csharp/cgmanifest.json | 4 +- .../csharp/syntaxes/csharp.tmLanguage.json | 1922 +++++++++++------ extensions/fsharp/cgmanifest.json | 2 +- .../fsharp/syntaxes/fsharp.tmLanguage.json | 16 +- extensions/r/syntaxes/r.tmLanguage.json | 2 +- extensions/razor/build/update-grammar.mjs | 2 +- extensions/razor/cgmanifest.json | 2 +- .../razor/syntaxes/cshtml.tmLanguage.json | 4 +- extensions/rust/cgmanifest.json | 2 +- extensions/rust/syntaxes/rust.tmLanguage.json | 118 +- .../test/colorize-results/test_cs.json | 152 +- .../test/colorize-results/test_cshtml.json | 110 +- 12 files changed, 1519 insertions(+), 817 deletions(-) diff --git a/extensions/csharp/cgmanifest.json b/extensions/csharp/cgmanifest.json index 176ee56da48..ad27f27b271 100644 --- a/extensions/csharp/cgmanifest.json +++ b/extensions/csharp/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "dotnet/csharp-tmLanguage", "repositoryUrl": "https://github.com/dotnet/csharp-tmLanguage", - "commitHash": "772323937fedd65c6dc1c8ce6ea41d97415ed7d1" + "commitHash": "6666eb1d5e6fb565a4110d6db645cc534fb3c6d2" } }, "license": "MIT", @@ -15,4 +15,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/csharp/syntaxes/csharp.tmLanguage.json b/extensions/csharp/syntaxes/csharp.tmLanguage.json index c4266da462d..9b6cf2e9664 100644 --- a/extensions/csharp/syntaxes/csharp.tmLanguage.json +++ b/extensions/csharp/syntaxes/csharp.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/dotnet/csharp-tmLanguage/commit/772323937fedd65c6dc1c8ce6ea41d97415ed7d1", + "version": "https://github.com/dotnet/csharp-tmLanguage/commit/6666eb1d5e6fb565a4110d6db645cc534fb3c6d2", "name": "C#", "scopeName": "source.cs", "patterns": [ @@ -210,9 +210,6 @@ { "include": "#else-part" }, - { - "include": "#switch-statement" - }, { "include": "#goto-statement" }, @@ -238,10 +235,10 @@ "include": "#checked-unchecked-statement" }, { - "include": "#lock-statement" + "include": "#context-control-statement" }, { - "include": "#using-statement" + "include": "#context-control-paren-statement" }, { "include": "#labeled-statement" @@ -278,13 +275,10 @@ "include": "#comment" }, { - "include": "#checked-unchecked-expression" + "include": "#expression-operator-expression" }, { - "include": "#typeof-or-default-expression" - }, - { - "include": "#nameof-expression" + "include": "#type-operator-expression" }, { "include": "#default-literal-expression" @@ -305,14 +299,20 @@ "include": "#type-builtin" }, { - "include": "#this-or-base-expression" + "include": "#language-variable" }, { - "include": "#switch-expression" + "include": "#switch-statement-or-expression" + }, + { + "include": "#with-expression" }, { "include": "#conditional-operator" }, + { + "include": "#assignment-expression" + }, { "include": "#expression-operators" }, @@ -370,36 +370,39 @@ ] }, "extern-alias-directive": { - "begin": "\\s*(extern)\\b\\s*(alias)\\b\\s*(@?[_[:alpha:]][_[:alnum:]]*)", + "begin": "\\b(extern)\\s+(alias)\\b", "beginCaptures": { "1": { - "name": "keyword.other.extern.cs" + "name": "keyword.other.directive.extern.cs" }, "2": { - "name": "keyword.other.alias.cs" - }, - "3": { - "name": "variable.other.alias.cs" + "name": "keyword.other.directive.alias.cs" } }, - "end": "(?=;)" + "end": "(?=;)", + "patterns": [ + { + "match": "\\@?[_[:alpha:]][_[:alnum:]]*", + "name": "variable.other.alias.cs" + } + ] }, "using-directive": { "patterns": [ { - "begin": "(\\b(global)\\b\\s+)?\\b(using)\\b\\s+(static)\\b\\s+(\\b(unsafe)\\b\\s+)?", + "begin": "\\b(?:(global)\\s+)?(using)\\s+(static)\\b\\s*(?:(unsafe)\\b\\s*)?", "beginCaptures": { + "1": { + "name": "keyword.other.directive.global.cs" + }, "2": { - "name": "keyword.other.global.cs" + "name": "keyword.other.directive.using.cs" }, "3": { - "name": "keyword.other.using.cs" + "name": "keyword.other.directive.static.cs" }, "4": { - "name": "keyword.other.static.cs" - }, - "6": { - "name": "storage.modifier.cs" + "name": "storage.modifier.unsafe.cs" } }, "end": "(?=;)", @@ -410,19 +413,22 @@ ] }, { - "begin": "(\\b(global)\\b\\s+)?\\b(using)\\b\\s+(\\b(unsafe)\\b\\s+)?(?=(@?[_[:alpha:]][_[:alnum:]]*)\\s*=)", + "begin": "\\b(?:(global)\\s+)?(using)\\b\\s*(?:(unsafe)\\b\\s*)?(@?[_[:alpha:]][_[:alnum:]]*)\\s*(=)", "beginCaptures": { + "1": { + "name": "keyword.other.directive.global.cs" + }, "2": { - "name": "keyword.other.global.cs" + "name": "keyword.other.directive.using.cs" }, "3": { - "name": "keyword.other.using.cs" + "name": "storage.modifier.unsafe.cs" + }, + "4": { + "name": "entity.name.type.alias.cs" }, "5": { - "name": "storage.modifier.cs" - }, - "6": { - "name": "entity.name.type.alias.cs" + "name": "keyword.operator.assignment.cs" } }, "end": "(?=;)", @@ -432,20 +438,17 @@ }, { "include": "#type" - }, - { - "include": "#operator-assignment" } ] }, { - "begin": "(\\b(global)\\b\\s+)?\\b(using)\\s*(?!\\(|\\s|var)", + "begin": "\\b(?:(global)\\s+)?(using)\\b\\s*+(?!\\(|var\\b)", "beginCaptures": { - "2": { - "name": "keyword.other.global.cs" + "1": { + "name": "keyword.other.directive.global.cs" }, - "3": { - "name": "keyword.other.using.cs" + "2": { + "name": "keyword.other.directive.using.cs" } }, "end": "(?=;)", @@ -455,7 +458,10 @@ }, { "name": "entity.name.type.namespace.cs", - "match": "@?[_[:alpha:]][_[:alnum:]]*" + "match": "\\@?[_[:alpha:]][_[:alnum:]]*" + }, + { + "include": "#punctuation-accessor" }, { "include": "#operator-assignment" @@ -551,7 +557,7 @@ "begin": "\\b(namespace)\\s+", "beginCaptures": { "1": { - "name": "keyword.other.namespace.cs" + "name": "storage.type.namespace.cs" } }, "end": "(?<=\\})|(?=;)", @@ -594,7 +600,7 @@ ] }, "storage-modifier": { - "name": "storage.modifier.cs", + "name": "storage.modifier.$1.cs", "match": "(?\n (?:\n (?:ref\\s+(?:readonly\\s+)?)? # ref return\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s+\n(\\g)\\s*\n(<([^<>]+)>)?\\s*\n(?=\\()", "beginCaptures": { "1": { - "name": "keyword.other.delegate.cs" + "name": "storage.type.delegate.cs" }, "2": { "patterns": [ @@ -712,7 +718,7 @@ "match": "(enum)\\s+(@?[_[:alpha:]][_[:alnum:]]*)", "captures": { "1": { - "name": "keyword.other.enum.cs" + "name": "storage.type.enum.cs" }, "2": { "name": "entity.name.type.enum.cs" @@ -796,7 +802,7 @@ "begin": "(?x)\n(interface)\\b\\s+\n(@?[_[:alpha:]][_[:alnum:]]*)", "beginCaptures": { "1": { - "name": "keyword.other.interface.cs" + "name": "storage.type.interface.cs" }, "2": { "name": "entity.name.type.interface.cs" @@ -853,7 +859,7 @@ "begin": "(?x)\n(record)\\b\\s+\n(@?[_[:alpha:]][_[:alnum:]]*)", "beginCaptures": { "1": { - "name": "keyword.other.record.cs" + "name": "storage.type.record.cs" }, "2": { "name": "entity.name.type.class.cs" @@ -913,10 +919,10 @@ "begin": "(?x)\n(\\b(record)\\b\\s+)?\n(struct)\\b\\s+\n(@?[_[:alpha:]][_[:alnum:]]*)", "beginCaptures": { "2": { - "name": "keyword.other.record.cs" + "name": "storage.type.record.cs" }, "3": { - "name": "keyword.other.struct.cs" + "name": "storage.type.struct.cs" }, "4": { "name": "entity.name.type.struct.cs" @@ -984,19 +990,11 @@ "patterns": [ { "match": "\\b(in|out)\\b", - "captures": { - "1": { - "name": "storage.modifier.cs" - } - } + "name": "storage.modifier.$1.cs" }, { "match": "(@?[_[:alpha:]][_[:alnum:]]*)\\b", - "captures": { - "1": { - "name": "entity.name.type.type-parameter.cs" - } - } + "name": "entity.name.type.type-parameter.cs" }, { "include": "#comment" @@ -1033,7 +1031,7 @@ "begin": "(where)\\s+(@?[_[:alpha:]][_[:alnum:]]*)\\s*(:)", "beginCaptures": { "1": { - "name": "keyword.other.where.cs" + "name": "storage.modifier.where.cs" }, "2": { "name": "entity.name.type.type-parameter.cs" @@ -1045,18 +1043,18 @@ "end": "(?=\\{|where|;|=>)", "patterns": [ { - "name": "keyword.other.class.cs", + "name": "storage.type.class.cs", "match": "\\bclass\\b" }, { - "name": "keyword.other.struct.cs", + "name": "storage.type.struct.cs", "match": "\\bstruct\\b" }, { "match": "(new)\\s*(\\()\\s*(\\))", "captures": { "1": { - "name": "keyword.other.new.cs" + "name": "keyword.operator.expression.new.cs" }, "2": { "name": "punctuation.parenthesis.open.cs" @@ -1112,7 +1110,7 @@ ] }, "property-declaration": { - "begin": "(?x)\n\n# The negative lookahead below ensures that we don't match nested types\n# or other declarations as properties.\n(?![[:word:][:space:]]*\\b(?:class|interface|struct|enum|event)\\b)\n\n(?\n (?\n (?:\n (?:ref\\s+(?:readonly\\s+)?)? # ref return\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n )\\s+\n)\n(?\\g\\s*\\.\\s*)?\n(?\\g)\\s*\n(?=\\{|=>|$)", + "begin": "(?x)\n\n# The negative lookahead below ensures that we don't match nested types\n# or other declarations as properties.\n(?![[:word:][:space:]]*\\b(?:class|interface|struct|enum|event)\\b)\n\n(?\n (?\n (?:\n (?:ref\\s+(?:readonly\\s+)?)? # ref return\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n )\\s+\n)\n(?\\g\\s*\\.\\s*)?\n(?\\g)\\s*\n(?=\\{|=>|//|/\\*|$)", "beginCaptures": { "1": { "patterns": [ @@ -1144,7 +1142,7 @@ "include": "#property-accessors" }, { - "include": "#expression-body" + "include": "#accessor-getter-expression" }, { "include": "#variable-initializer" @@ -1175,7 +1173,7 @@ ] }, "8": { - "name": "keyword.other.this.cs" + "name": "variable.language.this.cs" } }, "end": "(?<=\\})|(?=;)", @@ -1190,7 +1188,7 @@ "include": "#property-accessors" }, { - "include": "#expression-body" + "include": "#accessor-getter-expression" }, { "include": "#variable-initializer" @@ -1198,10 +1196,10 @@ ] }, "event-declaration": { - "begin": "(?x)\n\\b(event)\\b\\s*\n(?\n (?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n )\\s+\n)\n(?\\g\\s*\\.\\s*)?\n(?\\g(?:\\s*,\\s*\\g)*)\\s*\n(?=\\{|;|$)", + "begin": "(?x)\n\\b(event)\\b\\s*\n(?\n (?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n )\\s+\n)\n(?\\g\\s*\\.\\s*)?\n(\\g)\\s* # first event name\n(?=\\{|;|,|=|//|/\\*|$)", "beginCaptures": { "1": { - "name": "keyword.other.event.cs" + "name": "storage.type.event.cs" }, "2": { "patterns": [ @@ -1221,15 +1219,7 @@ ] }, "9": { - "patterns": [ - { - "name": "entity.name.variable.event.cs", - "match": "@?[_[:alpha:]][_[:alnum:]]*" - }, - { - "include": "#punctuation-comma" - } - ] + "name": "entity.name.variable.event.cs" } }, "end": "(?<=\\})|(?=;)", @@ -1240,8 +1230,29 @@ { "include": "#event-accessors" }, + { + "name": "entity.name.variable.event.cs", + "match": "@?[_[:alpha:]][_[:alnum:]]*" + }, { "include": "#punctuation-comma" + }, + { + "begin": "=", + "beginCaptures": { + "0": { + "name": "keyword.operator.assignment.cs" + } + }, + "end": "(?<=,)|(?=;)", + "patterns": [ + { + "include": "#expression" + }, + { + "include": "#punctuation-comma" + } + ] } ] }, @@ -1259,22 +1270,6 @@ } }, "patterns": [ - { - "name": "storage.modifier.cs", - "match": "\\b(private|protected|internal)\\b" - }, - { - "name": "keyword.other.get.cs", - "match": "\\b(get)\\b" - }, - { - "name": "keyword.other.set.cs", - "match": "\\b(set)\\b" - }, - { - "name": "keyword.other.init.cs", - "match": "\\b(init)\\b" - }, { "include": "#comment" }, @@ -1282,13 +1277,36 @@ "include": "#attribute-section" }, { - "include": "#expression-body" + "name": "storage.modifier.$1.cs", + "match": "\\b(private|protected|internal)\\b" }, { - "include": "#block" + "begin": "\\b(get)\\b\\s*(?=\\{|;|=>|//|/\\*|$)", + "beginCaptures": { + "1": { + "name": "storage.type.accessor.$1.cs" + } + }, + "end": "(?<=\\}|;)|(?=\\})", + "patterns": [ + { + "include": "#accessor-getter" + } + ] }, { - "include": "#punctuation-semicolon" + "begin": "\\b(set|init)\\b\\s*(?=\\{|;|=>|//|/\\*|$)", + "beginCaptures": { + "1": { + "name": "storage.type.accessor.$1.cs" + } + }, + "end": "(?<=\\}|;)|(?=\\})", + "patterns": [ + { + "include": "#accessor-setter" + } + ] } ] }, @@ -1306,14 +1324,6 @@ } }, "patterns": [ - { - "name": "keyword.other.add.cs", - "match": "\\b(add)\\b" - }, - { - "name": "keyword.other.remove.cs", - "match": "\\b(remove)\\b" - }, { "include": "#comment" }, @@ -1321,10 +1331,108 @@ "include": "#attribute-section" }, { - "include": "#expression-body" + "begin": "\\b(add|remove)\\b\\s*(?=\\{|;|=>|//|/\\*|$)", + "beginCaptures": { + "1": { + "name": "storage.type.accessor.$1.cs" + } + }, + "end": "(?<=\\}|;)|(?=\\})", + "patterns": [ + { + "include": "#accessor-setter" + } + ] + } + ] + }, + "accessor-getter": { + "patterns": [ + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.curlybrace.open.cs" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.curlybrace.close.cs" + } + }, + "contentName": "meta.accessor.getter.cs", + "patterns": [ + { + "include": "#statement" + } + ] }, { - "include": "#block" + "include": "#accessor-getter-expression" + }, + { + "include": "#punctuation-semicolon" + } + ] + }, + "accessor-getter-expression": { + "begin": "=>", + "beginCaptures": { + "0": { + "name": "keyword.operator.arrow.cs" + } + }, + "end": "(?=;|\\})", + "contentName": "meta.accessor.getter.cs", + "patterns": [ + { + "include": "#ref-modifier" + }, + { + "include": "#expression" + } + ] + }, + "accessor-setter": { + "patterns": [ + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.curlybrace.open.cs" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.curlybrace.close.cs" + } + }, + "contentName": "meta.accessor.setter.cs", + "patterns": [ + { + "include": "#statement" + } + ] + }, + { + "begin": "=>", + "beginCaptures": { + "0": { + "name": "keyword.operator.arrow.cs" + } + }, + "end": "(?=;|\\})", + "contentName": "meta.accessor.setter.cs", + "patterns": [ + { + "include": "#ref-modifier" + }, + { + "include": "#expression" + } + ] }, { "include": "#punctuation-semicolon" @@ -1425,13 +1533,10 @@ ] }, "constructor-initializer": { - "begin": "\\b(?:(base)|(this))\\b\\s*(?=\\()", + "begin": "\\b(base|this)\\b\\s*(?=\\()", "beginCaptures": { "1": { - "name": "keyword.other.base.cs" - }, - "2": { - "name": "keyword.other.this.cs" + "name": "variable.language.$1.cs" } }, "end": "(?<=\\))", @@ -1468,7 +1573,7 @@ ] }, "operator-declaration": { - "begin": "(?x)\n(?\n (?:\n (?:ref\\s+(?:readonly\\s+)?)? # ref return\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s*\n(?(?:\\b(?:operator)))\\s*\n(?(?:\\+|-|\\*|/|%|&|\\||\\^|\\<\\<|\\>\\>|==|!=|\\>|\\<|\\>=|\\<=|!|~|\\+\\+|--|true|false))\\s*\n(?=\\()", + "begin": "(?x)\n(?\n (?:\n (?:ref\\s+(?:readonly\\s+)?)? # ref return\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s*\n\\b(?operator)\\b\\s*\n(?[+\\-*/%&|\\^!=~<>]+|true|false)\\s*\n(?=\\()", "beginCaptures": { "1": { "patterns": [ @@ -1478,7 +1583,7 @@ ] }, "6": { - "name": "keyword.other.operator-decl.cs" + "name": "storage.type.operator.cs" }, "7": { "name": "entity.name.function.cs" @@ -1509,7 +1614,7 @@ "match": "\\b(explicit)\\b", "captures": { "1": { - "name": "keyword.other.explicit.cs" + "name": "storage.modifier.explicit.cs" } } }, @@ -1517,14 +1622,14 @@ "match": "\\b(implicit)\\b", "captures": { "1": { - "name": "keyword.other.implicit.cs" + "name": "storage.modifier.implicit.cs" } } } ] }, "2": { - "name": "keyword.other.operator-decl.cs" + "name": "storage.type.operator.cs" }, "3": { "patterns": [ @@ -1607,19 +1712,19 @@ "begin": "(?", + "beginCaptures": { + "0": { + "name": "keyword.operator.arrow.cs" + } + }, + "end": "(?=,|})", + "patterns": [ + { + "include": "#expression" + } + ] + }, + { + "begin": "\\b(when)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.conditional.when.cs" + } + }, + "end": "(?==>|,|})", + "patterns": [ + { + "include": "#case-guard" + } + ] + }, + { + "begin": "(?!\\s)", + "end": "(?=\\bwhen\\b|=>|,|})", + "patterns": [ + { + "include": "#pattern" + } + ] + } + ] + }, + "case-guard": { + "patterns": [ + { + "include": "#parenthesized-expression" + }, + { + "include": "#expression" + } + ] + }, + "is-expression": { + "begin": "(?=?", + "beginCaptures": { + "0": { + "name": "keyword.operator.relational.cs" + } + }, + "end": "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)", + "patterns": [ + { + "include": "#expression" + } + ] + }, + "var-pattern": { + "begin": "\\b(var)\\b", + "beginCaptures": { + "1": { + "name": "storage.type.var.cs" + } + }, + "end": "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)", + "patterns": [ + { + "include": "#designation-pattern" + } + ] + }, + "designation-pattern": { + "patterns": [ + { + "include": "#intrusive" + }, + { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.parenthesis.open.cs" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.parenthesis.close.cs" + } + }, + "patterns": [ + { + "include": "#punctuation-comma" + }, + { + "include": "#designation-pattern" + } + ] + }, + { + "include": "#simple-designation-pattern" + } + ] + }, + "simple-designation-pattern": { + "patterns": [ + { + "include": "#discard-pattern" + }, + { + "match": "@?[_[:alpha:]][_[:alnum:]]*", + "name": "entity.name.variable.local.cs" + } + ] + }, + "type-pattern": { + "begin": "(?=@?[_[:alpha:]][_[:alnum:]]*)", + "end": "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)", + "patterns": [ + { + "begin": "\\G", + "end": "(?!\\G[@_[:alpha:]])(?=[\\({@_[:alpha:])}\\],;:=&|^]|(?:\\s|^)\\?|!=|\\b(and|or|when)\\b)", + "patterns": [ + { + "include": "#intrusive" + }, + { + "include": "#type-subpattern" + } + ] + }, + { + "begin": "(?=[\\({@_[:alpha:]])", + "end": "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)", + "patterns": [ + { + "include": "#intrusive" + }, + { + "include": "#positional-pattern" + }, + { + "include": "#property-pattern" + }, + { + "include": "#simple-designation-pattern" + } + ] + } + ] + }, + "type-subpattern": { + "patterns": [ + { + "include": "#type-builtin" + }, + { + "begin": "(@?[_[:alpha:]][_[:alnum:]]*)\\s*(::)", + "beginCaptures": { + "1": { + "name": "entity.name.type.alias.cs" + }, + "2": { + "name": "punctuation.separator.coloncolon.cs" + } + }, + "end": "(?<=[_[:alnum:]])|(?=[.<\\[\\({)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)", + "patterns": [ + { + "include": "#intrusive" + }, + { + "match": "\\@?[_[:alpha:]][_[:alnum:]]*", + "name": "entity.name.type.cs" + } + ] + }, + { + "match": "\\@?[_[:alpha:]][_[:alnum:]]*", + "name": "entity.name.type.cs" + }, + { + "begin": "\\.", + "beginCaptures": { + "0": { + "name": "punctuation.accessor.cs" + } + }, + "end": "(?<=[_[:alnum:]])|(?=[<\\[\\({)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)", + "patterns": [ + { + "include": "#intrusive" + }, + { + "match": "\\@?[_[:alpha:]][_[:alnum:]]*", + "name": "entity.name.type.cs" + } + ] + }, + { + "include": "#type-arguments" + }, + { + "include": "#type-array-suffix" + }, + { + "match": "(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s+\n(\\g)\\b\\s*", - "beginCaptures": { - "1": { + }, + { + "begin": "(?<=\\})", + "end": "(?=[)}\\],;:?=&|^]|!=|\\b(and|or|when)\\b)", "patterns": [ { - "include": "#type" - } - ] - }, - "2": { - "name": "entity.name.variable.local.cs" - } - }, - "end": "(?==>)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#switch-when-clause" - } - ] - }, - "switch-property-expression": { - "begin": "(?x) # e.g. int x OR var x\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)?\\s*\n(\\{)", - "beginCaptures": { - "1": { - "patterns": [ + "include": "#intrusive" + }, { - "include": "#type" - } - ] - }, - "6": { - "name": "punctuation.curlybrace.open.cs" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.curlybrace.close.cs" - } - }, - "patterns": [ - { - "include": "#expression" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "switch-var-pattern": { - "begin": "(?x) # match foreach (var (x, y) in ...)\n(?:\\b(var)\\b\\s*)\n(?\\((?:[^\\(\\)]|\\g)+\\))\\s*", - "beginCaptures": { - "1": { - "name": "keyword.other.var.cs" - }, - "2": { - "patterns": [ - { - "include": "#tuple-declaration-deconstruction-element-list" + "include": "#simple-designation-pattern" } ] } - }, - "end": "(?==>)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#switch-when-clause" - } ] }, - "switch-when-clause": { - "begin": "(?)", + "subpattern": { "patterns": [ { - "include": "#comment" - }, - { - "include": "#expression" - }, - { - "include": "#punctuation-comma" - }, - { - "match": "\\(", - "captures": { - "0": { - "name": "punctuation.parenthesis.open.cs" - } - } - }, - { - "match": "\\)", - "captures": { - "0": { - "name": "punctuation.parenthesis.close.cs" - } - } - } - ] - }, - "switch-label": { - "patterns": [ - { - "begin": "(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n )\n)\\s+\n(\\g)\\s+\n\\b(in)\\b", "captures": { "1": { - "name": "keyword.other.var.cs" + "name": "storage.type.var.cs" }, "2": { "patterns": [ @@ -2176,7 +2719,7 @@ "match": "(?x) # match foreach (var (x, y) in ...)\n(?:\\b(var)\\b\\s*)?\n(?\\((?:[^\\(\\)]|\\g)+\\))\\s+\n\\b(in)\\b", "captures": { "1": { - "name": "keyword.other.var.cs" + "name": "storage.type.var.cs" }, "2": { "patterns": [ @@ -2194,9 +2737,6 @@ "include": "#expression" } ] - }, - { - "include": "#statement" } ] }, @@ -2217,7 +2757,7 @@ "begin": "(?\n (?:\n (?:ref\\s+(?:readonly\\s+)?)? # ref local\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n )\n)\\s+\n(\\g)\\s*\n(?!=>)\n(?=,|;|=|\\))", + "begin": "(?x)\n(?:\n (?:(\\bref)\\s+(?:(\\breadonly)\\s+)?)?(\\bvar\\b)| # ref local\n (?\n (?:\n (?:ref\\s+(?:readonly\\s+)?)? # ref local\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*[?*]\\s*)? # nullable or pointer suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n )\n)\\s+\n(\\g)\\s*\n(?!=>)\n(?=,|;|=|\\))", "beginCaptures": { "1": { - "name": "keyword.other.using.cs" + "name": "storage.modifier.ref.cs" }, "2": { - "name": "storage.modifier.cs" + "name": "storage.modifier.readonly.cs" }, "3": { - "name": "storage.modifier.cs" + "name": "storage.type.var.cs" }, "4": { - "name": "keyword.other.var.cs" - }, - "5": { "patterns": [ { "include": "#type" } ] }, - "10": { + "9": { "name": "entity.name.variable.local.cs" } }, - "end": "(?=;|\\))", + "end": "(?=[;)}])", "patterns": [ { "name": "entity.name.variable.local.cs", @@ -2486,7 +3068,7 @@ "begin": "(?x)\n(?\\b(?:const)\\b)\\s*\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s+\n(\\g)\\s*\n(?=,|;|=)", "beginCaptures": { "1": { - "name": "storage.modifier.cs" + "name": "storage.modifier.const.cs" }, "2": { "patterns": [ @@ -2517,9 +3099,49 @@ ] }, "local-function-declaration": { + "begin": "(?x)\n\\b((?:(?:async|unsafe|static|extern)\\s+)*)\n(?\n (?:ref\\s+(?:readonly\\s+)?)? # ref return\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n \\s*(?:,\\s*)* # commata for multi-dimensional arrays\n \\]\n (?:\\s*\\?)? # arrays can be nullable reference types\n )*\n)\\s+\n(\\g)\\s*\n(<[^<>]+>)?\\s*\n(?=\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#storage-modifier" + } + ] + }, + "2": { + "patterns": [ + { + "include": "#type" + } + ] + }, + "7": { + "name": "entity.name.function.cs" + }, + "8": { + "patterns": [ + { + "include": "#type-parameter-list" + } + ] + } + }, + "end": "(?<=\\})|(?=;)", "patterns": [ { - "include": "#method-declaration" + "include": "#comment" + }, + { + "include": "#parenthesized-parameter-list" + }, + { + "include": "#generic-constraints" + }, + { + "include": "#expression-body" + }, + { + "include": "#block" } ] }, @@ -2527,7 +3149,7 @@ "begin": "(?x) # e.g. var (x, y) = GetPoint();\n(?:\\b(var)\\b\\s*)\n(?\\((?:[^\\(\\)]|\\g)+\\))\\s*\n(?=;|=|\\))", "beginCaptures": { "1": { - "name": "keyword.other.var.cs" + "name": "storage.type.var.cs" }, "2": { "patterns": [ @@ -2635,7 +3257,7 @@ "match": "(?x) # e.g. int x OR var x\n(?:\n \\b(var)\\b|\n (?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n )\n)\\s+\n(\\g)\\b\\s*\n(?=[,)\\]])", "captures": { "1": { - "name": "keyword.other.var.cs" + "name": "storage.type.var.cs" }, "2": { "patterns": [ @@ -2653,7 +3275,7 @@ "match": "(?x) # e.g. int x OR var x\n(?:\n \\b(var)\\b|\n (?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n )\n)\\s+\n(\\g)\\b\\s*\n(?=[,)])", "captures": { "1": { - "name": "keyword.other.var.cs" + "name": "storage.type.var.cs" }, "2": { "patterns": [ @@ -2667,16 +3289,13 @@ } } }, - "checked-unchecked-expression": { - "begin": "(?>>?|\\|)?=(?!=|>)", + "beginCaptures": { + "0": { + "patterns": [ + { + "include": "#assignment-operators" + } + ] + } + }, + "end": "(?=[,\\)\\];}])", + "patterns": [ + { + "include": "#ref-modifier" + }, + { + "include": "#expression" + } + ] + }, + "assignment-operators": { "patterns": [ { "name": "keyword.operator.assignment.compound.cs", @@ -3391,11 +4006,19 @@ }, { "name": "keyword.operator.assignment.compound.bitwise.cs", - "match": "\\&=|\\^=|<<=|>>=|\\|=" + "match": "\\&=|\\^=|<<=|>>>?=|\\|=" }, + { + "name": "keyword.operator.assignment.cs", + "match": "\\=" + } + ] + }, + "expression-operators": { + "patterns": [ { "name": "keyword.operator.bitwise.shift.cs", - "match": "<<|>>" + "match": "<<|>>>?" }, { "name": "keyword.operator.comparison.cs", @@ -3413,10 +4036,6 @@ "name": "keyword.operator.bitwise.cs", "match": "\\&|~|\\^|\\|" }, - { - "name": "keyword.operator.assignment.cs", - "match": "\\=" - }, { "name": "keyword.operator.decrement.cs", "match": "--" @@ -3427,56 +4046,50 @@ }, { "name": "keyword.operator.arithmetic.cs", - "match": "%|\\*|/|-|\\+" + "match": "\\+|-(?!>)|\\*|/|%" }, { "name": "keyword.operator.null-coalescing.cs", "match": "\\?\\?" + }, + { + "name": "keyword.operator.range.cs", + "match": "\\.\\." } ] }, - "switch-literal": { - "name": "constant.language.null.cs", - "match": "(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)?", + "match": "(?x)\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?(?!\\?))? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n \\s*(?:,\\s*)* # commata for multi-dimensional arrays\n \\]\n (?:\\s*\\?(?!\\?))? # arrays can be nullable reference types\n )*\n )\n)?", "captures": { "1": { - "name": "keyword.other.as.cs" + "name": "keyword.operator.expression.as.cs" }, "2": { "patterns": [ @@ -3556,34 +4169,20 @@ } } }, - "is-expression": { - "match": "(?x)\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)?", - "captures": { - "1": { - "name": "keyword.other.is.cs" + "language-variable": { + "patterns": [ + { + "name": "variable.language.$1.cs", + "match": "\\b(base|this)\\b" }, - "2": { - "patterns": [ - { - "include": "#type" - } - ] + { + "name": "variable.other.$1.cs", + "match": "\\b(value)\\b" } - } - }, - "this-or-base-expression": { - "match": "\\b(?:(base)|(this))\\b", - "captures": { - "1": { - "name": "keyword.other.base.cs" - }, - "2": { - "name": "keyword.other.this.cs" - } - } + ] }, "invocation-expression": { - "begin": "(?x)\n(?:(\\?)\\s*)? # preceding null-conditional operator?\n(?:(\\.)\\s*)? # preceding dot?\n(@?[_[:alpha:]][_[:alnum:]]*)\\s* # method name\n(?\\s*<([^<>]|\\g)+>\\s*)?\\s* # type arguments\n(?=\\() # open paren of argument list", + "begin": "(?x)\n(?:\n (?:(\\?)\\s*)? # preceding null-conditional operator?\n (\\.)\\s*| # preceding dot?\n (->)\\s* # preceding pointer arrow?\n)?\n(@?[_[:alpha:]][_[:alnum:]]*)\\s* # method name\n(\n <\n (?\n [^<>()]++|\n <\\g*+>|\n \\(\\g*+\\)\n )*+\n >\\s*\n)? # type arguments\n(?=\\() # open paren of argument list", "beginCaptures": { "1": { "name": "keyword.operator.null-conditional.cs" @@ -3592,9 +4191,12 @@ "name": "punctuation.accessor.cs" }, "3": { - "name": "entity.name.function.cs" + "name": "punctuation.accessor.pointer.cs" }, "4": { + "name": "entity.name.function.cs" + }, + "5": { "patterns": [ { "include": "#type-arguments" @@ -3610,7 +4212,7 @@ ] }, "element-access-expression": { - "begin": "(?x)\n(?:(\\?)\\s*)? # preceding null-conditional operator?\n(?:(\\.)\\s*)? # preceding dot?\n(?:(@?[_[:alpha:]][_[:alnum:]]*)\\s*)? # property name\n(?:(\\?)\\s*)? # null-conditional operator?\n(?=\\[) # open bracket of argument list", + "begin": "(?x)\n(?:\n (?:(\\?)\\s*)? # preceding null-conditional operator?\n (\\.)\\s*| # preceding dot?\n (->)\\s* # preceding pointer arrow?\n)?\n(?:(@?[_[:alpha:]][_[:alnum:]]*)\\s*)? # property name\n(?:(\\?)\\s*)? # null-conditional operator?\n(?=\\[) # open bracket of argument list", "beginCaptures": { "1": { "name": "keyword.operator.null-conditional.cs" @@ -3619,9 +4221,12 @@ "name": "punctuation.accessor.cs" }, "3": { - "name": "variable.other.object.property.cs" + "name": "punctuation.accessor.pointer.cs" }, "4": { + "name": "variable.other.object.property.cs" + }, + "5": { "name": "keyword.operator.null-conditional.cs" } }, @@ -3635,7 +4240,7 @@ "member-access-expression": { "patterns": [ { - "match": "(?x)\n(?:(\\?)\\s*)? # preceding null-conditional operator?\n(\\.)\\s* # preceding dot\n(@?[_[:alpha:]][_[:alnum:]]*)\\s* # property name\n(?![_[:alnum:]]|\\(|(\\?)?\\[|<) # next character is not alpha-numeric, nor a (, [, or <. Also, test for ?[", + "match": "(?x)\n(?:\n (?:(\\?)\\s*)? # preceding null-conditional operator?\n (\\.)\\s*| # preceding dot?\n (->)\\s* # preceding pointer arrow?\n)\n(@?[_[:alpha:]][_[:alnum:]]*)\\s* # property name\n(?![_[:alnum:]]|\\(|(\\?)?\\[|<) # next character is not alpha-numeric, nor a (, [, or <. Also, test for ?[", "captures": { "1": { "name": "keyword.operator.null-conditional.cs" @@ -3644,6 +4249,9 @@ "name": "punctuation.accessor.cs" }, "3": { + "name": "punctuation.accessor.pointer.cs" + }, + "4": { "name": "variable.other.object.property.cs" } } @@ -3667,7 +4275,7 @@ } }, { - "match": "(?x)\n(@?[_[:alpha:]][_[:alnum:]]*)\n(?=\n (\\s*\\?)?\n \\s*\\.\\s*@?[_[:alpha:]][_[:alnum:]]*\n)", + "match": "(?x)\n(@?[_[:alpha:]][_[:alnum:]]*)\n(?=\n \\s*(?:(?:\\?\\s*)?\\.|->)\n \\s*@?[_[:alpha:]][_[:alnum:]]*\n)", "captures": { "1": { "name": "variable.other.object.cs" @@ -3690,7 +4298,7 @@ "begin": "(?x)\n(new)(?:\\s+\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n))?\\s*\n(?=\\()", "beginCaptures": { "1": { - "name": "keyword.other.new.cs" + "name": "keyword.operator.expression.new.cs" }, "2": { "patterns": [ @@ -3708,10 +4316,10 @@ ] }, "object-creation-expression-with-no-parameters": { - "match": "(?x)\n(new)\\s+\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s*\n(?=\\{|$)", + "match": "(?x)\n(new)\\s+\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s*\n(?=\\{|//|/\\*|$)", "captures": { "1": { - "name": "keyword.other.new.cs" + "name": "keyword.operator.expression.new.cs" }, "2": { "patterns": [ @@ -3726,7 +4334,7 @@ "begin": "(?x)\n\\b(new|stackalloc)\\b\\s*\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)?\\s*\n(?=\\[)", "beginCaptures": { "1": { - "name": "keyword.other.new.cs" + "name": "keyword.operator.expression.$1.cs" }, "2": { "patterns": [ @@ -3744,14 +4352,17 @@ ] }, "anonymous-object-creation-expression": { - "begin": "\\b(new)\\b\\s*(?=\\{|$)", + "begin": "\\b(new)\\b\\s*(?=\\{|//|/\\*|$)", "beginCaptures": { "1": { - "name": "keyword.other.new.cs" + "name": "keyword.operator.expression.new.cs" } }, "end": "(?<=\\})", "patterns": [ + { + "include": "#comment" + }, { "include": "#initializer-expression" } @@ -3826,10 +4437,10 @@ ] }, "parameter": { - "match": "(?x)\n(?:(?:\\b(ref|params|out|in|this)\\b)\\s+)?\n(?\n (?:\n (?:ref\\s+)? # ref return\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s+\n(\\g)", + "match": "(?x)\n(?:(?:\\b(ref|params|out|in|this)\\b)\\s+)?\n(?\n (?:\n (?:ref\\s+)? # ref return\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^()]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s+\n(\\g)", "captures": { "1": { - "name": "storage.modifier.cs" + "name": "storage.modifier.$1.cs" }, "2": { "patterns": [ @@ -3913,11 +4524,25 @@ "argument": { "patterns": [ { - "name": "storage.modifier.cs", - "match": "\\b(ref|out|in)\\b" + "name": "storage.modifier.$1.cs", + "match": "\\b(ref|in)\\b" }, { - "include": "#declaration-expression-local" + "begin": "\\b(out)\\b", + "beginCaptures": { + "1": { + "name": "storage.modifier.out.cs" + } + }, + "end": "(?=,|\\)|\\])", + "patterns": [ + { + "include": "#declaration-expression-local" + }, + { + "include": "#expression" + } + ] }, { "include": "#expression" @@ -3928,7 +4553,7 @@ "begin": "(?x)\n\\b(from)\\b\\s*\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)?\n\\s+(\\g)\\b\\s*\n\\b(in)\\b\\s*", "beginCaptures": { "1": { - "name": "keyword.query.from.cs" + "name": "keyword.operator.expression.query.from.cs" }, "2": { "patterns": [ @@ -3941,7 +4566,7 @@ "name": "entity.name.variable.range-variable.cs" }, "8": { - "name": "keyword.query.in.cs" + "name": "keyword.operator.expression.query.in.cs" } }, "end": "(?=;|\\))", @@ -3980,7 +4605,7 @@ "begin": "(?x)\n\\b(let)\\b\\s*\n(@?[_[:alpha:]][_[:alnum:]]*)\\b\\s*\n(=)\\s*", "beginCaptures": { "1": { - "name": "keyword.query.let.cs" + "name": "keyword.operator.expression.query.let.cs" }, "2": { "name": "entity.name.variable.range-variable.cs" @@ -4003,7 +4628,7 @@ "begin": "(?x)\n\\b(where)\\b\\s*", "beginCaptures": { "1": { - "name": "keyword.query.where.cs" + "name": "keyword.operator.expression.query.where.cs" } }, "end": "(?=;|\\))", @@ -4020,7 +4645,7 @@ "begin": "(?x)\n\\b(join)\\b\\s*\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)?\n\\s+(\\g)\\b\\s*\n\\b(in)\\b\\s*", "beginCaptures": { "1": { - "name": "keyword.query.join.cs" + "name": "keyword.operator.expression.query.join.cs" }, "2": { "patterns": [ @@ -4033,7 +4658,7 @@ "name": "entity.name.variable.range-variable.cs" }, "8": { - "name": "keyword.query.in.cs" + "name": "keyword.operator.expression.query.in.cs" } }, "end": "(?=;|\\))", @@ -4059,7 +4684,7 @@ "match": "\\b(on)\\b\\s*", "captures": { "1": { - "name": "keyword.query.on.cs" + "name": "keyword.operator.expression.query.on.cs" } } }, @@ -4067,7 +4692,7 @@ "match": "\\b(equals)\\b\\s*", "captures": { "1": { - "name": "keyword.query.equals.cs" + "name": "keyword.operator.expression.query.equals.cs" } } }, @@ -4075,7 +4700,7 @@ "match": "(?x)\n\\b(into)\\b\\s*\n(@?[_[:alpha:]][_[:alnum:]]*)\\b\\s*", "captures": { "1": { - "name": "keyword.query.into.cs" + "name": "keyword.operator.expression.query.into.cs" }, "2": { "name": "entity.name.variable.range-variable.cs" @@ -4086,7 +4711,7 @@ "begin": "\\b(orderby)\\b\\s*", "beginCaptures": { "1": { - "name": "keyword.query.orderby.cs" + "name": "keyword.operator.expression.query.orderby.cs" } }, "end": "(?=;|\\))", @@ -4106,13 +4731,10 @@ ] }, "ordering-direction": { - "match": "\\b(?:(ascending)|(descending))\\b", + "match": "\\b(ascending|descending)\\b", "captures": { "1": { - "name": "keyword.query.ascending.cs" - }, - "2": { - "name": "keyword.query.descending.cs" + "name": "keyword.operator.expression.query.$1.cs" } } }, @@ -4120,7 +4742,7 @@ "begin": "\\b(select)\\b\\s*", "beginCaptures": { "1": { - "name": "keyword.query.select.cs" + "name": "keyword.operator.expression.query.select.cs" } }, "end": "(?=;|\\))", @@ -4137,7 +4759,7 @@ "begin": "\\b(group)\\b\\s*", "beginCaptures": { "1": { - "name": "keyword.query.group.cs" + "name": "keyword.operator.expression.query.group.cs" } }, "end": "(?=;|\\))", @@ -4160,7 +4782,7 @@ "match": "\\b(by)\\b\\s*", "captures": { "1": { - "name": "keyword.query.by.cs" + "name": "keyword.operator.expression.query.by.cs" } } }, @@ -4168,7 +4790,7 @@ "match": "(?x)\n\\b(into)\\b\\s*\n(@?[_[:alpha:]][_[:alnum:]]*)\\b\\s*", "captures": { "1": { - "name": "keyword.query.into.cs" + "name": "keyword.operator.expression.query.into.cs" }, "2": { "name": "entity.name.variable.range-variable.cs" @@ -4178,119 +4800,138 @@ "anonymous-method-expression": { "patterns": [ { - "begin": "(?x)\n(?:\\b(async)\\b\\s*)?\n(@?[_[:alpha:]][_[:alnum:]]*)\\b\\s*\n(=>)", + "begin": "(?x)\n((?:\\b(?:async|static)\\b\\s*)*)\n(?:\n (@?[_[:alpha:]][_[:alnum:]]*)\\b|\n (\\()\n (?(?:[^()]|\\(\\g\\))*)\n (\\))\n)\\s*\n(=>)", "beginCaptures": { "1": { - "name": "storage.modifier.cs" + "patterns": [ + { + "match": "async|static", + "name": "storage.modifier.$0.cs" + } + ] }, "2": { "name": "entity.name.variable.parameter.cs" }, "3": { - "name": "keyword.operator.arrow.cs" - } - }, - "end": "(?=\\)|;|}|,)", - "patterns": [ - { - "include": "#block" + "name": "punctuation.parenthesis.open.cs" }, - { - "include": "#ref-modifier" - }, - { - "include": "#expression" - } - ] - }, - { - "begin": "(?x)\n(?:\\b(async)\\b\\s*)?\n(\\(.*?\\))\\s*\n(=>)", - "beginCaptures": { - "1": { - "name": "storage.modifier.cs" - }, - "2": { + "4": { "patterns": [ { - "include": "#lambda-parameter-list" + "include": "#comment" + }, + { + "include": "#explicit-anonymous-function-parameter" + }, + { + "include": "#implicit-anonymous-function-parameter" + }, + { + "include": "#default-argument" + }, + { + "include": "#punctuation-comma" } ] }, - "3": { + "5": { + "name": "punctuation.parenthesis.close.cs" + }, + "6": { "name": "keyword.operator.arrow.cs" } }, - "end": "(?=\\)|;|}|,)", + "end": "(?=[,;)}])", "patterns": [ { - "include": "#block" + "include": "#intrusive" }, { - "include": "#ref-modifier" + "begin": "(?={)", + "end": "(?=[,;)}])", + "patterns": [ + { + "include": "#block" + }, + { + "include": "#intrusive" + } + ] }, { - "include": "#expression" + "begin": "\\b(ref)\\b|(?=\\S)", + "beginCaptures": { + "1": { + "name": "storage.modifier.ref.cs" + } + }, + "end": "(?=[,;)}])", + "patterns": [ + { + "include": "#expression" + } + ] } ] }, { - "begin": "(?x)\n(?:\\b(async)\\b\\s*)?\n(?:\\b(delegate)\\b\\s*)", + "begin": "(?x)\n((?:\\b(?:async|static)\\b\\s*)*)\n\\b(delegate)\\b\\s*", "beginCaptures": { "1": { - "name": "storage.modifier.cs" + "patterns": [ + { + "match": "async|static", + "name": "storage.modifier.$0.cs" + } + ] }, "2": { - "name": "keyword.other.delegate.cs" + "name": "storage.type.delegate.cs" } }, - "end": "(?=\\)|;|}|,)", + "end": "(?<=})|(?=[,;)}])", "patterns": [ { - "include": "#parenthesized-parameter-list" + "include": "#intrusive" + }, + { + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.parenthesis.open.cs" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.parenthesis.close.cs" + } + }, + "patterns": [ + { + "include": "#intrusive" + }, + { + "include": "#explicit-anonymous-function-parameter" + }, + { + "include": "#punctuation-comma" + } + ] }, { "include": "#block" - }, - { - "include": "#expression" } ] } ] }, - "lambda-parameter-list": { - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "punctuation.parenthesis.open.cs" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.parenthesis.close.cs" - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#attribute-section" - }, - { - "include": "#lambda-parameter" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "lambda-parameter": { - "match": "(?x)\n(?:\\b(ref|out|in)\\b)?\\s*\n(?:(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?\\s*<(?:[^<>]|\\g)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^\\(\\)]|\\g)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s+)?\n(\\g)\\b\\s*\n(?=[,)])", + "explicit-anonymous-function-parameter": { + "match": "(?x)\n(?:\\b(ref|params|out|in)\\b\\s*)?\n(?\n (?:\n (?:\n (?:(?@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (? # identifier + type arguments (if any)\n \\g\\s*\n (?<(?:[^<>]|\\g)*>\\s*)?\n )\n (?:\\s*\\.\\s*\\g)* | # Are there any more names being dotted into?\n (?\\s*\\((?:[^()]|\\g)*\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s*\n\\b(\\g)\\b", "captures": { "1": { - "name": "storage.modifier.cs" + "name": "storage.modifier.$1.cs" }, "2": { "patterns": [ @@ -4304,8 +4945,25 @@ } } }, + "implicit-anonymous-function-parameter": { + "match": "\\@?[_[:alpha:]][_[:alnum:]]*\\b", + "name": "entity.name.variable.parameter.cs" + }, + "default-argument": { + "begin": "=", + "beginCaptures": { + "0": { + "name": "keyword.operator.assignment.cs" + } + }, + "end": "(?=,|\\))", + "patterns": [ + { + "include": "#expression" + } + ] + }, "type": { - "name": "meta.type.cs", "patterns": [ { "include": "#comment" @@ -4333,16 +4991,19 @@ }, { "include": "#type-nullable-suffix" + }, + { + "include": "#type-pointer-suffix" } ] }, "ref-modifier": { - "name": "storage.modifier.cs", - "match": "\\b(ref)\\b" + "name": "storage.modifier.ref.cs", + "match": "\\bref\\b" }, "readonly-modifier": { - "name": "storage.modifier.cs", - "match": "\\b(readonly)\\b" + "name": "storage.modifier.readonly.cs", + "match": "\\breadonly\\b" }, "tuple-type": { "begin": "\\(", @@ -4382,10 +5043,10 @@ } }, "type-builtin": { - "match": "\\b(bool|byte|char|decimal|double|float|int|long|object|sbyte|short|string|uint|ulong|ushort|void|dynamic)\\b", + "match": "\\b(bool|s?byte|u?short|n?u?int|u?long|float|double|decimal|char|string|object|void|dynamic)\\b", "captures": { "1": { - "name": "keyword.type.cs" + "name": "keyword.type.$1.cs" } } }, @@ -4444,9 +5105,6 @@ } }, "patterns": [ - { - "include": "#comment" - }, { "include": "#type" }, @@ -4469,6 +5127,9 @@ } }, "patterns": [ + { + "include": "#intrusive" + }, { "include": "#punctuation-comma" } @@ -4476,11 +5137,11 @@ }, "type-nullable-suffix": { "match": "\\?", - "captures": { - "0": { - "name": "punctuation.separator.question-mark.cs" - } - } + "name": "punctuation.separator.question-mark.cs" + }, + "type-pointer-suffix": { + "match": "\\*", + "name": "punctuation.separator.asterisk.cs" }, "operator-assignment": { "name": "keyword.operator.assignment.cs", @@ -4498,6 +5159,16 @@ "name": "punctuation.accessor.cs", "match": "\\." }, + "intrusive": { + "patterns": [ + { + "include": "#preprocessor" + }, + { + "include": "#comment" + } + ] + }, "preprocessor": { "name": "meta.preprocessor.cs", "begin": "^\\s*(\\#)\\s*", @@ -4803,38 +5474,47 @@ "comment": { "patterns": [ { - "name": "comment.block.cs", - "begin": "/\\*", - "beginCaptures": { - "0": { - "name": "punctuation.definition.comment.cs" - } - }, - "end": "\\*/", - "endCaptures": { - "0": { - "name": "punctuation.definition.comment.cs" - } - } - }, - { - "begin": "(^\\s+)?(?=//)", - "beginCaptures": { + "name": "comment.block.documentation.cs", + "begin": "(^\\s+)?(///)(?!/)", + "while": "^(\\s*)(///)(?!/)", + "captures": { "1": { "name": "punctuation.whitespace.comment.leading.cs" + }, + "2": { + "name": "punctuation.definition.comment.cs" } }, - "end": "(?=$)", "patterns": [ { - "name": "comment.block.documentation.cs", - "begin": "(??@^|/])///(?!/)", + "while": "(??@^|/])///(?!/)", "patterns": [ { "include": "text.html.markdown" @@ -600,7 +600,7 @@ }, { "name": "comment.line.double-slash.fsharp", - "match": "//.*$" + "match": "(??@^|/])//(?![!%&+-.<=>?@^|]).*$" } ] }, @@ -1125,7 +1125,7 @@ }, { "name": "keyword.symbol.fsharp", - "match": "(&&&|\\|\\|\\||\\^\\^\\^|~~~|<<<|>>>|\\|>|:>|:\\?>|:|\\[|\\]|\\;|<>|=|@|\\|\\||&&|{|}|\\||_|\\.\\.|\\,|\\+|\\-|\\*|\\/|\\^|\\!|\\>|\\>\\=|\\>\\>|\\<|\\<\\=|\\(|\\)|\\<\\<)" + "match": "(&&&|\\|\\|\\||\\^\\^\\^|~~~|~\\+|~\\-|<<<|>>>|\\|>|:>|:\\?>|:|\\[|\\]|\\;|<>|=|@|\\|\\||&&|&|%|{|}|\\||_|\\.\\.|\\,|\\+|\\-|\\*|\\/|\\^|\\!|\\>|\\>\\=|\\>\\>|\\<|\\<\\=|\\(|\\)|\\<\\<)" } ] }, @@ -1133,7 +1133,7 @@ "patterns": [ { "name": "entity.name.section.fsharp", - "begin": "\\b(namespace global)|\\b(namespace|module)\\s*(public|internal|private|rec)?\\s+([[:alpha:]][[:alpha:]0-9'_. ]*)", + "begin": "\\b(namespace global)|\\b(namespace|module)\\s*(public|internal|private|rec)?\\s+([[:alpha:]|``][[:alpha:]0-9'_. ]*)", "end": "(\\s?=|\\s|$)", "beginCaptures": { "1": { @@ -1171,7 +1171,7 @@ }, { "name": "namespace.open.fsharp", - "begin": "\\b(open type|open)\\s+([[:alpha:]][[:alpha:]0-9'_]*)(?=(\\.[A-Z][[:alpha:]0-9_]*)*)", + "begin": "\\b(open type|open)\\s+([[:alpha:]|``][[:alpha:]0-9'_]*)(?=(\\.[A-Z][[:alpha:]0-9_]*)*)", "end": "(\\s|$)", "beginCaptures": { "1": { @@ -1331,7 +1331,7 @@ "match": "\\(\\)" }, { - "match": "(\\?{0,1})(``[[:alpha:]0-9'`^:,._ ]+``|(?!private\\b)\\b[\\w[:alpha:]0-9'`<>^._ ]+)", + "match": "(\\?{0,1})(``[[:alpha:]0-9'`^:,._ ]+``|(?!private|struct\\b)\\b[\\w[:alpha:]0-9'`<>^._ ]+)", "captures": { "1": { "name": "keyword.symbol.fsharp" diff --git a/extensions/r/syntaxes/r.tmLanguage.json b/extensions/r/syntaxes/r.tmLanguage.json index 88de4fd07d9..d50ab5b6d78 100644 --- a/extensions/r/syntaxes/r.tmLanguage.json +++ b/extensions/r/syntaxes/r.tmLanguage.json @@ -639,4 +639,4 @@ ] } } -} +} \ No newline at end of file diff --git a/extensions/razor/build/update-grammar.mjs b/extensions/razor/build/update-grammar.mjs index db0ac9dbd6f..cacb9e79abc 100644 --- a/extensions/razor/build/update-grammar.mjs +++ b/extensions/razor/build/update-grammar.mjs @@ -12,7 +12,7 @@ function patchGrammar(grammar) { } const razorGrammarRepo = 'dotnet/razor'; -const grammarPath = 'src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/syntaxes/aspnetcorerazor.tmLanguage.json'; +const grammarPath = 'src/Razor/src/Microsoft.VisualStudio.RazorExtension/EmbeddedGrammars/aspnetcorerazor.tmLanguage.json'; vscodeGrammarUpdater.update(razorGrammarRepo, grammarPath, './syntaxes/cshtml.tmLanguage.json', grammar => patchGrammar(grammar), 'main'); diff --git a/extensions/razor/cgmanifest.json b/extensions/razor/cgmanifest.json index 799e12cf325..e90c7d75d8c 100644 --- a/extensions/razor/cgmanifest.json +++ b/extensions/razor/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "dotnet/razor", "repositoryUrl": "https://github.com/dotnet/razor", - "commitHash": "69f60231df08319b544d3d32a588575acbb58ff0" + "commitHash": "b44d0a906d054d2d343adc3f58cbea11d97d7488" } }, "license": "MIT", diff --git a/extensions/razor/syntaxes/cshtml.tmLanguage.json b/extensions/razor/syntaxes/cshtml.tmLanguage.json index 0b5463ee3ca..4594037960a 100644 --- a/extensions/razor/syntaxes/cshtml.tmLanguage.json +++ b/extensions/razor/syntaxes/cshtml.tmLanguage.json @@ -1,10 +1,10 @@ { "information_for_contributors": [ - "This file has been converted from https://github.com/dotnet/razor/blob/master/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/syntaxes/aspnetcorerazor.tmLanguage.json", + "This file has been converted from https://github.com/dotnet/razor/blob/master/src/Razor/src/Microsoft.VisualStudio.RazorExtension/EmbeddedGrammars/aspnetcorerazor.tmLanguage.json", "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/dotnet/razor/commit/69f60231df08319b544d3d32a588575acbb58ff0", + "version": "https://github.com/dotnet/razor/commit/b44d0a906d054d2d343adc3f58cbea11d97d7488", "name": "ASP.NET Razor", "scopeName": "text.html.cshtml", "patterns": [ diff --git a/extensions/rust/cgmanifest.json b/extensions/rust/cgmanifest.json index 512dc80a65b..46bf27cd454 100644 --- a/extensions/rust/cgmanifest.json +++ b/extensions/rust/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "rust-syntax", "repositoryUrl": "https://github.com/dustypomerleau/rust-syntax", - "commitHash": "328a68299533bc2b8c71028be741cce78a9e0d53" + "commitHash": "20730dff3c367cb40a7edd278fdaf0239ea50833" } }, "license": "MIT", diff --git a/extensions/rust/syntaxes/rust.tmLanguage.json b/extensions/rust/syntaxes/rust.tmLanguage.json index 8fcbdc5082f..542e8ec1fd1 100644 --- a/extensions/rust/syntaxes/rust.tmLanguage.json +++ b/extensions/rust/syntaxes/rust.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/dustypomerleau/rust-syntax/commit/328a68299533bc2b8c71028be741cce78a9e0d53", + "version": "https://github.com/dustypomerleau/rust-syntax/commit/20730dff3c367cb40a7edd278fdaf0239ea50833", "name": "Rust", "scopeName": "source.rust", "patterns": [ @@ -119,54 +119,6 @@ } } }, - { - "comment": "attributes", - "name": "meta.attribute.rust", - "begin": "(#)(\\!?)(\\[)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.attribute.rust" - }, - "2": { - "name": "keyword.operator.attribute.inner.rust" - }, - "3": { - "name": "punctuation.brackets.attribute.rust" - } - }, - "end": "\\]", - "endCaptures": { - "0": { - "name": "punctuation.brackets.attribute.rust" - } - }, - "patterns": [ - { - "include": "#block-comments" - }, - { - "include": "#comments" - }, - { - "include": "#keywords" - }, - { - "include": "#lifetimes" - }, - { - "include": "#punctuation" - }, - { - "include": "#strings" - }, - { - "include": "#gtypes" - }, - { - "include": "#types" - } - ] - }, { "comment": "modules", "match": "(mod)\\s+((?:r#(?!crate|[Ss]elf|super))?[a-z][A-Za-z0-9_]*)", @@ -257,6 +209,9 @@ { "include": "#comments" }, + { + "include": "#attributes" + }, { "include": "#lvariables" }, @@ -421,7 +376,7 @@ "escapes": { "comment": "escapes: ASCII, byte, Unicode, quote, regex", "name": "constant.character.escape.rust", - "match": "(\\\\)(?:(?:(x[0-7][0-7a-fA-F])|(u(\\{)[\\da-fA-F]{4,6}(\\}))|.))", + "match": "(\\\\)(?:(?:(x[0-7][\\da-fA-F])|(u(\\{)[\\da-fA-F]{4,6}(\\}))|.))", "captures": { "1": { "name": "constant.character.escape.backslash.rust" @@ -440,6 +395,51 @@ } } }, + "attributes": { + "comment": "attributes", + "name": "meta.attribute.rust", + "begin": "(#)(\\!?)(\\[)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.attribute.rust" + }, + "3": { + "name": "punctuation.brackets.attribute.rust" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "punctuation.brackets.attribute.rust" + } + }, + "patterns": [ + { + "include": "#block-comments" + }, + { + "include": "#comments" + }, + { + "include": "#keywords" + }, + { + "include": "#lifetimes" + }, + { + "include": "#punctuation" + }, + { + "include": "#strings" + }, + { + "include": "#gtypes" + }, + { + "include": "#types" + } + ] + }, "functions": { "patterns": [ { @@ -548,6 +548,9 @@ { "include": "#comments" }, + { + "include": "#attributes" + }, { "include": "#keywords" }, @@ -608,6 +611,9 @@ { "include": "#comments" }, + { + "include": "#attributes" + }, { "include": "#keywords" }, @@ -913,7 +919,7 @@ }, { "comment": "parameterized types", - "begin": "\\b([A-Z][A-Za-z0-9]*)(<)", + "begin": "\\b(_?[A-Z][A-Za-z0-9_]*)(<)", "beginCaptures": { "1": { "name": "entity.name.type.rust" @@ -962,7 +968,7 @@ }, { "comment": "trait declarations", - "match": "\\b(trait)\\s+([A-Z][A-Za-z0-9]*)\\b", + "match": "\\b(trait)\\s+(_?[A-Z][A-Za-z0-9_]*)\\b", "captures": { "1": { "name": "keyword.declaration.trait.rust storage.type.rust" @@ -974,7 +980,7 @@ }, { "comment": "struct declarations", - "match": "\\b(struct)\\s+([A-Z][A-Za-z0-9]*)\\b", + "match": "\\b(struct)\\s+(_?[A-Z][A-Za-z0-9_]*)\\b", "captures": { "1": { "name": "keyword.declaration.struct.rust storage.type.rust" @@ -986,7 +992,7 @@ }, { "comment": "enum declarations", - "match": "\\b(enum)\\s+([A-Z][A-Za-z0-9_]*)\\b", + "match": "\\b(enum)\\s+(_?[A-Z][A-Za-z0-9_]*)\\b", "captures": { "1": { "name": "keyword.declaration.enum.rust storage.type.rust" @@ -998,7 +1004,7 @@ }, { "comment": "type declarations", - "match": "\\b(type)\\s+([A-Z][A-Za-z0-9_]*)\\b", + "match": "\\b(type)\\s+(_?[A-Z][A-Za-z0-9_]*)\\b", "captures": { "1": { "name": "keyword.declaration.type.rust storage.type.rust" @@ -1011,7 +1017,7 @@ { "comment": "types", "name": "entity.name.type.rust", - "match": "\\b[A-Z][A-Za-z0-9]*\\b(?!!)" + "match": "\\b_?[A-Z][A-Za-z0-9_]*\\b(?!!)" } ] }, diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_cs.json b/extensions/vscode-colorize-tests/test/colorize-results/test_cs.json index bf42bc29b6d..7f4bbb7758b 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_cs.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_cs.json @@ -1,16 +1,16 @@ [ { "c": "using", - "t": "source.cs keyword.other.using.cs", + "t": "source.cs keyword.other.directive.using.cs", "r": { - "dark_plus": "keyword.other.using: #C586C0", - "light_plus": "keyword.other.using: #AF00DB", + "dark_plus": "keyword.other.directive.using: #C586C0", + "light_plus": "keyword.other.directive.using: #AF00DB", "dark_vs": "keyword: #569CD6", "light_vs": "keyword: #0000FF", - "hc_black": "keyword.other.using: #C586C0", - "dark_modern": "keyword.other.using: #C586C0", - "hc_light": "keyword.other.using: #B5200D", - "light_modern": "keyword.other.using: #AF00DB" + "hc_black": "keyword.other.directive.using: #C586C0", + "dark_modern": "keyword.other.directive.using: #C586C0", + "hc_light": "keyword.other.directive.using: #B5200D", + "light_modern": "keyword.other.directive.using: #AF00DB" } }, { @@ -57,16 +57,16 @@ }, { "c": "namespace", - "t": "source.cs keyword.other.namespace.cs", + "t": "source.cs storage.type.namespace.cs", "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6", - "dark_modern": "keyword: #569CD6", - "hc_light": "keyword: #0F4A85", - "light_modern": "keyword: #0000FF" + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6", + "dark_modern": "storage.type: #569CD6", + "hc_light": "storage.type: #0F4A85", + "light_modern": "storage.type: #0000FF" } }, { @@ -127,16 +127,16 @@ }, { "c": "class", - "t": "source.cs keyword.other.class.cs", + "t": "source.cs storage.type.class.cs", "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6", - "dark_modern": "keyword: #569CD6", - "hc_light": "keyword: #0F4A85", - "light_modern": "keyword: #0000FF" + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6", + "dark_modern": "storage.type: #569CD6", + "hc_light": "storage.type: #0F4A85", + "light_modern": "storage.type: #0000FF" } }, { @@ -211,7 +211,7 @@ }, { "c": "static", - "t": "source.cs storage.modifier.cs", + "t": "source.cs storage.modifier.static.cs", "r": { "dark_plus": "storage.modifier: #569CD6", "light_plus": "storage.modifier: #0000FF", @@ -239,7 +239,7 @@ }, { "c": "void", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.void.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -295,7 +295,7 @@ }, { "c": "string", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.string.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -925,7 +925,7 @@ }, { "c": "int", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.int.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -1303,7 +1303,7 @@ }, { "c": "const", - "t": "source.cs storage.modifier.cs", + "t": "source.cs storage.modifier.const.cs", "r": { "dark_plus": "storage.modifier: #569CD6", "light_plus": "storage.modifier: #0000FF", @@ -1331,7 +1331,7 @@ }, { "c": "double", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.double.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -1527,7 +1527,7 @@ }, { "c": "int", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.int.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -1681,7 +1681,7 @@ }, { "c": "double", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.double.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -1933,16 +1933,16 @@ }, { "c": " ", - "t": "source.cs punctuation.whitespace.comment.leading.cs", + "t": "source.cs comment.line.double-slash.cs punctuation.whitespace.comment.leading.cs", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF", - "dark_modern": "default: #CCCCCC", - "hc_light": "default: #292929", - "light_modern": "default: #3B3B3B" + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668", + "dark_modern": "comment: #6A9955", + "hc_light": "comment: #515151", + "light_modern": "comment: #008000" } }, { @@ -2255,7 +2255,7 @@ }, { "c": "public", - "t": "source.cs storage.modifier.cs", + "t": "source.cs storage.modifier.public.cs", "r": { "dark_plus": "storage.modifier: #569CD6", "light_plus": "storage.modifier: #0000FF", @@ -2283,7 +2283,7 @@ }, { "c": "void", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.void.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -2451,16 +2451,16 @@ }, { "c": "new", - "t": "source.cs keyword.other.new.cs", + "t": "source.cs keyword.operator.expression.new.cs", "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6", - "dark_modern": "keyword: #569CD6", - "hc_light": "keyword: #0F4A85", - "light_modern": "keyword: #0000FF" + "dark_plus": "keyword.operator.expression: #569CD6", + "light_plus": "keyword.operator.expression: #0000FF", + "dark_vs": "keyword.operator.expression: #569CD6", + "light_vs": "keyword.operator.expression: #0000FF", + "hc_black": "keyword.operator.expression: #569CD6", + "dark_modern": "keyword.operator.expression: #569CD6", + "hc_light": "keyword.operator.expression: #0F4A85", + "light_modern": "keyword.operator.expression: #0000FF" } }, { @@ -2507,7 +2507,7 @@ }, { "c": "int", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.int.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -2619,7 +2619,7 @@ }, { "c": "int", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.int.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -2759,16 +2759,16 @@ }, { "c": "new", - "t": "source.cs keyword.other.new.cs", + "t": "source.cs keyword.operator.expression.new.cs", "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6", - "dark_modern": "keyword: #569CD6", - "hc_light": "keyword: #0F4A85", - "light_modern": "keyword: #0000FF" + "dark_plus": "keyword.operator.expression: #569CD6", + "light_plus": "keyword.operator.expression: #0000FF", + "dark_vs": "keyword.operator.expression: #569CD6", + "light_vs": "keyword.operator.expression: #0000FF", + "hc_black": "keyword.operator.expression: #569CD6", + "dark_modern": "keyword.operator.expression: #569CD6", + "hc_light": "keyword.operator.expression: #0F4A85", + "light_modern": "keyword.operator.expression: #0000FF" } }, { @@ -2815,7 +2815,7 @@ }, { "c": "int", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.int.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -2927,7 +2927,7 @@ }, { "c": "int", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.int.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", @@ -3025,16 +3025,16 @@ }, { "c": "new", - "t": "source.cs keyword.other.new.cs", + "t": "source.cs keyword.operator.expression.new.cs", "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6", - "dark_modern": "keyword: #569CD6", - "hc_light": "keyword: #0F4A85", - "light_modern": "keyword: #0000FF" + "dark_plus": "keyword.operator.expression: #569CD6", + "light_plus": "keyword.operator.expression: #0000FF", + "dark_vs": "keyword.operator.expression: #569CD6", + "light_vs": "keyword.operator.expression: #0000FF", + "hc_black": "keyword.operator.expression: #569CD6", + "dark_modern": "keyword.operator.expression: #569CD6", + "hc_light": "keyword.operator.expression: #0F4A85", + "light_modern": "keyword.operator.expression: #0000FF" } }, { @@ -3081,7 +3081,7 @@ }, { "c": "int", - "t": "source.cs keyword.type.cs", + "t": "source.cs keyword.type.int.cs", "r": { "dark_plus": "keyword: #569CD6", "light_plus": "keyword: #0000FF", diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_cshtml.json b/extensions/vscode-colorize-tests/test/colorize-results/test_cshtml.json index 5923b8411fe..4307f03ed1e 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_cshtml.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_cshtml.json @@ -43,16 +43,16 @@ }, { "c": "var", - "t": "text.html.cshtml meta.structure.razor.codeblock source.cs keyword.other.var.cs", + "t": "text.html.cshtml meta.structure.razor.codeblock source.cs storage.type.var.cs", "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6", - "dark_modern": "keyword: #569CD6", - "hc_light": "keyword: #0F4A85", - "light_modern": "keyword: #0000FF" + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6", + "dark_modern": "storage.type: #569CD6", + "hc_light": "storage.type: #0F4A85", + "light_modern": "storage.type: #0000FF" } }, { @@ -169,16 +169,16 @@ }, { "c": "var", - "t": "text.html.cshtml meta.structure.razor.codeblock source.cs keyword.other.var.cs", + "t": "text.html.cshtml meta.structure.razor.codeblock source.cs storage.type.var.cs", "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6", - "dark_modern": "keyword: #569CD6", - "hc_light": "keyword: #0F4A85", - "light_modern": "keyword: #0000FF" + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6", + "dark_modern": "storage.type: #569CD6", + "hc_light": "storage.type: #0F4A85", + "light_modern": "storage.type: #0000FF" } }, { @@ -505,16 +505,16 @@ }, { "c": " ", - "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock punctuation.whitespace.comment.leading.cs", + "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock comment.line.double-slash.cs punctuation.whitespace.comment.leading.cs", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF", - "dark_modern": "default: #CCCCCC", - "hc_light": "default: #292929", - "light_modern": "default: #3B3B3B" + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668", + "dark_modern": "comment: #6A9955", + "hc_light": "comment: #515151", + "light_modern": "comment: #008000" } }, { @@ -561,16 +561,16 @@ }, { "c": "var", - "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock keyword.other.var.cs", + "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock storage.type.var.cs", "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6", - "dark_modern": "keyword: #569CD6", - "hc_light": "keyword: #0F4A85", - "light_modern": "keyword: #0000FF" + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6", + "dark_modern": "storage.type: #569CD6", + "hc_light": "storage.type: #0F4A85", + "light_modern": "storage.type: #0000FF" } }, { @@ -757,16 +757,16 @@ }, { "c": "var", - "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock keyword.other.var.cs", + "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock storage.type.var.cs", "r": { - "dark_plus": "keyword: #569CD6", - "light_plus": "keyword: #0000FF", - "dark_vs": "keyword: #569CD6", - "light_vs": "keyword: #0000FF", - "hc_black": "keyword: #569CD6", - "dark_modern": "keyword: #569CD6", - "hc_light": "keyword: #0F4A85", - "light_modern": "keyword: #0000FF" + "dark_plus": "storage.type: #569CD6", + "light_plus": "storage.type: #0000FF", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6", + "dark_modern": "storage.type: #569CD6", + "hc_light": "storage.type: #0F4A85", + "light_modern": "storage.type: #0000FF" } }, { @@ -939,16 +939,16 @@ }, { "c": " ", - "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock punctuation.whitespace.comment.leading.cs", + "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock comment.line.double-slash.cs punctuation.whitespace.comment.leading.cs", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF", - "dark_modern": "default: #CCCCCC", - "hc_light": "default: #292929", - "light_modern": "default: #3B3B3B" + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668", + "dark_modern": "comment: #6A9955", + "hc_light": "comment: #515151", + "light_modern": "comment: #008000" } }, { @@ -4535,4 +4535,4 @@ "light_modern": "punctuation.definition.tag: #800000" } } -] +] \ No newline at end of file From c82bf84bf1287bd87013d1ed8538a8e48dc389ef Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 27 Oct 2023 20:01:14 +0200 Subject: [PATCH 159/162] fix #196846 (#196847) --- src/vs/workbench/browser/workbench.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index ee33ba1f914..8e1e052f18c 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -479,7 +479,7 @@ const registry = Registry.as(ConfigurationExtensions.Con 'type': 'string', 'enum': ['side', 'top', 'hidden'], 'default': 'side', - 'markdownDescription': localize({ comment: ['This is the description for a setting'], key: 'activityBarLocation' }, "Controls the location of the activity bar. It can either show to the `side` or `top` (requires `{0}`) of the primary side bar or `hidden`.", '#window.commandCenter#'), + 'markdownDescription': localize({ comment: ['This is the description for a setting'], key: 'activityBarLocation' }, "Controls the location of the activity bar. It can either show to the `side` or `top` (requires {0} set to {1}) of the primary side bar or `hidden`.", '`#window.titleBarStyle#`', '`custom`'), 'enumDescriptions': [ localize('workbench.activityBar.location.side', "Show the activity bar to the side of the primary side bar."), localize('workbench.activityBar.location.top', "Show the activity bar on top of the primary side bar."), From cc70dc611c0ca3c3c4b050e0e84ac20372c99d9d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Oct 2023 20:27:06 +0200 Subject: [PATCH 160/162] debt - remove debug logging for fullscreen window transitions (#196848) --- .../windows/electron-main/windowImpl.ts | 30 +++++-------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/src/vs/platform/windows/electron-main/windowImpl.ts b/src/vs/platform/windows/electron-main/windowImpl.ts index ea74e8a2811..3b87cdf6085 100644 --- a/src/vs/platform/windows/electron-main/windowImpl.ts +++ b/src/vs/platform/windows/electron-main/windowImpl.ts @@ -374,10 +374,7 @@ export class CodeWindow extends BaseWindow implements ICodeWindow { this._win.maximize(); if (this.windowState.mode === WindowMode.Fullscreen) { - this.logConditionally('WindowMode.Fullscreen'); this.setFullScreen(true); - } else { - this.logConditionally('WindowMode.Maximized'); } // to reduce flicker from the default window size @@ -405,13 +402,6 @@ export class CodeWindow extends BaseWindow implements ICodeWindow { this.registerListeners(); } - private logConditionally(msg: string): void { - // TODO@bpasero remove native fullscreen logging eventually - if (this.configurationService.getValue('window.logFullScreenTransitions')) { - this.logService.info(`window-fullscreen-bug: ${msg})`); - } - } - setRepresentedFilename(filename: string): void { if (isMacintosh) { this._win.setRepresentedFilename(filename); @@ -550,7 +540,6 @@ export class CodeWindow extends BaseWindow implements ICodeWindow { this._win.on('enter-full-screen', () => { this.sendWhenReady('vscode:enterFullScreen', CancellationToken.None); - this.logConditionally(`enter-full-screen: ${Date.now()}`); this.joinNativeFullScreenTransition?.complete(); this.joinNativeFullScreenTransition = undefined; }); @@ -558,7 +547,6 @@ export class CodeWindow extends BaseWindow implements ICodeWindow { this._win.on('leave-full-screen', () => { this.sendWhenReady('vscode:leaveFullScreen', CancellationToken.None); - this.logConditionally(`leave-full-screen: ${Date.now()}`); this.joinNativeFullScreenTransition?.complete(); this.joinNativeFullScreenTransition = undefined; }); @@ -1288,19 +1276,13 @@ export class CodeWindow extends BaseWindow implements ICodeWindow { } get isFullScreen(): boolean { - this.logConditionally(`isFullScreen(): begin at ${Date.now()}`); - if (isMacintosh && typeof this.transientIsNativeFullScreen === 'boolean') { - this.logConditionally(`isFullScreen(): returning transientIsNativeFullScreen = ${this.transientIsNativeFullScreen}`); - return this.transientIsNativeFullScreen; } const isFullScreen = this._win.isFullScreen(); const isSimpleFullScreen = this._win.isSimpleFullScreen(); - this.logConditionally(`isFullScreen(): returning natively, isFullScreen = ${isFullScreen}, isSimpleFullScreen = ${isSimpleFullScreen}`); - return isFullScreen || isSimpleFullScreen; } @@ -1314,16 +1296,18 @@ export class CodeWindow extends BaseWindow implements ICodeWindow { private doSetNativeFullScreen(fullscreen: boolean): void { if (isMacintosh) { - this.logConditionally(`doSetNativeFullScreen(${fullscreen}): begin at ${Date.now()}`); - this.transientIsNativeFullScreen = fullscreen; this.joinNativeFullScreenTransition = new DeferredPromise(); Promise.race([ this.joinNativeFullScreenTransition.p, - timeout(10000) // still timeout after some time in case the transition is unusually slow + // still timeout after some time in case the transition is unusually slow + // this can easily happen for an OS update where macOS tries to reopen + // previous applications and that can take multiple seconds, probably due + // to security checks. its worth noting that if this takes more than + // 10 seconds, users would see a window that is not-fullscreen but without + // custom titlebar... + timeout(10000) ]).finally(() => { - this.logConditionally(`doSetNativeFullScreen(${fullscreen}): finish at ${Date.now()}`); - this.transientIsNativeFullScreen = undefined; }); } From 519d45ed805e02180b4b96d7f5923809631612a3 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 27 Oct 2023 14:08:00 -0700 Subject: [PATCH 161/162] Don't show empty animated agent avatar when the agent doesn't have an icon Fix microsoft/vscode-copilot#2467 --- src/vs/workbench/contrib/chat/browser/chatListRenderer.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index c1811430075..82c067d6b1a 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -372,6 +372,9 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer Date: Sat, 28 Oct 2023 15:08:49 +0200 Subject: [PATCH 162/162] debt - merge EditResponse and MarkdownResponse into ReplyResponse (#196885) --- .../browser/inlineChatController.ts | 73 ++++++++----------- .../inlineChat/browser/inlineChatSession.ts | 29 ++++---- .../browser/inlineChatStrategies.ts | 22 +++--- .../inlineChat/browser/inlineChatWidget.ts | 5 +- 4 files changed, 60 insertions(+), 69 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 9f620df3117..ee45fe91669 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -24,7 +24,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; -import { EditResponse, EmptyResponse, ErrorResponse, ExpansionState, IInlineChatSessionService, MarkdownResponse, Session, SessionExchange, SessionPrompt } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; +import { ReplyResponse, EmptyResponse, ErrorResponse, ExpansionState, IInlineChatSessionService, Session, SessionExchange, SessionPrompt } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; import { EditModeStrategy, LivePreviewStrategy, LiveStrategy, PreviewStrategy, ProgressingEditsOptions } from 'vs/workbench/contrib/inlineChat/browser/inlineChatStrategies'; import { InlineChatZoneWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatWidget'; import { CTX_INLINE_CHAT_HAS_ACTIVE_REQUEST, CTX_INLINE_CHAT_LAST_FEEDBACK, IInlineChatRequest, IInlineChatResponse, INLINE_CHAT_ID, EditMode, InlineChatResponseFeedbackKind, CTX_INLINE_CHAT_LAST_RESPONSE_TYPE, InlineChatResponseType, CTX_INLINE_CHAT_DID_EDIT, CTX_INLINE_CHAT_HAS_STASHED_SESSION, InlineChateResponseTypes, CTX_INLINE_CHAT_RESPONSE_TYPES, CTX_INLINE_CHAT_USER_DID_EDIT, IInlineChatProgressItem } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; @@ -514,7 +514,7 @@ export class InlineChatController implements IEditorContribution { if (message & Message.RERUN_INPUT && this._activeSession.lastExchange) { const { lastExchange } = this._activeSession; this._activeSession.addInput(lastExchange.prompt.retry()); - if (lastExchange.response instanceof EditResponse) { + if (lastExchange.response instanceof ReplyResponse) { try { this._ignoreModelContentChanged = true; await this._strategy.undoChanges(lastExchange.response.modelAltVersionId); @@ -659,7 +659,7 @@ export class InlineChatController implements IEditorContribution { const task = this._activeSession.provider.provideResponse(this._activeSession.session, request, progress, requestCts.token); this._log('request started', this._activeSession.provider.debugName, this._activeSession.session, request); - let response: EditResponse | MarkdownResponse | ErrorResponse | EmptyResponse; + let response: ReplyResponse | ErrorResponse | EmptyResponse; let reply: IInlineChatResponse | null | undefined; try { this._zone.value.widget.updateProgress(true); @@ -673,22 +673,25 @@ export class InlineChatController implements IEditorContribution { } await progress.drain(); - if (reply?.type === InlineChatResponseType.Message) { - markdownContents.appendMarkdown(reply.message.value); - response = new MarkdownResponse(this._activeSession.textModelN.uri, reply, markdownContents); - a11yResponse = renderMarkdownAsPlaintext(markdownContents); - } else if (reply) { - const editResponse = new EditResponse(this._activeSession.textModelN.uri, modelAltVersionIdNow, reply, progressEdits); - for (let i = progressEdits.length; i < editResponse.allLocalEdits.length; i++) { - await this._makeChanges(editResponse.allLocalEdits[i], undefined); - } - response = editResponse; - a11yResponse = this._strategy.checkChanges(editResponse) && a11yVerboseInlineChat - ? localize('editResponseMessage', "Review proposed changes in the diff editor.") - : ''; - } else { + if (!reply) { response = new EmptyResponse(); a11yResponse = localize('empty', "No results, please refine your input and try again"); + } else { + + const replyResponse = response = new ReplyResponse(reply, markdownContents, this._activeSession.textModelN.uri, modelAltVersionIdNow, progressEdits); + if (reply.type === InlineChatResponseType.Message) { + markdownContents.appendMarkdown(reply.message.value); + } + + for (let i = progressEdits.length; i < replyResponse.allLocalEdits.length; i++) { + await this._makeChanges(replyResponse.allLocalEdits[i], undefined); + } + + const a11yMessageResponse = renderMarkdownAsPlaintext(replyResponse.mdContent); + + a11yResponse = this._strategy.checkChanges(replyResponse) && a11yVerboseInlineChat + ? a11yMessageResponse ? localize('editResponseMessage2', "{0}, also review proposed changes in the diff editor.", a11yMessageResponse) : localize('editResponseMessage', "Review proposed changes in the diff editor.") + : a11yMessageResponse; } } catch (e) { @@ -709,7 +712,7 @@ export class InlineChatController implements IEditorContribution { msgListener.dispose(); typeListener.dispose(); - if (request.live && !(response instanceof EditResponse)) { + if (request.live && !(response instanceof ReplyResponse)) { this._strategy?.undoChanges(modelAltVersionIdNow); } @@ -731,7 +734,7 @@ export class InlineChatController implements IEditorContribution { assertType(this._strategy); const { response } = this._activeSession.lastExchange!; - if (response instanceof EditResponse) { + if (response instanceof ReplyResponse) { // edit response -> complex... this._zone.value.widget.updateMarkdownMessage(undefined); @@ -778,16 +781,14 @@ export class InlineChatController implements IEditorContribution { const { response } = this._activeSession.lastExchange!; - this._ctxLastResponseType.set(response instanceof EditResponse || response instanceof MarkdownResponse - ? response.raw.type - : undefined); + this._ctxLastResponseType.set(response instanceof ReplyResponse ? response.raw.type : undefined); let responseTypes: InlineChateResponseTypes | undefined; for (const { response } of this._activeSession.exchanges) { - const thisType = response instanceof MarkdownResponse - ? InlineChateResponseTypes.OnlyMessages : response instanceof EditResponse - ? InlineChateResponseTypes.OnlyEdits : undefined; + const thisType = response instanceof ReplyResponse + ? response.responseType + : undefined; if (responseTypes === undefined) { responseTypes = thisType; @@ -811,17 +812,11 @@ export class InlineChatController implements IEditorContribution { this._zone.value.widget.updateStatus(response.message, { classes: ['error'] }); } - } else if (response instanceof MarkdownResponse) { - // clear status, show MD message - + } else if (response instanceof ReplyResponse) { + // real response -> complex... this._zone.value.widget.updateStatus(''); this._zone.value.widget.updateMarkdownMessage(response.mdContent); - this._zone.value.widget.updateToolbar(true); this._activeSession.lastExpansionState = this._zone.value.widget.expansionState; - - } else if (response instanceof EditResponse) { - // edit response -> complex... - this._zone.value.widget.updateMarkdownMessage(undefined); this._zone.value.widget.updateToolbar(true); const canContinue = this._strategy.checkChanges(response); @@ -899,10 +894,6 @@ export class InlineChatController implements IEditorContribution { } } - private static isEditOrMarkdownResponse(response: EditResponse | MarkdownResponse | EmptyResponse | ErrorResponse | undefined): response is EditResponse | MarkdownResponse { - return response instanceof EditResponse || response instanceof MarkdownResponse; - } - // ---- controller API acceptInput(): void { @@ -960,7 +951,7 @@ export class InlineChatController implements IEditorContribution { } viewInChat() { - if (this._activeSession?.lastExchange?.response instanceof MarkdownResponse) { + if (this._activeSession?.lastExchange?.response instanceof ReplyResponse) { this._instaService.invokeFunction(showMessageResponse, this._activeSession.lastExchange.prompt.value, this._activeSession.lastExchange.response.mdContent.value); } } @@ -974,7 +965,7 @@ export class InlineChatController implements IEditorContribution { } feedbackLast(helpful: boolean) { - if (this._activeSession?.lastExchange && InlineChatController.isEditOrMarkdownResponse(this._activeSession.lastExchange.response)) { + if (this._activeSession?.lastExchange && this._activeSession.lastExchange.response instanceof ReplyResponse) { const kind = helpful ? InlineChatResponseFeedbackKind.Helpful : InlineChatResponseFeedbackKind.Unhelpful; this._activeSession.provider.handleInlineChatResponseFeedback?.(this._activeSession.session, this._activeSession.lastExchange.response.raw, kind); this._ctxLastFeedbackKind.set(helpful ? 'helpful' : 'unhelpful'); @@ -989,7 +980,7 @@ export class InlineChatController implements IEditorContribution { } acceptSession(): void { - if (this._activeSession?.lastExchange && InlineChatController.isEditOrMarkdownResponse(this._activeSession.lastExchange.response)) { + if (this._activeSession?.lastExchange && this._activeSession.lastExchange.response instanceof ReplyResponse) { this._activeSession.provider.handleInlineChatResponseFeedback?.(this._activeSession.session, this._activeSession.lastExchange.response.raw, InlineChatResponseFeedbackKind.Accepted); } this._messages.fire(Message.ACCEPT_SESSION); @@ -1003,7 +994,7 @@ export class InlineChatController implements IEditorContribution { const diff = await this._editorWorkerService.computeDiff(this._activeSession.textModel0.uri, this._activeSession.textModelN.uri, { ignoreTrimWhitespace: false, maxComputationTimeMs: 5000, computeMoves: false }, 'advanced'); result = this._activeSession.asChangedText(diff?.changes ?? []); - if (this._activeSession.lastExchange && InlineChatController.isEditOrMarkdownResponse(this._activeSession.lastExchange.response)) { + if (this._activeSession.lastExchange && this._activeSession.lastExchange.response instanceof ReplyResponse) { this._activeSession.provider.handleInlineChatResponseFeedback?.(this._activeSession.session, this._activeSession.lastExchange.response.raw, InlineChatResponseFeedbackKind.Undone); } } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts index 891b3c02da2..98a1f36d345 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts @@ -9,7 +9,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { ResourceEdit, ResourceFileEdit, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService'; import { TextEdit } from 'vs/editor/common/languages'; import { IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model'; -import { EditMode, IInlineChatSessionProvider, IInlineChatSession, IInlineChatBulkEditResponse, IInlineChatEditResponse, IInlineChatMessageResponse, IInlineChatResponse, IInlineChatService } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; +import { EditMode, IInlineChatSessionProvider, IInlineChatSession, IInlineChatBulkEditResponse, IInlineChatEditResponse, IInlineChatMessageResponse, IInlineChatResponse, IInlineChatService, InlineChatResponseType, InlineChateResponseTypes } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; import { IRange, Range } from 'vs/editor/common/core/range'; import { IActiveCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -226,7 +226,7 @@ export class Session { }; for (const exchange of this._exchange) { const response = exchange.response; - if (response instanceof MarkdownResponse || response instanceof EditResponse) { + if (response instanceof ReplyResponse) { result.exchanges.push({ prompt: exchange.prompt.value, res: response.raw }); } } @@ -258,7 +258,7 @@ export class SessionExchange { constructor( readonly prompt: SessionPrompt, - readonly response: MarkdownResponse | EditResponse | EmptyResponse | ErrorResponse + readonly response: ReplyResponse | EmptyResponse | ErrorResponse ) { } } @@ -279,37 +279,32 @@ export class ErrorResponse { } } -export class MarkdownResponse { - constructor( - readonly localUri: URI, - readonly raw: IInlineChatMessageResponse, - readonly mdContent: IMarkdownString, - ) { } -} - -export class EditResponse { +export class ReplyResponse { readonly allLocalEdits: TextEdit[][] = []; readonly singleCreateFileEdit: { uri: URI; edits: Promise[] } | undefined; readonly workspaceEdits: ResourceEdit[] | undefined; readonly workspaceEditsIncludeLocalEdits: boolean = false; + readonly responseType: InlineChateResponseTypes; + constructor( + readonly raw: IInlineChatBulkEditResponse | IInlineChatEditResponse | IInlineChatMessageResponse, + readonly mdContent: IMarkdownString, localUri: URI, readonly modelAltVersionId: number, - readonly raw: IInlineChatBulkEditResponse | IInlineChatEditResponse, progressEdits: TextEdit[][], ) { this.allLocalEdits.push(...progressEdits); - if (raw.type === 'editorEdit') { + if (raw.type === InlineChatResponseType.EditorEdit) { // this.allLocalEdits.push(raw.edits); this.singleCreateFileEdit = undefined; this.workspaceEdits = undefined; - } else { + } else if (raw.type === InlineChatResponseType.BulkEdit) { // const edits = ResourceEdit.convert(raw.edits); this.workspaceEdits = edits; @@ -351,6 +346,10 @@ export class EditResponse { this.singleCreateFileEdit = undefined; } } + + this.responseType = (this.allLocalEdits.length || this.workspaceEdits) + ? mdContent.value ? InlineChateResponseTypes.Mixed : InlineChateResponseTypes.OnlyEdits + : InlineChateResponseTypes.OnlyMessages; } } diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts index 31359f738a2..41271d9c977 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts @@ -27,7 +27,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati import { IStorageService } from 'vs/platform/storage/common/storage'; import { countWords, getNWords } from 'vs/workbench/contrib/chat/common/chatWordCounter'; import { InlineChatFileCreatePreviewWidget, InlineChatLivePreviewWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatLivePreviewWidget'; -import { EditResponse, Session } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; +import { ReplyResponse, Session } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession'; import { InlineChatWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatWidget'; import { CTX_INLINE_CHAT_DOCUMENT_CHANGED } from 'vs/workbench/contrib/inlineChat/common/inlineChat'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; @@ -36,7 +36,7 @@ export abstract class EditModeStrategy { abstract dispose(): void; - abstract checkChanges(response: EditResponse): boolean; + abstract checkChanges(response: ReplyResponse): boolean; abstract apply(): Promise; @@ -48,7 +48,7 @@ export abstract class EditModeStrategy { abstract undoChanges(altVersionId: number): Promise; - abstract renderChanges(response: EditResponse): Promise; + abstract renderChanges(response: ReplyResponse): Promise; abstract hasFocus(): boolean; @@ -82,7 +82,7 @@ export class PreviewStrategy extends EditModeStrategy { this._ctxDocumentChanged.reset(); } - checkChanges(response: EditResponse): boolean { + checkChanges(response: ReplyResponse): boolean { if (!response.workspaceEdits || response.singleCreateFileEdit) { // preview stategy can handle simple workspace edit (single file create) return true; @@ -93,7 +93,7 @@ export class PreviewStrategy extends EditModeStrategy { async apply() { - if (!(this._session.lastExchange?.response instanceof EditResponse)) { + if (!(this._session.lastExchange?.response instanceof ReplyResponse)) { return; } const editResponse = this._session.lastExchange?.response; @@ -132,7 +132,7 @@ export class PreviewStrategy extends EditModeStrategy { // nothing to do } - override async renderChanges(response: EditResponse): Promise { + override async renderChanges(response: ReplyResponse): Promise { if (response.allLocalEdits.length > 0) { const allEditOperation = response.allLocalEdits.map(edits => edits.map(TextEdit.asEditOperation)); await this._widget.showEditsPreview(this._session.textModel0, this._session.textModelN, allEditOperation); @@ -235,7 +235,7 @@ export class LiveStrategy extends EditModeStrategy { private readonly _inlineDiffDecorations: InlineDiffDecorations; private readonly _store: DisposableStore = new DisposableStore(); - private _lastResponse?: EditResponse; + private _lastResponse?: ReplyResponse; private _editCount: number = 0; constructor( @@ -271,7 +271,7 @@ export class LiveStrategy extends EditModeStrategy { this._inlineDiffDecorations.visible = this._diffEnabled; } - checkChanges(response: EditResponse): boolean { + checkChanges(response: ReplyResponse): boolean { this._lastResponse = response; if (response.singleCreateFileEdit) { // preview stategy can handle simple workspace edit (single file create) @@ -341,7 +341,7 @@ export class LiveStrategy extends EditModeStrategy { } } - override async renderChanges(response: EditResponse) { + override async renderChanges(response: ReplyResponse) { const diff = await this._editorWorkerService.computeDiff(this._session.textModel0.uri, this._session.textModelN.uri, { ignoreTrimWhitespace: false, maxComputationTimeMs: 5000, computeMoves: false }, 'advanced'); this._updateSummaryMessage(diff?.changes ?? []); this._inlineDiffDecorations.update(); @@ -509,7 +509,7 @@ export class LivePreviewStrategy extends LiveStrategy { await this._updateDiffZones(); } - override async renderChanges(response: EditResponse) { + override async renderChanges(response: ReplyResponse) { await this._updateDiffZones(); @@ -525,7 +525,7 @@ export class LivePreviewStrategy extends LiveStrategy { } } -function showSingleCreateFile(accessor: ServicesAccessor, edit: EditResponse) { +function showSingleCreateFile(accessor: ServicesAccessor, edit: ReplyResponse) { const editorService = accessor.get(IEditorService); if (edit.singleCreateFileEdit) { editorService.openEditor({ resource: edit.singleCreateFileEdit.uri }, SIDE_GROUP); diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts index cc825b900db..e33a5ea2193 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts @@ -542,10 +542,11 @@ export class InlineChatWidget { updateMarkdownMessage(message: IMarkdownString | undefined) { this._codeBlockDisposables.clear(); - this._elements.markdownMessage.classList.toggle('hidden', !message); + const hasMessage = message?.value; + this._elements.markdownMessage.classList.toggle('hidden', !hasMessage); let expansionState: ExpansionState; let textContent: string | undefined = undefined; - if (!message) { + if (!hasMessage) { reset(this._elements.message); this._ctxMessageCropState.reset(); expansionState = ExpansionState.NOT_CROPPED;