From ba046e5ace45bbee175be8c7272d7f7d9aa024eb Mon Sep 17 00:00:00 2001 From: Xinyu Sui Date: Tue, 22 Feb 2022 14:06:15 -0800 Subject: [PATCH 001/175] Allow stack frame without source as top stack frame when using disassembly view --- src/vs/workbench/contrib/debug/common/debugModel.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index a6bc155cb17..f3d5bbc7dfc 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -475,7 +475,10 @@ export class Thread implements IThread { getTopStackFrame(): IStackFrame | undefined { const callStack = this.getCallStack(); - const firstAvailableStackFrame = callStack.find(sf => !!(sf && sf.source && sf.source.available && sf.source.presentationHint !== 'deemphasize')); + // Allow stack frame without source and with instructionReferencePointer as top stack frame when using disassembly view. + const firstAvailableStackFrame = callStack.find(sf => !!(sf && + ((this.stoppedDetails?.reason === 'instruction breakpoint' || (this.stoppedDetails?.reason === 'step' && this.lastSteppingGranularity === 'instruction')) && sf.instructionPointerReference) || + (sf.source && sf.source.available && sf.source.presentationHint !== 'deemphasize'))); return firstAvailableStackFrame || (callStack.length > 0 ? callStack[0] : undefined); } From d56a149b3ff6979f829198ef7e2c32286e4d3185 Mon Sep 17 00:00:00 2001 From: Xinyu Sui Date: Thu, 24 Feb 2022 14:38:18 -0800 Subject: [PATCH 002/175] Fix disabled breakpoint icon in disassembly view --- .../contrib/debug/browser/disassemblyView.ts | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/disassemblyView.ts b/src/vs/workbench/contrib/debug/browser/disassemblyView.ts index 7cf0d618cd4..f84295e851d 100644 --- a/src/vs/workbench/contrib/debug/browser/disassemblyView.ts +++ b/src/vs/workbench/contrib/debug/browser/disassemblyView.ts @@ -44,6 +44,7 @@ import { applyFontInfo } from 'vs/editor/browser/config/domFontInfo'; interface IDisassembledInstructionEntry { allowBreakpoint: boolean; isBreakpointSet: boolean; + isBreakpointEnaled: boolean; instruction: DebugProtocol.DisassembledInstruction; instructionAddress?: bigint; } @@ -52,6 +53,7 @@ interface IDisassembledInstructionEntry { const disassemblyNotAvailable: IDisassembledInstructionEntry = { allowBreakpoint: false, isBreakpointSet: false, + isBreakpointEnaled: false, instruction: { address: '-1', instruction: localize('instructionNotAvailable', "Disassembly not available.") @@ -232,6 +234,7 @@ export class DisassemblyView extends EditorPane { const index = this.getIndexFromAddress(bp.instructionReference); if (index >= 0) { this._disassembledInstructions!.row(index).isBreakpointSet = true; + this._disassembledInstructions!.row(index).isBreakpointEnaled = bp.enabled; changed = true; } } @@ -247,6 +250,18 @@ export class DisassemblyView extends EditorPane { } }); + bpEvent.changed?.forEach((bp) => { + if (bp instanceof InstructionBreakpoint) { + const index = this.getIndexFromAddress(bp.instructionReference); + if (index >= 0) { + if (this._disassembledInstructions!.row(index).isBreakpointEnaled !== bp.enabled) { + this._disassembledInstructions!.row(index).isBreakpointEnaled = bp.enabled; + changed = true; + } + } + } + }); + // get an updated list so that items beyond the current range would render when reached. this._instructionBpList = this._debugService.getModel().getInstructionBreakpoints(); @@ -363,7 +378,7 @@ export class DisassemblyView extends EditorPane { } } - newEntries.push({ allowBreakpoint: true, isBreakpointSet: found !== undefined, instruction: instruction }); + newEntries.push({ allowBreakpoint: true, isBreakpointSet: found !== undefined, isBreakpointEnaled: !!found?.enabled, instruction: instruction }); } const specialEntriesToRemove = this._disassembledInstructions.length === 1 ? 1 : 0; @@ -467,6 +482,7 @@ class BreakpointRenderer implements ITableRenderer Date: Thu, 24 Feb 2022 15:49:06 -0800 Subject: [PATCH 003/175] Fix typo --- .../contrib/debug/browser/disassemblyView.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/disassemblyView.ts b/src/vs/workbench/contrib/debug/browser/disassemblyView.ts index f84295e851d..552a4f070c4 100644 --- a/src/vs/workbench/contrib/debug/browser/disassemblyView.ts +++ b/src/vs/workbench/contrib/debug/browser/disassemblyView.ts @@ -44,7 +44,7 @@ import { applyFontInfo } from 'vs/editor/browser/config/domFontInfo'; interface IDisassembledInstructionEntry { allowBreakpoint: boolean; isBreakpointSet: boolean; - isBreakpointEnaled: boolean; + isBreakpointEnabled: boolean; instruction: DebugProtocol.DisassembledInstruction; instructionAddress?: bigint; } @@ -53,7 +53,7 @@ interface IDisassembledInstructionEntry { const disassemblyNotAvailable: IDisassembledInstructionEntry = { allowBreakpoint: false, isBreakpointSet: false, - isBreakpointEnaled: false, + isBreakpointEnabled: false, instruction: { address: '-1', instruction: localize('instructionNotAvailable', "Disassembly not available.") @@ -234,7 +234,7 @@ export class DisassemblyView extends EditorPane { const index = this.getIndexFromAddress(bp.instructionReference); if (index >= 0) { this._disassembledInstructions!.row(index).isBreakpointSet = true; - this._disassembledInstructions!.row(index).isBreakpointEnaled = bp.enabled; + this._disassembledInstructions!.row(index).isBreakpointEnabled = bp.enabled; changed = true; } } @@ -254,8 +254,8 @@ export class DisassemblyView extends EditorPane { if (bp instanceof InstructionBreakpoint) { const index = this.getIndexFromAddress(bp.instructionReference); if (index >= 0) { - if (this._disassembledInstructions!.row(index).isBreakpointEnaled !== bp.enabled) { - this._disassembledInstructions!.row(index).isBreakpointEnaled = bp.enabled; + if (this._disassembledInstructions!.row(index).isBreakpointEnabled !== bp.enabled) { + this._disassembledInstructions!.row(index).isBreakpointEnabled = bp.enabled; changed = true; } } @@ -378,7 +378,7 @@ export class DisassemblyView extends EditorPane { } } - newEntries.push({ allowBreakpoint: true, isBreakpointSet: found !== undefined, isBreakpointEnaled: !!found?.enabled, instruction: instruction }); + newEntries.push({ allowBreakpoint: true, isBreakpointSet: found !== undefined, isBreakpointEnabled: !!found?.enabled, instruction: instruction }); } const specialEntriesToRemove = this._disassembledInstructions.length === 1 ? 1 : 0; @@ -558,7 +558,7 @@ class BreakpointRenderer implements ITableRenderer Date: Mon, 28 Feb 2022 02:51:38 +0900 Subject: [PATCH 004/175] chore: hasfocus -> hasFocus --- .../workbench/contrib/debug/browser/debugEditorContribution.ts | 2 +- src/vs/workbench/contrib/debug/browser/exceptionWidget.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts index 42d88028864..49f89c54f46 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts @@ -506,7 +506,7 @@ export class DebugEditorContribution implements IDebugEditorContribution { closeExceptionWidget(): void { if (this.exceptionWidget) { - const shouldFocusEditor = this.exceptionWidget.hasfocus(); + const shouldFocusEditor = this.exceptionWidget.hasFocus(); this.exceptionWidget.dispose(); this.exceptionWidget = undefined; this.exceptionWidgetVisible.set(false); diff --git a/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts b/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts index 34d3b84ec38..ad2b8e97293 100644 --- a/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts +++ b/src/vs/workbench/contrib/debug/browser/exceptionWidget.ts @@ -121,7 +121,7 @@ export class ExceptionWidget extends ZoneWidget { this.container?.focus(); } - hasfocus(): boolean { + hasFocus(): boolean { return dom.isAncestor(document.activeElement, this.container); } } From a4496484e458d38a03ee15e9eeda7603a0fe3724 Mon Sep 17 00:00:00 2001 From: jeanp413 Date: Sun, 6 Mar 2022 15:53:58 -0500 Subject: [PATCH 005/175] Fixes #144527 --- .../extensions/browser/abstractRuntimeExtensionsEditor.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts index fb40855a43f..c72727c939e 100644 --- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts @@ -370,15 +370,15 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { } let extraLabel: string | null = null; - if (element.description.extensionLocation.scheme === Schemas.vscodeRemote) { + if (element.status.runningLocation === ExtensionRunningLocation.LocalWebWorker) { + extraLabel = `$(globe) web worker`; + } else if (element.description.extensionLocation.scheme === Schemas.vscodeRemote) { const hostLabel = this._labelService.getHostLabel(Schemas.vscodeRemote, this._environmentService.remoteAuthority); if (hostLabel) { extraLabel = `$(remote) ${hostLabel}`; } else { extraLabel = `$(remote) ${element.description.extensionLocation.authority}`; } - } else if (element.status.runningLocation === ExtensionRunningLocation.LocalWebWorker) { - extraLabel = `$(globe) web worker`; } if (extraLabel) { From 103536401b0559a7dfe6f5384351dcf0af59257d Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 7 Mar 2022 12:19:25 -0800 Subject: [PATCH 006/175] Support shell type context key on mac/linux Fixes #144619 --- src/vs/platform/terminal/common/terminal.ts | 12 ++++++++++- .../platform/terminal/node/terminalProcess.ts | 20 +++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 8c90aa61c62..3ff4e70ca4c 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -111,13 +111,23 @@ export const enum TerminalSettingId { ShellIntegrationCommandHistory = 'terminal.integrated.shellIntegration.history' } +export const enum PosixShellType { + PowerShell = 'pwsh', + Bash = 'bash', + Fish = 'fish', + Sh = 'sh', + Csh = 'csh', + Ksh = 'ksh', + Zsh = 'zsh', +} export const enum WindowsShellType { CommandPrompt = 'cmd', PowerShell = 'pwsh', Wsl = 'wsl', GitBash = 'gitbash' } -export type TerminalShellType = WindowsShellType | undefined; +export type TerminalShellType = PosixShellType | WindowsShellType | undefined; + export interface IRawTerminalInstanceLayoutInfo { relativeSize: number; terminal: T; diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts index 2a1dfd1823f..1c89b047438 100644 --- a/src/vs/platform/terminal/node/terminalProcess.ts +++ b/src/vs/platform/terminal/node/terminalProcess.ts @@ -17,7 +17,7 @@ import { URI } from 'vs/base/common/uri'; import { Promises } from 'vs/base/node/pfs'; import { localize } from 'vs/nls'; import { ILogService } from 'vs/platform/log/common/log'; -import { FlowControlConstants, IShellLaunchConfig, ITerminalChildProcess, ITerminalLaunchError, IProcessProperty, IProcessPropertyMap as IProcessPropertyMap, ProcessPropertyType, TerminalShellType, IProcessReadyEvent, ITerminalProcessOptions } from 'vs/platform/terminal/common/terminal'; +import { FlowControlConstants, IShellLaunchConfig, ITerminalChildProcess, ITerminalLaunchError, IProcessProperty, IProcessPropertyMap as IProcessPropertyMap, ProcessPropertyType, TerminalShellType, IProcessReadyEvent, ITerminalProcessOptions, PosixShellType } from 'vs/platform/terminal/common/terminal'; import { ChildProcessMonitor } from 'vs/platform/terminal/node/childProcessMonitor'; import { findExecutable, getShellIntegrationInjection, getWindowsBuildNumber, IShellIntegrationConfigInjection } from 'vs/platform/terminal/node/terminalEnvironment'; import { WindowsShellHelper } from 'vs/platform/terminal/node/windowsShellHelper'; @@ -75,6 +75,16 @@ interface IWriteObject { isBinary: boolean; } +const posixShellTypeMap = new Map([ + ['bash', PosixShellType.Bash], + ['csh', PosixShellType.Csh], + ['fish', PosixShellType.Fish], + ['ksh', PosixShellType.Ksh], + ['sh', PosixShellType.Sh], + ['pwsh', PosixShellType.PowerShell], + ['zsh', PosixShellType.Zsh] +]); + export class TerminalProcess extends Disposable implements ITerminalChildProcess { readonly id = 0; readonly shouldPersist = false; @@ -111,7 +121,12 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess get exitMessage(): string | undefined { return this._exitMessage; } get currentTitle(): string { return this._windowsShellHelper?.shellTitle || this._currentTitle; } - get shellType(): TerminalShellType { return this._windowsShellHelper ? this._windowsShellHelper.shellType : undefined; } + get shellType(): TerminalShellType { + if (isWindows) { + return this._windowsShellHelper?.shellType; + } + return posixShellTypeMap.get(this._currentTitle); + } private readonly _onProcessData = this._register(new Emitter()); readonly onProcessData = this._onProcessData.event; @@ -389,6 +404,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } this._currentTitle = ptyProcess.process; this._onDidChangeProperty.fire({ type: ProcessPropertyType.Title, value: this._currentTitle }); + this._onDidChangeProperty.fire({ type: ProcessPropertyType.ShellType, value: posixShellTypeMap.get(this.currentTitle) }); } shutdown(immediate: boolean): void { From 1a9016d0a4aa0eb98fd6dce3baf1678a3ccc35b9 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Mar 2022 11:20:24 +0100 Subject: [PATCH 007/175] add failing/skipped test for https://github.com/microsoft/vscode/issues/144664 --- .../test/browser/extHostEditorTabs.test.ts | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts b/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts index 6be6712566c..ed27b7b6dec 100644 --- a/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts +++ b/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts @@ -211,4 +211,59 @@ suite('ExtHostEditorTabs', function () { assert.strictEqual(activeTabGroup, undefined); assert.strictEqual(activeTabGroup, activeTabGroupFromEvent); }); + + test.skip('Ensure reference stability', function () { + + const extHostEditorTabs = new ExtHostEditorTabs( + SingleProxyRPCProtocol(new class extends mock() { + // override/implement $moveTab or $closeTab + }) + ); + const tabDto: IEditorTabDto = { + isActive: true, + isDirty: true, + isPinned: true, + label: 'label1', + resource: URI.parse('file://abc/def.txt'), + editorId: 'default', + viewColumn: 0, + additionalResourcesAndViewTypes: [], + kind: TabKind.Singular + }; + + // single dirty tab + + extHostEditorTabs.$acceptEditorTabModel([{ + isActive: true, + viewColumn: 0, + groupId: 12, + tabs: [tabDto], + activeTab: undefined // NOT needed + }]); + let all = extHostEditorTabs.tabGroups.all.map(group => group.tabs).flat(); + assert.strictEqual(all.length, 1); + const apiTab1 = all[0]; + assert.strictEqual(apiTab1.resource?.toString(), URI.revive(tabDto.resource)?.toString()); + assert.strictEqual(apiTab1.isDirty, true); + + + // NOT DIRTY anymore + + const tabDto2: IEditorTabDto = { ...tabDto, isDirty: false }; + extHostEditorTabs.$acceptEditorTabModel([{ + isActive: true, + viewColumn: 0, + groupId: 12, + tabs: [tabDto2], + activeTab: undefined // NOT needed + }]); + + all = extHostEditorTabs.tabGroups.all.map(group => group.tabs).flat(); + assert.strictEqual(all.length, 1); + const apiTab2 = all[0]; + assert.strictEqual(apiTab2.resource?.toString(), URI.revive(tabDto.resource)?.toString()); + assert.strictEqual(apiTab2.isDirty, false); + + assert.strictEqual(apiTab1 === apiTab2, true); + }); }); From a4e406e5bc6ae3402db160b5c2ed5ac07e0e503f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 8 Mar 2022 12:29:00 +0100 Subject: [PATCH 008/175] `native-keymap@3.3.0` --- package.json | 4 ++-- yarn.lock | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index a0ec41c5583..421ff9f3dec 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "keytar": "7.6.0", "minimist": "^1.2.5", "native-is-elevated": "0.4.3", - "native-keymap": "3.2.1", + "native-keymap": "3.3.0", "native-watchdog": "1.3.0", "node-pty": "0.11.0-beta11", "spdlog": "^0.13.0", @@ -232,4 +232,4 @@ "elliptic": "^6.5.3", "nwmatcher": "^1.4.4" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 2c500d4ca97..a9e35e612d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8196,10 +8196,10 @@ native-is-elevated@0.4.3: resolved "https://registry.yarnpkg.com/native-is-elevated/-/native-is-elevated-0.4.3.tgz#f1071c4a821acc71d43f36ff8051d3816d832e1c" integrity sha512-bHS3sCoh+raqFGIxmL/plER3eBQ+IEBy4RH/4uahhToZneTvqNKQrL0PgOTtnpL55XjBd3dy0pNtZMkCk0J48g== -native-keymap@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/native-keymap/-/native-keymap-3.2.1.tgz#2b34ee7e08722f107baba9beae7e61ea43eceae7" - integrity sha512-kR8r1Ody16qNE52fenuCMQBHtFpIV7HNVjQA7dm/pXpFcQmqCl8jWQuJYdZvNH7fQmyAv3lOgPfR3FDHPRYiiA== +native-keymap@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/native-keymap/-/native-keymap-3.3.0.tgz#927ca6afcf4ebd986b5dc1bddfab4270e750915d" + integrity sha512-nvhI1Cdr+ywhpqqGdM+JM8EjMYA1s6SW8EqhWNKtffHU07JcTKDhd8N3o0TLSFn8y2YuRFoOwfAIzdTU6TVhDA== native-watchdog@1.3.0: version "1.3.0" From 8e6177fc9cd317b90c6296acddb2b0b180ceaabd Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 8 Mar 2022 12:33:47 +0100 Subject: [PATCH 009/175] `native-watchdog@1.4.0` --- package.json | 4 ++-- yarn.lock | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index a0ec41c5583..4f74d1e2bf8 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "minimist": "^1.2.5", "native-is-elevated": "0.4.3", "native-keymap": "3.2.1", - "native-watchdog": "1.3.0", + "native-watchdog": "1.4.0", "node-pty": "0.11.0-beta11", "spdlog": "^0.13.0", "tas-client-umd": "0.1.4", @@ -232,4 +232,4 @@ "elliptic": "^6.5.3", "nwmatcher": "^1.4.4" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 2c500d4ca97..0815ab4f67a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8201,10 +8201,10 @@ native-keymap@3.2.1: resolved "https://registry.yarnpkg.com/native-keymap/-/native-keymap-3.2.1.tgz#2b34ee7e08722f107baba9beae7e61ea43eceae7" integrity sha512-kR8r1Ody16qNE52fenuCMQBHtFpIV7HNVjQA7dm/pXpFcQmqCl8jWQuJYdZvNH7fQmyAv3lOgPfR3FDHPRYiiA== -native-watchdog@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.3.0.tgz#88cee94c9dc766b85c8506eda14c8bd8c9618e27" - integrity sha512-WOjGRNGkYZ5MXsntcvCYrKtSYMaewlbCFplbcUVo9bE80LPVt8TAVFHYWB8+a6fWCGYheq21+Wtt6CJrUaCJhw== +native-watchdog@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.4.0.tgz#547a1f9f88754c38089c622d405ed1e324c7a545" + integrity sha512-4FynAeGtTpoQ2+5AxVJXGEGsOzPsNYDh8Xmawjgs7YWJe+bbbgt7CYlA/Qx6X+kwtN5Ey1aNSm9MqZa0iNKkGw== natural-compare@^1.4.0: version "1.4.0" From 4249087e680911df8bb5112edbd2052983120983 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 8 Mar 2022 12:54:37 +0100 Subject: [PATCH 010/175] Update `native-watchdog` also in the `remote` folder --- remote/package.json | 2 +- remote/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/remote/package.json b/remote/package.json index 47878146a32..7339e21ada2 100644 --- a/remote/package.json +++ b/remote/package.json @@ -16,7 +16,7 @@ "jschardet": "3.0.0", "keytar": "7.6.0", "minimist": "^1.2.5", - "native-watchdog": "1.3.0", + "native-watchdog": "1.4.0", "node-pty": "0.11.0-beta11", "spdlog": "^0.13.0", "tas-client-umd": "0.1.4", diff --git a/remote/yarn.lock b/remote/yarn.lock index 7fa9e60d8f0..cb3a9fb85a1 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -544,10 +544,10 @@ napi-build-utils@^1.0.1: resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== -native-watchdog@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.3.0.tgz#88cee94c9dc766b85c8506eda14c8bd8c9618e27" - integrity sha512-WOjGRNGkYZ5MXsntcvCYrKtSYMaewlbCFplbcUVo9bE80LPVt8TAVFHYWB8+a6fWCGYheq21+Wtt6CJrUaCJhw== +native-watchdog@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.4.0.tgz#547a1f9f88754c38089c622d405ed1e324c7a545" + integrity sha512-4FynAeGtTpoQ2+5AxVJXGEGsOzPsNYDh8Xmawjgs7YWJe+bbbgt7CYlA/Qx6X+kwtN5Ey1aNSm9MqZa0iNKkGw== node-abi@^2.21.0: version "2.30.1" From 52faf21ef240c71cd72368bcdc318ac770175168 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Mar 2022 14:15:35 +0100 Subject: [PATCH 011/175] move/copy `onDidSaveNotebookDocument`-event into workspace, add `onDidChangeNotebookDocument`-event which fires for any notebook change: metadata, structure, cell output, cell metadata --- .../browser/mainThreadNotebookDocuments.ts | 6 +- .../workbench/api/common/extHost.api.impl.ts | 8 ++ .../workbench/api/common/extHost.protocol.ts | 2 +- .../api/common/extHostNotebookDocument.ts | 75 +++++++++++++++++-- .../api/common/extHostNotebookDocuments.ts | 12 ++- .../common/extensionsApiProposals.ts | 1 + ...scode.proposed.notebookDocumentEvents.d.ts | 55 ++++++++++++++ 7 files changed, 145 insertions(+), 14 deletions(-) create mode 100644 src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts diff --git a/src/vs/workbench/api/browser/mainThreadNotebookDocuments.ts b/src/vs/workbench/api/browser/mainThreadNotebookDocuments.ts index 693ab628076..c586ceacf35 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebookDocuments.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebookDocuments.ts @@ -97,16 +97,18 @@ export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsS } } + const hasDocumentMetadataChangeEvent = event.rawEvents.find(e => e.kind === NotebookCellsChangeType.ChangeDocumentMetadata); + // using the model resolver service to know if the model is dirty or not. // assuming this is the first listener it can mean that at first the model // is marked as dirty and that another event is fired this._proxy.$acceptModelChanged( textModel.uri, new SerializableObjectWithBuffers(eventDto), - this._notebookEditorModelResolverService.isDirty(textModel.uri) + this._notebookEditorModelResolverService.isDirty(textModel.uri), + hasDocumentMetadataChangeEvent ? textModel.metadata : undefined ); - const hasDocumentMetadataChangeEvent = event.rawEvents.find(e => e.kind === NotebookCellsChangeType.ChangeDocumentMetadata); if (hasDocumentMetadataChangeEvent) { this._proxy.$acceptDocumentPropertiesChanged(textModel.uri, { metadata: textModel.metadata }); } diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 36adbdf73ac..370b8d0478e 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -882,6 +882,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I } return extHostNotebook.getNotebookDocument(uri).apiNotebook; }, + onDidSaveNotebookDocument(listener, thisArg, disposables) { + checkProposedApiEnabled(extension, 'notebookDocumentEvents'); + return extHostNotebookDocuments.onDidSaveNotebookDocument(listener, thisArg, disposables); + }, + onDidChangeNotebookDocument(listener, thisArg, disposables) { + checkProposedApiEnabled(extension, 'notebookDocumentEvents'); + return extHostNotebookDocuments.onDidChangeNotebookDocument(listener, thisArg, disposables); + }, get onDidOpenNotebookDocument(): Event { return extHostNotebook.onDidOpenNotebookDocument; }, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 0081e8aec8b..64f9f7de22a 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -2005,7 +2005,7 @@ export type NotebookCellsChangedEventDto = { }; export interface ExtHostNotebookDocumentsShape { - $acceptModelChanged(uriComponents: UriComponents, event: SerializableObjectWithBuffers, isDirty: boolean): void; + $acceptModelChanged(uriComponents: UriComponents, event: SerializableObjectWithBuffers, isDirty: boolean, newMetadata?: notebookCommon.NotebookDocumentMetadata): void; $acceptDirtyStateChanged(uriComponents: UriComponents, isDirty: boolean): void; $acceptModelSaved(uriComponents: UriComponents): void; $acceptDocumentPropertiesChanged(uriComponents: UriComponents, data: INotebookDocumentPropertiesChangeData): void; diff --git a/src/vs/workbench/api/common/extHostNotebookDocument.ts b/src/vs/workbench/api/common/extHostNotebookDocument.ts index 055a0b7424b..7462e349dfe 100644 --- a/src/vs/workbench/api/common/extHostNotebookDocument.ts +++ b/src/vs/workbench/api/common/extHostNotebookDocument.ts @@ -10,12 +10,25 @@ import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol'; import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; import { ExtHostDocumentsAndEditors, IExtHostModelAddedData } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters'; +import { NotebookRange } from 'vs/workbench/api/common/extHostTypes'; import * as notebookCommon from 'vs/workbench/contrib/notebook/common/notebookCommon'; import * as vscode from 'vscode'; class RawContentChangeEvent { - constructor(readonly start: number, readonly deletedCount: number, readonly deletedItems: vscode.NotebookCell[], readonly items: ExtHostCell[]) { } + + constructor(readonly start: number, readonly deletedCount: number, readonly deletedItems: vscode.NotebookCell[], readonly items: ExtHostCell[]) { + + } + + asApiEvent(): vscode.NotebookDocumentContentChange { + return { + range: new NotebookRange(this.start, this.start + this.deletedCount), + addedCells: this.items.map(cell => cell.apiCell), + removedCells: this.deletedItems, + }; + } + static asApiEvents(events: RawContentChangeEvent[]): readonly vscode.NotebookCellsChangeData[] { return events.map(event => { @@ -157,7 +170,7 @@ export class ExtHostNotebookDocument { ) { this._notebookType = data.viewType; this._metadata = Object.freeze(data.metadata ?? Object.create(null)); - this._spliceNotebookCells([[0, 0, data.cells]], true /* init -> no event*/); + this._spliceNotebookCells([[0, 0, data.cells]], true /* init -> no event*/, undefined); this._versionId = data.versionId; } @@ -213,29 +226,67 @@ export class ExtHostNotebookDocument { this._isDirty = isDirty; } - acceptModelChanged(event: extHostProtocol.NotebookCellsChangedEventDto, isDirty: boolean): void { + acceptModelChanged(event: extHostProtocol.NotebookCellsChangedEventDto, isDirty: boolean, newMetadata: notebookCommon.NotebookDocumentMetadata | undefined): vscode.NotebookDocumentChangeEvent { this._versionId = event.versionId; this._isDirty = isDirty; + this.acceptDocumentPropertiesChanged({ metadata: newMetadata }); + + + const result = { + notebook: this.apiNotebook, + metadata: newMetadata, + cellChanges: [], + contentChanges: [], + }; + const cellOutputChanges = new Set(); + const cellMetadataChanges = new Set(); + + // -- apply change and populate content changes for (const rawEvent of event.rawEvents) { if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ModelChange) { - this._spliceNotebookCells(rawEvent.changes, false); + this._spliceNotebookCells(rawEvent.changes, false, result.contentChanges); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.Move) { - this._moveCell(rawEvent.index, rawEvent.newIdx); + this._moveCell(rawEvent.index, rawEvent.newIdx, result.contentChanges); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.Output) { this._setCellOutputs(rawEvent.index, rawEvent.outputs); + cellOutputChanges.add(this._cells[rawEvent.index]); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.OutputItem) { this._setCellOutputItems(rawEvent.index, rawEvent.outputId, rawEvent.append, rawEvent.outputItems); + cellOutputChanges.add(this._cells[rawEvent.index]); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeLanguage) { this._changeCellLanguage(rawEvent.index, rawEvent.language); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMime) { this._changeCellMime(rawEvent.index, rawEvent.mime); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMetadata) { this._changeCellMetadata(rawEvent.index, rawEvent.metadata); + cellMetadataChanges.add(this._cells[rawEvent.index]); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellInternalMetadata) { this._changeCellInternalMetadata(rawEvent.index, rawEvent.internalMetadata); } } + + // -- populate cell changes + + for (const cell of cellOutputChanges) { + result.cellChanges.push({ + cell: cell.apiCell, + outputs: cell.apiCell.outputs, + metadata: cellMetadataChanges.has(cell) ? cell.apiCell.metadata : undefined, + executionSummary: undefined + }); + cellMetadataChanges.delete(cell); + } + for (const cell of cellMetadataChanges) { + result.cellChanges.push({ + cell: cell.apiCell, + metadata: cell.apiCell.metadata, + outputs: undefined, + executionSummary: undefined + }); + } + + return result; } private _validateIndex(index: number): number { @@ -277,7 +328,7 @@ export class ExtHostNotebookDocument { return this._proxy.$trySaveNotebook(this.uri); } - private _spliceNotebookCells(splices: notebookCommon.NotebookCellTextModelSplice[], initialization: boolean): void { + private _spliceNotebookCells(splices: notebookCommon.NotebookCellTextModelSplice[], initialization: boolean, bucket: vscode.NotebookDocumentContentChange[] | undefined): void { if (this._disposed) { return; } @@ -303,7 +354,6 @@ export class ExtHostNotebookDocument { removedCellDocuments.push(cell.uri); changeEvent.deletedItems.push(cell.apiCell); } - contentChangeEvents.push(changeEvent); }); @@ -312,6 +362,12 @@ export class ExtHostNotebookDocument { removedDocuments: removedCellDocuments }); + if (bucket) { + for (let changeEvent of contentChangeEvents) { + bucket.push(changeEvent.asApiEvent()); + } + } + if (!initialization) { this._emitter.emitModelChange(deepFreeze({ document: this.apiNotebook, @@ -320,13 +376,16 @@ export class ExtHostNotebookDocument { } } - private _moveCell(index: number, newIdx: number): void { + private _moveCell(index: number, newIdx: number, bucket: vscode.NotebookDocumentContentChange[]): void { const cells = this._cells.splice(index, 1); this._cells.splice(newIdx, 0, ...cells); const changes = [ new RawContentChangeEvent(index, 1, cells.map(c => c.apiCell), []), new RawContentChangeEvent(newIdx, 0, [], cells) ]; + for (const change of changes) { + bucket.push(change.asApiEvent()); + } this._emitter.emitModelChange(deepFreeze({ document: this.apiNotebook, changes: RawContentChangeEvent.asApiEvents(changes) diff --git a/src/vs/workbench/api/common/extHostNotebookDocuments.ts b/src/vs/workbench/api/common/extHostNotebookDocuments.ts index 70db04b1181..50995c9f93f 100644 --- a/src/vs/workbench/api/common/extHostNotebookDocuments.ts +++ b/src/vs/workbench/api/common/extHostNotebookDocuments.ts @@ -4,10 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter } from 'vs/base/common/event'; +import { deepFreeze } from 'vs/base/common/objects'; import { URI, UriComponents } from 'vs/base/common/uri'; import { ILogService } from 'vs/platform/log/common/log'; import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol'; import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook'; +import { NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier'; import type * as vscode from 'vscode'; @@ -16,17 +18,21 @@ export class ExtHostNotebookDocuments implements extHostProtocol.ExtHostNotebook private readonly _onDidChangeNotebookDocumentMetadata = new Emitter(); readonly onDidChangeNotebookDocumentMetadata = this._onDidChangeNotebookDocumentMetadata.event; - private _onDidSaveNotebookDocument = new Emitter(); + private readonly _onDidSaveNotebookDocument = new Emitter(); readonly onDidSaveNotebookDocument = this._onDidSaveNotebookDocument.event; + private readonly _onDidChangeNotebookDocument = new Emitter(); + readonly onDidChangeNotebookDocument = this._onDidChangeNotebookDocument.event; + constructor( @ILogService private readonly _logService: ILogService, private readonly _notebooksAndEditors: ExtHostNotebookController, ) { } - $acceptModelChanged(uri: UriComponents, event: SerializableObjectWithBuffers, isDirty: boolean): void { + $acceptModelChanged(uri: UriComponents, event: SerializableObjectWithBuffers, isDirty: boolean, newMetadata?: NotebookDocumentMetadata): void { const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri)); - document.acceptModelChanged(event.value, isDirty); + const e = document.acceptModelChanged(event.value, isDirty, newMetadata); + this._onDidChangeNotebookDocument.fire(deepFreeze(e)); } $acceptDirtyStateChanged(uri: UriComponents, isDirty: boolean): void { diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index 6267489b52d..0134a9a014d 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -31,6 +31,7 @@ export const allApiProposals = Object.freeze({ notebookControllerKind: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookControllerKind.d.ts', notebookDebugOptions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookDebugOptions.d.ts', notebookDeprecated: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookDeprecated.d.ts', + notebookDocumentEvents: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts', notebookDocumentSelector: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookDocumentSelector.d.ts', notebookEditor: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookEditor.d.ts', notebookEditorDecorationType: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookEditorDecorationType.d.ts', diff --git a/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts b/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts new file mode 100644 index 00000000000..5eb564f12d8 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts @@ -0,0 +1,55 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + export interface NotebookDocumentContentCellChange { + + /** + * The affected notebook. + */ + readonly cell: NotebookCell; + + readonly metadata: { [key: string]: any } | undefined; + readonly outputs: readonly NotebookCellOutput[] | undefined; + readonly executionSummary: readonly NotebookCellExecutionSummary[] | undefined; + } + + export interface NotebookDocumentContentChange { + readonly range: NotebookRange; + readonly addedCells: NotebookCell[]; + readonly removedCells: NotebookCell[]; + } + + export interface NotebookDocumentChangeEvent { + + /** + * The affected notebook. + */ + readonly notebook: NotebookDocument; + + /** + * The notebook metadata when it has changed or `undefined` when it has not changed. + */ + readonly metadata: { [key: string]: any } | undefined; + + readonly contentChanges: readonly NotebookDocumentContentChange[]; + + readonly cellChanges: NotebookDocumentContentCellChange[]; + } + + export namespace workspace { + + /** + * An event that is emitted when a {@link NotebookDocument notebook} is saved. + */ + export const onDidSaveNotebookDocument: Event; + + /** + * An event that is emitted when a {@link NotebookDocument notebook} has changed. + */ + export const onDidChangeNotebookDocument: Event; + } +} From 07ad8ae6386335c5b324c86ee3fb0623d76e72f0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Mar 2022 14:31:49 +0100 Subject: [PATCH 012/175] also popular and fix `executionSummary` --- .../api/common/extHostNotebookDocument.ts | 43 +++++++++---------- ...scode.proposed.notebookDocumentEvents.d.ts | 2 +- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/api/common/extHostNotebookDocument.ts b/src/vs/workbench/api/common/extHostNotebookDocument.ts index 7462e349dfe..4866879fb1a 100644 --- a/src/vs/workbench/api/common/extHostNotebookDocument.ts +++ b/src/vs/workbench/api/common/extHostNotebookDocument.ts @@ -238,52 +238,51 @@ export class ExtHostNotebookDocument { cellChanges: [], contentChanges: [], }; - const cellOutputChanges = new Set(); - const cellMetadataChanges = new Set(); // -- apply change and populate content changes for (const rawEvent of event.rawEvents) { if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ModelChange) { this._spliceNotebookCells(rawEvent.changes, false, result.contentChanges); + } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.Move) { this._moveCell(rawEvent.index, rawEvent.newIdx, result.contentChanges); + } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.Output) { this._setCellOutputs(rawEvent.index, rawEvent.outputs); - cellOutputChanges.add(this._cells[rawEvent.index]); + result.cellChanges.push({ cell: this._cells[rawEvent.index].apiCell, outputs: this._cells[rawEvent.index].apiCell.outputs, executionSummary: undefined, metadata: undefined }); + } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.OutputItem) { this._setCellOutputItems(rawEvent.index, rawEvent.outputId, rawEvent.append, rawEvent.outputItems); - cellOutputChanges.add(this._cells[rawEvent.index]); + result.cellChanges.push({ cell: this._cells[rawEvent.index].apiCell, outputs: this._cells[rawEvent.index].apiCell.outputs, executionSummary: undefined, metadata: undefined }); + } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeLanguage) { this._changeCellLanguage(rawEvent.index, rawEvent.language); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMime) { this._changeCellMime(rawEvent.index, rawEvent.mime); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMetadata) { this._changeCellMetadata(rawEvent.index, rawEvent.metadata); - cellMetadataChanges.add(this._cells[rawEvent.index]); + result.cellChanges.push({ cell: this._cells[rawEvent.index].apiCell, outputs: undefined, executionSummary: undefined, metadata: this._cells[rawEvent.index].apiCell.metadata }); + } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellInternalMetadata) { this._changeCellInternalMetadata(rawEvent.index, rawEvent.internalMetadata); + result.cellChanges.push({ cell: this._cells[rawEvent.index].apiCell, outputs: undefined, executionSummary: this._cells[rawEvent.index].apiCell.executionSummary, metadata: undefined }); } } - // -- populate cell changes + // -- compact cellChanges - for (const cell of cellOutputChanges) { - result.cellChanges.push({ - cell: cell.apiCell, - outputs: cell.apiCell.outputs, - metadata: cellMetadataChanges.has(cell) ? cell.apiCell.metadata : undefined, - executionSummary: undefined - }); - cellMetadataChanges.delete(cell); - } - for (const cell of cellMetadataChanges) { - result.cellChanges.push({ - cell: cell.apiCell, - metadata: cell.apiCell.metadata, - outputs: undefined, - executionSummary: undefined - }); + const map = new Map(); + for (let i = 0; i < result.cellChanges.length; i++) { + let c = result.cellChanges[i]; + let existing = map.get(c.cell); + if (existing === undefined) { + map.set(c.cell, i); + } else { + result.cellChanges[existing] = { ...result.cellChanges[existing], ...c }; + result.cellChanges.splice(i, 1); + i--; + } } return result; diff --git a/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts b/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts index 5eb564f12d8..92052dced75 100644 --- a/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts +++ b/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts @@ -14,7 +14,7 @@ declare module 'vscode' { readonly metadata: { [key: string]: any } | undefined; readonly outputs: readonly NotebookCellOutput[] | undefined; - readonly executionSummary: readonly NotebookCellExecutionSummary[] | undefined; + readonly executionSummary: NotebookCellExecutionSummary | undefined; } export interface NotebookDocumentContentChange { From c7334ace34f50c1094da01815bbbc44a684284ec Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Mar 2022 15:05:10 +0100 Subject: [PATCH 013/175] fix https://github.com/microsoft/vscode/issues/144681 --- .../services/extensions/worker/polyfillNestedWorker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts b/src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts index f70257dafd7..da0a8f5a574 100644 --- a/src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts +++ b/src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts @@ -90,7 +90,7 @@ export class NestedWorker extends EventTarget implements Worker { type: '_terminateWorker', id }; - channel.port1.postMessage(msg); + nativePostMessage(msg); URL.revokeObjectURL(blobUrl); channel.port1.close(); From d77935ebfd6c544b1be235f523ab3b1cf26231c9 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Mar 2022 15:07:01 +0100 Subject: [PATCH 014/175] update distro --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a0ec41c5583..3725ef849fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.66.0", - "distro": "98240d3c774b8651c2beec9020e21abe32916840", + "distro": "621c6035be8022ecbef748501f769f483a85f2a9", "author": { "name": "Microsoft Corporation" }, @@ -232,4 +232,4 @@ "elliptic": "^6.5.3", "nwmatcher": "^1.4.4" } -} \ No newline at end of file +} From e8e34889d85d4b5556374bb68e127d50139944d1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Mar 2022 15:33:47 +0100 Subject: [PATCH 015/175] missing `throw` --- src/vs/workbench/api/browser/mainThreadDocuments.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/browser/mainThreadDocuments.ts b/src/vs/workbench/api/browser/mainThreadDocuments.ts index 256b1b08bf9..0e64e46b917 100644 --- a/src/vs/workbench/api/browser/mainThreadDocuments.ts +++ b/src/vs/workbench/api/browser/mainThreadDocuments.ts @@ -214,7 +214,7 @@ export class MainThreadDocuments extends Disposable implements MainThreadDocumen async $tryOpenDocument(uriData: UriComponents): Promise { const inputUri = URI.revive(uriData); if (!inputUri.scheme || !(inputUri.fsPath || inputUri.authority)) { - new Error(`Invalid uri. Scheme and authority or path must be set.`); + throw new Error(`Invalid uri. Scheme and authority or path must be set.`); } const canonicalUri = this._uriIdentityService.asCanonicalUri(inputUri); From 92f4bd7894c3b790d37b1eec3c7fb5e5f8618f70 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 8 Mar 2022 15:36:12 +0100 Subject: [PATCH 016/175] Update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3725ef849fc..c6983330f73 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.66.0", - "distro": "621c6035be8022ecbef748501f769f483a85f2a9", + "distro": "a946da5062e015d407fd55c37b8fe53db13c639e", "author": { "name": "Microsoft Corporation" }, From cf86a5e3107af33a1b8420a0d10d293c5811bbd7 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Tue, 8 Mar 2022 07:00:28 -0800 Subject: [PATCH 017/175] Identify language tag settings (#144441) --- .../configuration/common/configurationRegistry.ts | 3 ++- .../preferences/browser/media/settingsEditor2.css | 4 ++++ .../contrib/preferences/browser/settingsTree.ts | 14 ++++++++++---- .../preferences/browser/settingsTreeModels.ts | 11 +++++++++-- .../services/preferences/common/preferences.ts | 4 +++- .../preferences/common/preferencesModels.ts | 8 +++++++- 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index 1aa57c19107..a542ece3216 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -292,10 +292,11 @@ class ConfigurationRegistry implements IConfigurationRegistry { if (OVERRIDE_PROPERTY_REGEX.test(key)) { const defaultValue = { ...(this.configurationDefaultsOverrides.get(key)?.value || {}), ...overrides[key] }; this.configurationDefaultsOverrides.set(key, { source, value: defaultValue }); + const plainKey = key.replace(/[\[\]]/g, ''); const property: IRegisteredConfigurationPropertySchema = { type: 'object', default: defaultValue, - description: nls.localize('defaultLanguageConfiguration.description', "Configure settings to be overridden for {0} language.", key), + description: nls.localize('defaultLanguageConfiguration.description', "Configure settings to be overridden for the {0} language.", plainKey), $ref: resourceLanguageSettingsSchemaId, defaultDefaultValue: defaultValue, source: types.isString(source) ? undefined : source, diff --git a/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css b/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css index f8a66626787..3804fa90843 100644 --- a/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css +++ b/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css @@ -340,6 +340,10 @@ padding-left: 1px; } +.settings-editor > .settings-body .settings-tree-container .setting-item-contents .setting-item-title .setting-item-label .codicon { + vertical-align: text-top; +} + .settings-editor > .settings-body .settings-tree-container .setting-item-contents .setting-item-title .setting-item-overrides a.modified-scope { text-decoration: underline; cursor: pointer; diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index adcce5c886c..83c3b881206 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -583,7 +583,7 @@ interface ISettingItemTemplate extends IDisposableTemplate { context?: SettingsTreeSettingElement; containerElement: HTMLElement; categoryElement: HTMLElement; - labelElement: HTMLElement; + labelElement: SimpleIconLabel; descriptionElement: HTMLElement; controlElement: HTMLElement; deprecationWarningElement: HTMLElement; @@ -775,7 +775,8 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre const titleElement = DOM.append(container, $('.setting-item-title')); const labelCategoryContainer = DOM.append(titleElement, $('.setting-item-cat-label-container')); const categoryElement = DOM.append(labelCategoryContainer, $('span.setting-item-category')); - const labelElement = DOM.append(labelCategoryContainer, $('span.setting-item-label')); + const labelElementContainer = DOM.append(labelCategoryContainer, $('span.setting-item-label')); + const labelElement = new SimpleIconLabel(labelElementContainer); const miscLabel = new SettingsTreeMiscLabel(titleElement); @@ -867,7 +868,7 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre template.categoryElement.textContent = element.displayCategory && (element.displayCategory + ': '); template.categoryElement.title = titleTooltip; - template.labelElement.textContent = element.displayLabel; + template.labelElement.text = element.displayLabel; template.labelElement.title = titleTooltip; template.descriptionElement.innerText = ''; @@ -1756,7 +1757,8 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre const titleElement = DOM.append(container, $('.setting-item-title')); const categoryElement = DOM.append(titleElement, $('span.setting-item-category')); - const labelElement = DOM.append(titleElement, $('span.setting-item-label')); + const labelElementContainer = DOM.append(titleElement, $('span.setting-item-label')); + const labelElement = new SimpleIconLabel(labelElementContainer); const miscLabel = new SettingsTreeMiscLabel(titleElement); const descriptionAndValueElement = DOM.append(container, $('.setting-item-value-description')); @@ -2303,6 +2305,10 @@ class SettingsTreeDelegate extends CachedListVirtualDelegate= 0) { @@ -515,6 +517,11 @@ export function settingKeyToDisplayFormat(key: string, groupId = ''): { category category = trimCategoryForGroup(category, groupId); category = wordifyKey(category); + if (isLanguageTagSetting) { + key = key.replace(/[\[\]]/g, ''); + key = '$(bracket) ' + key; + } + const label = wordifyKey(key); return { category, label }; } diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts index 7b8c9cbc518..637c82f3e47 100644 --- a/src/vs/workbench/services/preferences/common/preferences.ts +++ b/src/vs/workbench/services/preferences/common/preferences.ts @@ -34,7 +34,8 @@ export enum SettingValueType { NullableInteger = 'nullable-integer', NullableNumber = 'nullable-number', Object = 'object', - BooleanObject = 'boolean-object' + BooleanObject = 'boolean-object', + LanguageTag = 'language-tag' } export interface ISettingsGroup { @@ -87,6 +88,7 @@ export interface ISetting { allKeysAreBoolean?: boolean; editPresentation?: EditPresentationTypes; defaultValueSource?: string | IExtensionInfo; + isLanguageTagSetting?: boolean; } export interface IExtensionSetting extends ISetting { diff --git a/src/vs/workbench/services/preferences/common/preferencesModels.ts b/src/vs/workbench/services/preferences/common/preferencesModels.ts index d9a1217ef07..979d4e0e660 100644 --- a/src/vs/workbench/services/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/services/preferences/common/preferencesModels.ts @@ -676,6 +676,11 @@ export class DefaultSettings extends Disposable { defaultValueSource = registeredConfigurationProp.defaultValueSource; } + let isLanguageTagSetting = false; + if (OVERRIDE_PROPERTY_REGEX.test(key)) { + isLanguageTagSetting = true; + } + result.push({ key, value, @@ -707,7 +712,8 @@ export class DefaultSettings extends Disposable { allKeysAreBoolean, editPresentation: prop.editPresentation, order: prop.order, - defaultValueSource + defaultValueSource, + isLanguageTagSetting }); } } From 952b2f81ebcfbfe224a93e3ff3751d7249e55090 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 8 Mar 2022 07:20:55 -0800 Subject: [PATCH 018/175] Default terminal min contrast to 4.5 (WCAG AA) Fixes #144411 --- .../workbench/contrib/terminal/common/terminalConfiguration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 3b2bebc9852..970b45c4144 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -188,7 +188,7 @@ const terminalConfiguration: IConfigurationNode = { [TerminalSettingId.MinimumContrastRatio]: { markdownDescription: localize('terminal.integrated.minimumContrastRatio', "When set the foreground color of each cell will change to try meet the contrast ratio specified. Example values:\n\n- 1: The default, do nothing.\n- 4.5: [WCAG AA compliance (minimum)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html).\n- 7: [WCAG AAA compliance (enhanced)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html).\n- 21: White on black or black on white."), type: 'number', - default: 1 + default: 4.5 }, [TerminalSettingId.FastScrollSensitivity]: { markdownDescription: localize('terminal.integrated.fastScrollSensitivity', "Scrolling speed multiplier when pressing `Alt`."), From a566d63fdf6a10f9b92d8b61d65b6715d4fdf6c7 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 8 Mar 2022 07:25:24 -0800 Subject: [PATCH 019/175] Update setting description for new default --- .../workbench/contrib/terminal/common/terminalConfiguration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 970b45c4144..4fa660d22a6 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -186,7 +186,7 @@ const terminalConfiguration: IConfigurationNode = { default: DEFAULT_LINE_HEIGHT }, [TerminalSettingId.MinimumContrastRatio]: { - markdownDescription: localize('terminal.integrated.minimumContrastRatio', "When set the foreground color of each cell will change to try meet the contrast ratio specified. Example values:\n\n- 1: The default, do nothing.\n- 4.5: [WCAG AA compliance (minimum)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html).\n- 7: [WCAG AAA compliance (enhanced)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html).\n- 21: White on black or black on white."), + markdownDescription: localize('terminal.integrated.minimumContrastRatio', "When set the foreground color of each cell will change to try meet the contrast ratio specified. Example values:\n\n- 1: Do nothing and use the standard theme colors.\n- 4.5: [WCAG AA compliance (minimum)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html) (default).\n- 7: [WCAG AAA compliance (enhanced)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html).\n- 21: White on black or black on white."), type: 'number', default: 4.5 }, From 28ae21d199922da627a3e0a2b501fd4d46be0299 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 8 Mar 2022 08:04:34 -0800 Subject: [PATCH 020/175] Fix link hover lifecycle problems - The mouse no longer needs to hover the tooltip to hide the link hover/target, this was fixed by having the widget container live under xterm.js' screen element instead of element. This ensures the events bubble in the right order and have the link get hidden by xterm.js (vscode link widget -> xterm.js link [listening to screen]). - Don't hide the hover when a modifier was pressed. This regressed in #128362 because the behavior is desirable in the activity bar/status bar. There is still a remaining issue where hovering a link, mousing over the tooltip and then back to the link will not allow link activation. This is hard to reproduce and I believe it's a bug in xterm.js somewhere. Fixes #143982 Fixes #144583 --- .../browser/parts/compositeBarActions.ts | 3 ++- .../browser/parts/statusbar/statusbarPart.ts | 5 ++++- .../contrib/terminal/browser/media/terminal.css | 4 ---- .../contrib/terminal/browser/media/widgets.css | 15 +++------------ .../contrib/terminal/browser/terminalInstance.ts | 4 ++-- .../terminal/browser/xterm/xtermTerminal.ts | 4 +++- src/vs/workbench/services/hover/browser/hover.ts | 7 ++++++- .../services/hover/browser/hoverService.ts | 8 +++++--- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 3e853a32ef1..3bfc0a6eca2 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -417,7 +417,8 @@ export class ActivityActionViewItem extends BaseActionViewItem { content: this.computeTitle(), showPointer: true, compact: true, - skipFadeInAnimation + hideOnKeyDown: true, + skipFadeInAnimation, }); } diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 8de32b0b4d5..ac42f712490 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -88,7 +88,10 @@ export class StatusbarPart extends Part implements IStatusbarService { ) { } showHover(options: IHoverDelegateOptions, focus?: boolean): IHoverWidget | undefined { - return this.hoverService.showHover(options, focus); + return this.hoverService.showHover({ + ...options, + hideOnKeyDown: true + }, focus); } onDidHideHover(): void { diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index 791df9d0f8d..9702a0cc0c3 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -109,10 +109,6 @@ position: relative; } -.monaco-workbench .xterm .hoverHighlight { - pointer-events: none; -} - .monaco-workbench .editor-instance .terminal-wrapper > div, .monaco-workbench .pane-body.integrated-terminal .terminal-wrapper > div { height: 100%; diff --git a/src/vs/workbench/contrib/terminal/browser/media/widgets.css b/src/vs/workbench/contrib/terminal/browser/media/widgets.css index 58545a1df0a..a7a58e9bf64 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/widgets.css +++ b/src/vs/workbench/contrib/terminal/browser/media/widgets.css @@ -5,22 +5,13 @@ .monaco-workbench .terminal-widget-container { position: absolute; - left: 10px; - bottom: 2px; - right: 10px; + left: 0; + bottom: 0; + right: 0; top: 0; overflow: visible; } -.monaco-workbench .editor-instance .terminal-group .monaco-split-view2.horizontal .split-view-view:first-child .terminal-widget-container, -.monaco-workbench .pane-body.integrated-terminal .terminal-group .monaco-split-view2.horizontal .split-view-view:first-child .terminal-widget-container { - left: 20px; -} -.monaco-workbench .editor-instance .terminal-group .monaco-split-view2.horizontal .split-view-view:last-child .terminal-widget-container, -.monaco-workbench .pane-body.integrated-terminal .terminal-group .monaco-split-view2.horizontal .split-view-view:last-child .terminal-widget-container { - right: 20px; -} - .monaco-workbench .terminal-overlay-widget { position: absolute; left: 0; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 6290c9b2bf9..c4b868836cb 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -963,7 +963,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // Attach the xterm object to the DOM, exposing it to the smoke tests this._wrapperElement.xterm = xterm.raw; - xterm.attachToElement(xtermElement); + const screenElement = xterm.attachToElement(xtermElement); if (!xterm.raw.element || !xterm.raw.textarea) { throw new Error('xterm elements not set after open'); @@ -1089,7 +1089,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._initDragAndDrop(container); - this._widgetManager.attachToElement(xterm.raw.element); + this._widgetManager.attachToElement(screenElement); this._processManager.onProcessReady((e) => { this._linkManager?.setWidgetManager(this._widgetManager); }); diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts index 256b73585bd..feec88f47ac 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts @@ -167,7 +167,7 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal { this.raw.loadAddon(this._decorationAddon); } - attachToElement(container: HTMLElement) { + attachToElement(container: HTMLElement): HTMLElement { // Update the theme when attaching as the terminal location could have changed this._updateTheme(); if (!this._container) { @@ -177,6 +177,8 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal { if (this._shouldLoadWebgl()) { this._enableWebglRenderer(); } + // Screen must be created at this point as xterm.open is called + return this._container.querySelector('.xterm-screen')!; } updateConfig(): void { diff --git a/src/vs/workbench/services/hover/browser/hover.ts b/src/vs/workbench/services/hover/browser/hover.ts index a9828d36e83..c22832f9755 100644 --- a/src/vs/workbench/services/hover/browser/hover.ts +++ b/src/vs/workbench/services/hover/browser/hover.ts @@ -68,7 +68,7 @@ export interface IHoverOptions { additionalClasses?: string[]; /** - * An optional link handler for markdown links, if this is not provided the IOpenerService will + * An optional link handler for markdown links, if this is not provided the IOpenerService will * be used to open the links using its default options. */ linkHandler?(url: string): void; @@ -85,6 +85,11 @@ export interface IHoverOptions { */ hideOnHover?: boolean; + /** + * Whether to hide the hover when a key is pressed. + */ + hideOnKeyDown?: boolean; + /** * Position of the hover. The default is to show above the target. This option will be ignored * if there is not enough room to layout the hover in the specified position, unless the diff --git a/src/vs/workbench/services/hover/browser/hoverService.ts b/src/vs/workbench/services/hover/browser/hoverService.ts index 4071dfb6a13..7d5331927d9 100644 --- a/src/vs/workbench/services/hover/browser/hoverService.ts +++ b/src/vs/workbench/services/hover/browser/hoverService.ts @@ -50,9 +50,11 @@ export class HoverService implements IHoverService { } else { hoverDisposables.add(addDisposableListener(options.target, EventType.CLICK, () => this.hideHover())); } - const focusedElement = document.activeElement; - if (focusedElement) { - hoverDisposables.add(addDisposableListener(focusedElement, EventType.KEY_DOWN, () => this.hideHover())); + if (options.hideOnKeyDown) { + const focusedElement = document.activeElement; + if (focusedElement) { + hoverDisposables.add(addDisposableListener(focusedElement, EventType.KEY_DOWN, () => this.hideHover())); + } } if ('IntersectionObserver' in window) { From 9be0d5ed05ea064568515e455d8488e3d523d0a8 Mon Sep 17 00:00:00 2001 From: Matt Adam Date: Tue, 8 Mar 2022 08:07:15 -0800 Subject: [PATCH 021/175] Add badges extension API (#139225) * First attempt at a badges API * Updated badge API to reflect feedback * Update to reflect PR feedback * Address further feedback * Badge -> ViewBadge Co-authored-by: Alex Ross --- .../common/extensionsApiProposals.ts | 1 + src/vscode-dts/vscode.proposed.badges.d.ts | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/vscode-dts/vscode.proposed.badges.d.ts diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index 6267489b52d..c4653e81b17 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -7,6 +7,7 @@ export const allApiProposals = Object.freeze({ authSession: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.authSession.d.ts', + badges: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.badges.d.ts', commentsResolvedState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.commentsResolvedState.d.ts', contribLabelFormatterWorkspaceTooltip: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribLabelFormatterWorkspaceTooltip.d.ts', contribMenuBarHome: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribMenuBarHome.d.ts', diff --git a/src/vscode-dts/vscode.proposed.badges.d.ts b/src/vscode-dts/vscode.proposed.badges.d.ts new file mode 100644 index 00000000000..5aed72b6019 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.badges.d.ts @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + // https://github.com/microsoft/vscode/issues/62783 @matthewjamesadam + + /** + * A badge presenting a value for a view + */ + export interface ViewBadge { + + /** + * A label to present in tooltips for the badge + */ + readonly tooltip: string; + + /** + * The value to present in the badge + */ + readonly value: number; + } + + export interface TreeView { + /** + * The badge to display for this TreeView. + * To remove the badge, set to undefined. + */ + badge?: ViewBadge | undefined; + } + + export interface WebviewView { + /** + * The badge to display for this webview view. + * To remove the badge, set to undefined. + */ + badge?: ViewBadge | undefined; + } +} From 4e417cbc550a4196b4586a7243a45f79a1bd24c7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Mar 2022 17:44:06 +0100 Subject: [PATCH 022/175] add tests, also an issue that the tests uncovered --- .../api/common/extHostNotebookDocument.ts | 33 +++++++----- .../api/test/browser/extHostNotebook.test.ts | 51 +++++++++++++++++++ 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/api/common/extHostNotebookDocument.ts b/src/vs/workbench/api/common/extHostNotebookDocument.ts index 4866879fb1a..3fa9f2a53f5 100644 --- a/src/vs/workbench/api/common/extHostNotebookDocument.ts +++ b/src/vs/workbench/api/common/extHostNotebookDocument.ts @@ -231,7 +231,6 @@ export class ExtHostNotebookDocument { this._isDirty = isDirty; this.acceptDocumentPropertiesChanged({ metadata: newMetadata }); - const result = { notebook: this.apiNotebook, metadata: newMetadata, @@ -239,6 +238,9 @@ export class ExtHostNotebookDocument { contentChanges: [], }; + type RelaxedCellChange = Partial & { cell: vscode.NotebookCell }; + const relaxedCellChanges: RelaxedCellChange[] = []; + // -- apply change and populate content changes for (const rawEvent of event.rawEvents) { @@ -250,11 +252,11 @@ export class ExtHostNotebookDocument { } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.Output) { this._setCellOutputs(rawEvent.index, rawEvent.outputs); - result.cellChanges.push({ cell: this._cells[rawEvent.index].apiCell, outputs: this._cells[rawEvent.index].apiCell.outputs, executionSummary: undefined, metadata: undefined }); + relaxedCellChanges.push({ cell: this._cells[rawEvent.index].apiCell, outputs: this._cells[rawEvent.index].apiCell.outputs }); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.OutputItem) { this._setCellOutputItems(rawEvent.index, rawEvent.outputId, rawEvent.append, rawEvent.outputItems); - result.cellChanges.push({ cell: this._cells[rawEvent.index].apiCell, outputs: this._cells[rawEvent.index].apiCell.outputs, executionSummary: undefined, metadata: undefined }); + relaxedCellChanges.push({ cell: this._cells[rawEvent.index].apiCell, outputs: this._cells[rawEvent.index].apiCell.outputs }); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeLanguage) { this._changeCellLanguage(rawEvent.index, rawEvent.language); @@ -262,26 +264,33 @@ export class ExtHostNotebookDocument { this._changeCellMime(rawEvent.index, rawEvent.mime); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMetadata) { this._changeCellMetadata(rawEvent.index, rawEvent.metadata); - result.cellChanges.push({ cell: this._cells[rawEvent.index].apiCell, outputs: undefined, executionSummary: undefined, metadata: this._cells[rawEvent.index].apiCell.metadata }); + relaxedCellChanges.push({ cell: this._cells[rawEvent.index].apiCell, metadata: this._cells[rawEvent.index].apiCell.metadata }); } else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellInternalMetadata) { this._changeCellInternalMetadata(rawEvent.index, rawEvent.internalMetadata); - result.cellChanges.push({ cell: this._cells[rawEvent.index].apiCell, outputs: undefined, executionSummary: this._cells[rawEvent.index].apiCell.executionSummary, metadata: undefined }); + relaxedCellChanges.push({ cell: this._cells[rawEvent.index].apiCell, executionSummary: this._cells[rawEvent.index].apiCell.executionSummary }); } } // -- compact cellChanges const map = new Map(); - for (let i = 0; i < result.cellChanges.length; i++) { - let c = result.cellChanges[i]; - let existing = map.get(c.cell); + for (let i = 0; i < relaxedCellChanges.length; i++) { + const relaxedCellChange = relaxedCellChanges[i]; + const existing = map.get(relaxedCellChange.cell); if (existing === undefined) { - map.set(c.cell, i); + const newLen = result.cellChanges.push({ + executionSummary: undefined, + metadata: undefined, + outputs: undefined, + ...relaxedCellChange, + }); + map.set(relaxedCellChange.cell, newLen - 1); } else { - result.cellChanges[existing] = { ...result.cellChanges[existing], ...c }; - result.cellChanges.splice(i, 1); - i--; + result.cellChanges[existing] = { + ...result.cellChanges[existing], + ...relaxedCellChange + }; } } diff --git a/src/vs/workbench/api/test/browser/extHostNotebook.test.ts b/src/vs/workbench/api/test/browser/extHostNotebook.test.ts index 9930ad289b2..49bd53fa713 100644 --- a/src/vs/workbench/api/test/browser/extHostNotebook.test.ts +++ b/src/vs/workbench/api/test/browser/extHostNotebook.test.ts @@ -418,4 +418,55 @@ suite('NotebookCell#Document', function () { assert.strictEqual(first.document.languageId, 'fooLang'); assert.ok(removedDoc === addedDoc); }); + + test('onDidChangeNotebook-event, cell changes', async function () { + + const p = Event.toPromise(extHostNotebookDocuments.onDidChangeNotebookDocument); + + extHostNotebookDocuments.$acceptModelChanged(notebook.uri, new SerializableObjectWithBuffers({ + versionId: 12, rawEvents: [{ + kind: NotebookCellsChangeType.ChangeCellMetadata, + index: 0, + metadata: { foo: 1 } + }, { + kind: NotebookCellsChangeType.ChangeCellMetadata, + index: 1, + metadata: { foo: 2 }, + }, { + kind: NotebookCellsChangeType.Output, + index: 1, + outputs: [] + }] + }), false, undefined); + + + const event = await p; + + assert.strictEqual(event.notebook === notebook.apiNotebook, true); + assert.strictEqual(event.contentChanges.length, 0); + assert.strictEqual(event.cellChanges.length, 2); + + const [first, second] = event.cellChanges; + assert.deepStrictEqual(first.metadata, first.cell.metadata); + assert.deepStrictEqual(first.executionSummary, undefined); + assert.deepStrictEqual(first.outputs, undefined); + + assert.deepStrictEqual(second.outputs, second.cell.outputs); + assert.deepStrictEqual(second.metadata, second.cell.metadata); + assert.deepStrictEqual(second.executionSummary, undefined); + }); + + test('onDidChangeNotebook-event, notebook metadata', async function () { + + const p = Event.toPromise(extHostNotebookDocuments.onDidChangeNotebookDocument); + + extHostNotebookDocuments.$acceptModelChanged(notebook.uri, new SerializableObjectWithBuffers({ versionId: 12, rawEvents: [] }), false, { foo: 2 }); + + const event = await p; + + assert.strictEqual(event.notebook === notebook.apiNotebook, true); + assert.strictEqual(event.contentChanges.length, 0); + assert.strictEqual(event.cellChanges.length, 0); + assert.deepStrictEqual(event.metadata, { foo: 2 }); + }); }); From 9aa84a3eb0836c6f58d523e4adcb5885370c7e3c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Mar 2022 17:53:04 +0100 Subject: [PATCH 023/175] finalize `DocumentFilter#notebookType`, https://github.com/microsoft/vscode/issues/141143 --- .../workbench/api/common/extHost.api.impl.ts | 3 --- .../common/extensionsApiProposals.ts | 1 - src/vscode-dts/vscode.d.ts | 10 +++++++++ ...ode.proposed.notebookDocumentSelector.d.ts | 22 ------------------- 4 files changed, 10 insertions(+), 26 deletions(-) delete mode 100644 src/vscode-dts/vscode.proposed.notebookDocumentSelector.d.ts diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 36adbdf73ac..dcbda46a232 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -223,9 +223,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I if (typeof filter.exclusive === 'boolean') { checkProposedApiEnabled(extension, 'documentFiltersExclusive'); } - if (typeof filter.notebookType === 'string') { - checkProposedApiEnabled(extension, 'notebookDocumentSelector'); - } } return selector; }; diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index c4653e81b17..445d2114d56 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -32,7 +32,6 @@ export const allApiProposals = Object.freeze({ notebookControllerKind: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookControllerKind.d.ts', notebookDebugOptions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookDebugOptions.d.ts', notebookDeprecated: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookDeprecated.d.ts', - notebookDocumentSelector: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookDocumentSelector.d.ts', notebookEditor: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookEditor.d.ts', notebookEditorDecorationType: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookEditorDecorationType.d.ts', notebookEditorEdit: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookEditorEdit.d.ts', diff --git a/src/vscode-dts/vscode.d.ts b/src/vscode-dts/vscode.d.ts index 43588847444..88aa2cf8cdf 100644 --- a/src/vscode-dts/vscode.d.ts +++ b/src/vscode-dts/vscode.d.ts @@ -2064,6 +2064,16 @@ declare module 'vscode' { */ readonly language?: string; + /** + * The {@link NotebookDocument.notebookType type} of a notebook, like `jupyter`. This allows + * to narrow down on the type of a notebook that a {@link NotebookCell.document cell document} belongs to. + * + * *Note* that combining `notebookType` and {@link DocumentFilter.scheme `scheme`} with a value + * different than `"vscode-notebook-cell"` or `undefined` is invalid and will not match + * any document. + */ + readonly notebookType?: string; + /** * A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. */ diff --git a/src/vscode-dts/vscode.proposed.notebookDocumentSelector.d.ts b/src/vscode-dts/vscode.proposed.notebookDocumentSelector.d.ts deleted file mode 100644 index 5444140314c..00000000000 --- a/src/vscode-dts/vscode.proposed.notebookDocumentSelector.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -declare module 'vscode' { - - // https://github.com/microsoft/vscode/issues/141143 - - export interface DocumentFilter { - - /** - * The {@link NotebookDocument.notebookType type} of a notebook, like `jupyter`. This allows - * to narrow down on the type of a notebook that a {@link NotebookCell.document cell document} belongs to. - * - * *Note* that combining `notebookType` and {@link DocumentFilter.scheme `scheme`} with a value - * different than `"vscode-notebook-cell"` or `undefined` is invalid and will not match - * any document. - */ - readonly notebookType?: string; - } -} From 422665c68ac14e92019fe533f46199024fd250ea Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 8 Mar 2022 17:59:57 +0100 Subject: [PATCH 024/175] - store target platform in local extension - show update action for extensions with outdated target platform --- .../common/extensionManagement.ts | 2 ++ .../node/extensionManagementService.ts | 1 + .../node/extensionsScanner.ts | 3 ++- .../extensions/browser/extensionsActions.ts | 16 ++++++++---- .../browser/extensionsWorkbenchService.ts | 25 ++++++++++++++++--- .../contrib/extensions/common/extensions.ts | 1 + .../common/webExtensionManagementService.ts | 3 ++- 7 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index 0778ba407ab..49906652ff2 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -266,6 +266,7 @@ export interface IGalleryMetadata { publisherId: string; publisherDisplayName: string; isPreReleaseVersion: boolean; + targetPlatform?: TargetPlatform; } export type Metadata = Partial; @@ -277,6 +278,7 @@ export interface ILocalExtension extends IExtension { installedTimestamp?: number; isPreReleaseVersion: boolean; preRelease: boolean; + targetPlatform: TargetPlatform; } export const enum SortBy { diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index c522d9c1de2..98a4571640e 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -324,6 +324,7 @@ class InstallGalleryExtensionTask extends AbstractInstallExtensionTask { id: extension.identifier.uuid, publisherId: extension.publisherId, publisherDisplayName: extension.publisherDisplayName, + targetPlatform: extension.properties.targetPlatform }; let zipPath: string | undefined; diff --git a/src/vs/platform/extensionManagement/node/extensionsScanner.ts b/src/vs/platform/extensionManagement/node/extensionsScanner.ts index 593ae22edfc..07b924e45bd 100644 --- a/src/vs/platform/extensionManagement/node/extensionsScanner.ts +++ b/src/vs/platform/extensionManagement/node/extensionsScanner.ts @@ -20,7 +20,7 @@ import * as pfs from 'vs/base/node/pfs'; import { extract, ExtractError } from 'vs/base/node/zip'; import { localize } from 'vs/nls'; import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; -import { ExtensionManagementError, ExtensionManagementErrorCode, Metadata, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionManagementError, ExtensionManagementErrorCode, Metadata, ILocalExtension, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions, ExtensionIdentifierWithVersion, getGalleryExtensionId, groupByExtension } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls'; import { ExtensionType, IExtensionIdentifier, IExtensionManifest, UNDEFINED_PUBLISHER } from 'vs/platform/extensions/common/extensions'; @@ -336,6 +336,7 @@ export class ExtensionsScanner extends Disposable { local.preRelease = !!metadata?.preRelease; local.isBuiltin = local.type === ExtensionType.System || !!metadata?.isBuiltin; local.installedTimestamp = metadata?.installedTimestamp; + local.targetPlatform = metadata?.targetPlatform ?? TargetPlatform.UNDEFINED; } private async removeUninstalledExtensions(): Promise { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 8f6e11bee28..e4d00340619 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -745,14 +745,14 @@ export class UpdateAction extends ExtensionAction { if (!this.extension) { this.enabled = false; this.class = UpdateAction.DisabledClass; - this.label = this.getUpdateLabel(); + this.label = this.getLabel(); return; } if (this.extension.type !== ExtensionType.User) { this.enabled = false; this.class = UpdateAction.DisabledClass; - this.label = this.getUpdateLabel(); + this.label = this.getLabel(); return; } @@ -761,7 +761,7 @@ export class UpdateAction extends ExtensionAction { this.enabled = canInstall && isInstalled && this.extension.outdated; this.class = this.enabled ? UpdateAction.EnabledClass : UpdateAction.DisabledClass; - this.label = this.extension.outdated ? this.getUpdateLabel(this.extension.latestVersion) : this.getUpdateLabel(); + this.label = this.getLabel(this.extension); } override async run(): Promise { @@ -781,8 +781,14 @@ export class UpdateAction extends ExtensionAction { } } - private getUpdateLabel(version?: string): string { - return version ? localize('updateTo', "Update to {0}", version) : localize('updateAction', "Update"); + private getLabel(extension?: IExtension): string { + if (!extension?.outdated) { + return localize('updateAction', "Update"); + } + if (extension.outdatedTargetPlatform) { + return localize('updateToTargetPlatformVersion', "Update to {0} version", TargetPlatformToString(extension.gallery!.properties.targetPlatform)); + } + return localize('updateToLatestVersion', "Update to {0}", extension.latestVersion); } } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 4919f111cc4..264bb9fbc74 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -15,7 +15,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IExtensionGalleryService, ILocalExtension, IGalleryExtension, IQueryOptions, InstallExtensionEvent, DidUninstallExtensionEvent, IExtensionIdentifier, InstallOperation, InstallOptions, WEB_EXTENSION_TAG, InstallExtensionResult, - IExtensionsControlManifest, InstallVSIXOptions, IExtensionInfo, IExtensionQueryOptions + IExtensionsControlManifest, InstallVSIXOptions, IExtensionInfo, IExtensionQueryOptions, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService, DefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, groupByExtension, ExtensionIdentifierWithVersion, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; @@ -202,7 +202,26 @@ class Extension implements IExtension { } get outdated(): boolean { - return !!this.gallery && this.type === ExtensionType.User && semver.gt(this.latestVersion, this.version) && (this.local?.preRelease || !this.gallery?.properties.isPreReleaseVersion); + if (!this.gallery || !this.local) { + return false; + } + if (this.type !== ExtensionType.User) { + return false; + } + if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) { + return false; + } + if (semver.gt(this.latestVersion, this.version)) { + return true; + } + if (this.outdatedTargetPlatform) { + return true; + } + return false; + } + + get outdatedTargetPlatform(): boolean { + return !!this.local && !!this.gallery && this.local.targetPlatform !== TargetPlatform.UNDEFINED && this.local.targetPlatform !== this.gallery.properties.targetPlatform && semver.eq(this.latestVersion, this.version); } get telemetryData(): any { @@ -436,7 +455,7 @@ class Extensions extends Disposable { if (extension.local && !extension.local.identifier.uuid) { extension.local = await this.updateMetadata(extension.local, gallery); } - if (!extension.gallery || extension.gallery.version !== gallery.version) { + if (!extension.gallery || extension.gallery.version !== gallery.version || extension.gallery.properties.targetPlatform !== gallery.properties.targetPlatform) { extension.gallery = gallery; this._onChange.fire({ extension }); hasChanged = true; diff --git a/src/vs/workbench/contrib/extensions/common/extensions.ts b/src/vs/workbench/contrib/extensions/common/extensions.ts index b6744153baf..b3846d038fc 100644 --- a/src/vs/workbench/contrib/extensions/common/extensions.ts +++ b/src/vs/workbench/contrib/extensions/common/extensions.ts @@ -61,6 +61,7 @@ export interface IExtension { readonly rating?: number; readonly ratingCount?: number; readonly outdated: boolean; + readonly outdatedTargetPlatform: boolean; readonly enablementState: EnablementState; readonly tags: readonly string[]; readonly categories: readonly string[]; diff --git a/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts index c8210fb8179..e9acbbe1ace 100644 --- a/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts @@ -111,7 +111,8 @@ function toLocalExtension(extension: IScannedExtension): ILocalExtension { publisherDisplayName: metadata.publisherDisplayName || null, installedTimestamp: metadata.installedTimestamp, isPreReleaseVersion: !!metadata.isPreReleaseVersion, - preRelease: !!metadata.preRelease + preRelease: !!metadata.preRelease, + targetPlatform: TargetPlatform.WEB }; } From 028f61ace4fa55ecbf603e8c3dd87245ab7c996d Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 8 Mar 2022 18:02:45 +0100 Subject: [PATCH 025/175] Fix #144198 --- src/vs/workbench/contrib/markers/browser/messages.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/markers/browser/messages.ts b/src/vs/workbench/contrib/markers/browser/messages.ts index 3e615d39368..e5d0ab10ba4 100644 --- a/src/vs/workbench/contrib/markers/browser/messages.ts +++ b/src/vs/workbench/contrib/markers/browser/messages.ts @@ -49,7 +49,7 @@ export default class Messages { public static MARKERS_PANEL_SINGLE_UNKNOWN_LABEL: string = nls.localize('markers.panel.single.unknown.label', "1 Unknown"); public static readonly MARKERS_PANEL_MULTIPLE_UNKNOWNS_LABEL = (noOfUnknowns: number): string => { return nls.localize('markers.panel.multiple.unknowns.label', "{0} Unknowns", '' + noOfUnknowns); }; - public static readonly MARKERS_PANEL_AT_LINE_COL_NUMBER = (ln: number, col: number): string => { return nls.localize('markers.panel.at.ln.col.number', "[{0}, {1}]", '' + ln, '' + col); }; + public static readonly MARKERS_PANEL_AT_LINE_COL_NUMBER = (ln: number, col: number): string => { return nls.localize('markers.panel.at.ln.col.number', "[Ln {0}, Col {1}]", '' + ln, '' + col); }; public static readonly MARKERS_TREE_ARIA_LABEL_RESOURCE = (noOfProblems: number, fileName: string, folder: string): string => { return nls.localize('problems.tree.aria.label.resource', "{0} problems in file {1} of folder {2}", noOfProblems, fileName, folder); }; public static readonly MARKERS_TREE_ARIA_LABEL_MARKER = (marker: Marker): string => { From d54c705f6567958a732ac88b1c3ec4d2303fb026 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 8 Mar 2022 17:22:12 +0100 Subject: [PATCH 026/175] Fixes #131027 by introducing editor.bracketPairColorization.useIndependentColorPoolPerBracketType --- src/vs/editor/common/config/editorOptions.ts | 18 ++++++++-- .../editor/common/core/textModelDefaults.ts | 5 ++- src/vs/editor/common/model.ts | 1 + .../bracketPairsTree/ast.ts | 4 ++- .../bracketPairsTree/bracketPairsTree.ts | 34 +++++++++++++------ .../bracketPairsTree/brackets.ts | 4 +-- ...colorizedBracketPairsDecorationProvider.ts | 14 +++++--- src/vs/editor/common/services/modelService.ts | 3 +- src/vs/editor/common/textModelBracketPairs.ts | 1 + src/vs/monaco.d.ts | 5 +++ 10 files changed, 67 insertions(+), 22 deletions(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 54b671b6eb6..5ee0070afd9 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -3550,6 +3550,11 @@ export interface IBracketPairColorizationOptions { * Enable or disable bracket pair colorization. */ enabled?: boolean; + + /** + * Use independent color pool per bracket type. + */ + useIndependentColorPoolPerBracketType?: boolean; } /** @@ -3563,7 +3568,8 @@ export type InternalBracketPairColorizationOptions = Readonly { constructor() { const defaults: InternalBracketPairColorizationOptions = { - enabled: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions.enabled + enabled: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions.enabled, + useIndependentColorPoolPerBracketType: EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions.useIndependentColorPoolPerBracketType, }; super( @@ -3573,7 +3579,12 @@ class BracketPairColorization extends BaseEditorOption ): BracketAstNode { - const node = new BracketAstNode(length, languageId, bracketIds); + const node = new BracketAstNode(length, languageId, text, bracketIds); return node; } @@ -644,6 +645,7 @@ export class BracketAstNode extends ImmutableLeafAstNode { private constructor( length: Length, public readonly languageId: string, + public readonly text: string, /** * In case of a opening bracket, this is the id of the opening bracket. * In case of a closing bracket, this contains the ids of all opening brackets it can close. diff --git a/src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/bracketPairsTree.ts b/src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/bracketPairsTree.ts index 53ad4b6a524..12a1886b0e9 100644 --- a/src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/bracketPairsTree.ts +++ b/src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/bracketPairsTree.ts @@ -128,7 +128,7 @@ export class BracketPairsTree extends Disposable { const endOffset = toLength(range.endLineNumber - 1, range.endColumn - 1); const result = new Array(); const node = this.initialAstWithoutTokens || this.astWithTokens!; - collectBrackets(node, lengthZero, node.length, startOffset, endOffset, result); + collectBrackets(node, lengthZero, node.length, startOffset, endOffset, result, 0, new Map()); return result; } @@ -146,25 +146,35 @@ export class BracketPairsTree extends Disposable { } } -function collectBrackets(node: AstNode, nodeOffsetStart: Length, nodeOffsetEnd: Length, startOffset: Length, endOffset: Length, result: BracketInfo[], level: number = 0): void { +function collectBrackets(node: AstNode, nodeOffsetStart: Length, nodeOffsetEnd: Length, startOffset: Length, endOffset: Length, result: BracketInfo[], level: number = 0, levelPerBracketType?: Map): void { if (node.kind === AstNodeKind.List) { for (const child of node.children) { nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length); if (lengthLessThanEqual(nodeOffsetStart, endOffset) && lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) { - collectBrackets(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level); + collectBrackets(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level, levelPerBracketType); } nodeOffsetStart = nodeOffsetEnd; } } else if (node.kind === AstNodeKind.Pair) { - // Don't use node.children here to improve performance - level++; + let levelPerBracket = 0; + if (levelPerBracketType) { + let existing = levelPerBracketType.get(node.openingBracket.text); + if (existing === undefined) { + existing = 0; + } + levelPerBracket = existing; + existing++; + levelPerBracketType.set(node.openingBracket.text, existing); + } + + // Don't use node.children here to improve performance { const child = node.openingBracket; nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length); if (lengthLessThanEqual(nodeOffsetStart, endOffset) && lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) { const range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd); - result.push(new BracketInfo(range, level - 1, !node.closingBracket)); + result.push(new BracketInfo(range, level, levelPerBracket, !node.closingBracket)); } nodeOffsetStart = nodeOffsetEnd; } @@ -173,7 +183,7 @@ function collectBrackets(node: AstNode, nodeOffsetStart: Length, nodeOffsetEnd: const child = node.child; nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length); if (lengthLessThanEqual(nodeOffsetStart, endOffset) && lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) { - collectBrackets(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level); + collectBrackets(child, nodeOffsetStart, nodeOffsetEnd, startOffset, endOffset, result, level + 1, levelPerBracketType); } nodeOffsetStart = nodeOffsetEnd; } @@ -182,16 +192,20 @@ function collectBrackets(node: AstNode, nodeOffsetStart: Length, nodeOffsetEnd: nodeOffsetEnd = lengthAdd(nodeOffsetStart, child.length); if (lengthLessThanEqual(nodeOffsetStart, endOffset) && lengthGreaterThanEqual(nodeOffsetEnd, startOffset)) { const range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd); - result.push(new BracketInfo(range, level - 1, false)); + result.push(new BracketInfo(range, level, levelPerBracket, false)); } nodeOffsetStart = nodeOffsetEnd; } + + if (levelPerBracketType) { + levelPerBracketType.set(node.openingBracket.text, levelPerBracket); + } } else if (node.kind === AstNodeKind.UnexpectedClosingBracket) { const range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd); - result.push(new BracketInfo(range, level - 1, true)); + result.push(new BracketInfo(range, level - 1, 0, true)); } else if (node.kind === AstNodeKind.Bracket) { const range = lengthsToRange(nodeOffsetStart, nodeOffsetEnd); - result.push(new BracketInfo(range, level - 1, false)); + result.push(new BracketInfo(range, level - 1, 0, false)); } } diff --git a/src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/brackets.ts b/src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/brackets.ts index bfc3e727224..458001931b1 100644 --- a/src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/brackets.ts +++ b/src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/brackets.ts @@ -41,7 +41,7 @@ export class BracketTokens { TokenKind.ClosingBracket, info.first, info.openingBrackets, - BracketAstNode.create(length, configuration.languageId, info.openingBrackets) + BracketAstNode.create(length, configuration.languageId, closingText, info.openingBrackets) )); } @@ -54,7 +54,7 @@ export class BracketTokens { TokenKind.OpeningBracket, openingTextId, bracketIds, - BracketAstNode.create(length, configuration.languageId, bracketIds) + BracketAstNode.create(length, configuration.languageId, openingText, bracketIds) )); } diff --git a/src/vs/editor/common/model/bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider.ts b/src/vs/editor/common/model/bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider.ts index e698380ca34..594e27fb2f6 100644 --- a/src/vs/editor/common/model/bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider.ts +++ b/src/vs/editor/common/model/bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider.ts @@ -55,9 +55,15 @@ export class ColorizedBracketPairsDecorationProvider extends Disposable implemen for (const bracket of bracketsInRange) { result.push({ id: `bracket${bracket.range.toString()}-${bracket.nestingLevel}`, - options: { description: 'BracketPairColorization', inlineClassName: this.colorProvider.getInlineClassName(bracket) }, + options: { + description: 'BracketPairColorization', + inlineClassName: this.colorProvider.getInlineClassName( + bracket, + this.colorizationOptions.useIndependentColorPoolPerBracketType + ), + }, ownerId: 0, - range: bracket.range + range: bracket.range, }); } return result; @@ -81,11 +87,11 @@ export class ColorizedBracketPairsDecorationProvider extends Disposable implemen class ColorProvider { public readonly unexpectedClosingBracketClassName = 'unexpected-closing-bracket'; - getInlineClassName(bracket: BracketInfo): string { + getInlineClassName(bracket: BracketInfo, useIndependentColorPoolPerBracketType: boolean): string { if (bracket.isInvalid) { return this.unexpectedClosingBracketClassName; } - return this.getInlineClassNameOfLevel(bracket.nestingLevel); + return this.getInlineClassNameOfLevel(useIndependentColorPoolPerBracketType ? bracket.nestingLevelOfEqualBracketType : bracket.nestingLevel); } getInlineClassNameOfLevel(level: number): string { diff --git a/src/vs/editor/common/services/modelService.ts b/src/vs/editor/common/services/modelService.ts index 6af5b0c879c..b9772cfd08d 100644 --- a/src/vs/editor/common/services/modelService.ts +++ b/src/vs/editor/common/services/modelService.ts @@ -237,7 +237,8 @@ export class ModelService extends Disposable implements IModelService { let bracketPairColorizationOptions = EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions; if (config.editor?.bracketPairColorization && typeof config.editor.bracketPairColorization === 'object') { bracketPairColorizationOptions = { - enabled: !!config.editor.bracketPairColorization.enabled + enabled: !!config.editor.bracketPairColorization.enabled, + useIndependentColorPoolPerBracketType: !!config.editor.bracketPairColorization.useIndependentColorPoolPerBracketType }; } diff --git a/src/vs/editor/common/textModelBracketPairs.ts b/src/vs/editor/common/textModelBracketPairs.ts index 3a161c57706..a17f11405be 100644 --- a/src/vs/editor/common/textModelBracketPairs.ts +++ b/src/vs/editor/common/textModelBracketPairs.ts @@ -75,6 +75,7 @@ export class BracketInfo { public readonly range: Range, /** 0-based level */ public readonly nestingLevel: number, + public readonly nestingLevelOfEqualBracketType: number, public readonly isInvalid: boolean, ) { } } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 19f6773a063..f46f5507d82 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1686,6 +1686,7 @@ declare namespace monaco.editor { export interface BracketPairColorizationOptions { enabled: boolean; + useIndependentColorPoolPerBracketType: boolean; } export interface ITextModelUpdateOptions { @@ -3974,6 +3975,10 @@ declare namespace monaco.editor { * Enable or disable bracket pair colorization. */ enabled?: boolean; + /** + * Use independent color pool per bracket type. + */ + useIndependentColorPoolPerBracketType?: boolean; } export interface IGuidesOptions { From 0c498599fe225a9a5a7bca3967af6e1048580003 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 8 Mar 2022 09:27:54 -0800 Subject: [PATCH 027/175] Adopt reduced motion in notifications (#144643) --- .../browser/parts/notifications/media/notificationsToasts.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/browser/parts/notifications/media/notificationsToasts.css b/src/vs/workbench/browser/parts/notifications/media/notificationsToasts.css index 987f9a3686d..58b74fb0785 100644 --- a/src/vs/workbench/browser/parts/notifications/media/notificationsToasts.css +++ b/src/vs/workbench/browser/parts/notifications/media/notificationsToasts.css @@ -32,6 +32,10 @@ transition: transform 300ms ease-out, opacity 300ms ease-out; } +.monaco-workbench.reduce-motion > .notifications-toasts .notification-toast-container > .notification-toast { + transition: transform 0ms ease-out, opacity 0ms ease-out; +} + .monaco-workbench > .notifications-toasts .notification-toast-container > .notification-toast.notification-fade-in { opacity: 1; transform: none; From 9117450e6bb2425579be34e67135bd8540bd288d Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 8 Mar 2022 09:28:23 -0800 Subject: [PATCH 028/175] Observe reduced motion in pane split views (#144644) --- src/vs/base/browser/ui/splitview/paneview.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/base/browser/ui/splitview/paneview.css b/src/vs/base/browser/ui/splitview/paneview.css index 7dc22bed9f2..07981a17842 100644 --- a/src/vs/base/browser/ui/splitview/paneview.css +++ b/src/vs/base/browser/ui/splitview/paneview.css @@ -110,6 +110,10 @@ transition-timing-function: ease-out; } +.reduce-motion .monaco-pane-view .split-view-view { + transition-duration: 0s !important; +} + .monaco-pane-view.animated.vertical .split-view-view { transition-property: height; } From 55c34a3df69156a56be91f13f96373371cff84ae Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 8 Mar 2022 18:28:54 +0100 Subject: [PATCH 029/175] Fix #19561 --- .../workbench/api/common/extHost.api.impl.ts | 3 --- .../common/extensionsApiProposals.ts | 1 - src/vscode-dts/vscode.d.ts | 9 +++++-- ...vscode.proposed.outputChannelLanguage.d.ts | 24 ------------------- 4 files changed, 7 insertions(+), 30 deletions(-) delete mode 100644 src/vscode-dts/vscode.proposed.outputChannelLanguage.d.ts diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index dcbda46a232..853620ef7f6 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -649,9 +649,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I return extHostProgress.withProgress(extension, options, task); }, createOutputChannel(name: string, languageId?: string): vscode.OutputChannel { - if (languageId) { - checkProposedApiEnabled(extension, 'outputChannelLanguage'); - } return extHostOutputService.createOutputChannel(name, languageId, extension); }, createWebviewPanel(viewType: string, title: string, showOptions: vscode.ViewColumn | { viewColumn: vscode.ViewColumn; preserveFocus?: boolean }, options?: vscode.WebviewPanelOptions & vscode.WebviewOptions): vscode.WebviewPanel { diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index 445d2114d56..48d4171a9e3 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -38,7 +38,6 @@ export const allApiProposals = Object.freeze({ notebookLiveShare: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookLiveShare.d.ts', notebookMessaging: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookMessaging.d.ts', notebookMime: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookMime.d.ts', - outputChannelLanguage: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.outputChannelLanguage.d.ts', portsAttributes: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.portsAttributes.d.ts', quickPickSortByLabel: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.quickPickSortByLabel.d.ts', resolvers: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.resolvers.d.ts', diff --git a/src/vscode-dts/vscode.d.ts b/src/vscode-dts/vscode.d.ts index 88aa2cf8cdf..bc8381dc645 100644 --- a/src/vscode-dts/vscode.d.ts +++ b/src/vscode-dts/vscode.d.ts @@ -9400,11 +9400,16 @@ declare module 'vscode' { export function createInputBox(): InputBox; /** - * Creates a new {@link OutputChannel output channel} with the given name. + * Creates a new {@link OutputChannel output channel} with the given name and language id + * If language id is not provided, then **Log** is used as default language id. + * + * You can access the visible or active output channel as a {@link TextDocument text document} from {@link window.visibleTextEditors visible editors} or {@link window.activeTextEditor active editor} + * and use the langage id to contribute language features like syntax coloring, code lens etc., * * @param name Human-readable string which will be used to represent the channel in the UI. + * @param languageId The identifier of the language associated with the channel. */ - export function createOutputChannel(name: string): OutputChannel; + export function createOutputChannel(name: string, languageId?: string): OutputChannel; /** * Create and show a new webview panel. diff --git a/src/vscode-dts/vscode.proposed.outputChannelLanguage.d.ts b/src/vscode-dts/vscode.proposed.outputChannelLanguage.d.ts deleted file mode 100644 index c879b778fdd..00000000000 --- a/src/vscode-dts/vscode.proposed.outputChannelLanguage.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// https://github.com/microsoft/vscode/issues/19561 - -declare module 'vscode' { - - export namespace window { - - /** - * Creates a new {@link OutputChannel output channel} with the given name and language id - * If language id is not provided, then **Log** is used as default language id. - * - * You can access the visible or active output channel as a {@link TextDocument text document} from {@link window.visibleTextEditors visible editors} or {@link window.activeTextEditor active editor} - * and use the langage id to contribute language features like syntax coloring, code lens etc., - * - * @param name Human-readable string which will be used to represent the channel in the UI. - * @param languageId The identifier of the language associated with the channel. - */ - export function createOutputChannel(name: string, languageId?: string): OutputChannel; - } -} From 845f027eb385e1cdde3a5f2712cb34443b4b9cef Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 8 Mar 2022 09:33:47 -0800 Subject: [PATCH 030/175] Re-run -> Rerun This is correct according to Oxford Dictionary --- src/vs/workbench/contrib/terminal/browser/terminal.ts | 2 +- .../workbench/contrib/terminal/browser/xterm/decorationAddon.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 48c93766915..cfc20e347b5 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -837,7 +837,7 @@ export interface ITerminalInstance { /** * Triggers a quick pick that displays recent commands or cwds. Selecting one will - * re-run it in the active terminal. + * rerun it in the active terminal. */ runRecent(type: 'command' | 'cwd'): Promise; diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts index 86ecedbe6fa..3687abaf524 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts @@ -276,7 +276,7 @@ export class DecorationAddon extends Disposable implements ITerminalAddon { }); } actions.push({ - class: 'rerun-command', tooltip: 'Rerun Command', dispose: () => { }, id: 'terminal.rerunCommand', label: localize("terminal.rerunCommand", 'Re-run Command'), enabled: true, + class: 'rerun-command', tooltip: 'Rerun Command', dispose: () => { }, id: 'terminal.rerunCommand', label: localize("terminal.rerunCommand", 'Rerun Command'), enabled: true, run: () => this._onDidRequestRunCommand.fire(command.command) }); return actions; From 77ef6aa20efba339a79421d990bc5ae7f3415d02 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 8 Mar 2022 09:39:47 -0800 Subject: [PATCH 031/175] Fix listener leak in cellParts Fix #144338 --- .../contrib/notebook/browser/view/cellParts/cellPart.ts | 5 +++++ .../notebook/browser/view/cellParts/cellToolbars.ts | 4 ++++ .../contrib/notebook/browser/view/cellParts/codeCell.ts | 7 ++++--- .../notebook/browser/view/cellParts/codeCellRunToolbar.ts | 4 ++++ .../notebook/browser/view/cellParts/markdownCell.ts | 7 ++++--- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellPart.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellPart.ts index a8740668eee..66ff2cf6fc7 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellPart.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellPart.ts @@ -19,6 +19,11 @@ export abstract class CellPart extends Disposable { */ abstract renderCell(element: ICellViewModel, templateData: BaseCellRenderTemplate): void; + /** + * Dispose any disposables generated from `renderCell` + */ + unrenderCell(element: ICellViewModel, templateData: BaseCellRenderTemplate): void { } + /** * Perform DOM read operations to prepare for the list/cell layout update. */ diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellToolbars.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellToolbars.ts index 009510a82ae..01c2a557ef8 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellToolbars.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellToolbars.ts @@ -153,6 +153,10 @@ export class CellTitleToolbarPart extends CellPart { }); } + override unrenderCell(element: ICellViewModel, templateData: BaseCellRenderTemplate): void { + this.cellDisposable.clear(); + } + prepareLayout(): void { // nothing to read } diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts index f35f074ab31..3465aa8c244 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts @@ -107,9 +107,10 @@ export class CodeCell extends Disposable { } })); - this.cellParts.forEach(cellPart => { - cellPart.renderCell(this.viewCell, this.templateData); - }); + this.cellParts.forEach(cellPart => cellPart.renderCell(this.viewCell, this.templateData)); + this._register(toDisposable(() => { + this.cellParts.forEach(cellPart => cellPart.unrenderCell(this.viewCell, this.templateData)); + })); this.updateEditorOptions(); this.updateEditorForFocusModeChange(); diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCellRunToolbar.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCellRunToolbar.ts index ae6d1c831ab..9a8f30dc97b 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCellRunToolbar.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCellRunToolbar.ts @@ -66,6 +66,10 @@ export class RunToolbar extends CellPart { }; } + override unrenderCell(element: ICellViewModel, templateData: BaseCellRenderTemplate): void { + this.cellDisposable.clear(); + } + prepareLayout(): void { // no op } diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts index a68d73dc27e..d5a0b97e998 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts @@ -70,9 +70,10 @@ export class StatefulMarkdownCell extends Disposable { this.registerListeners(); // update for init state - this.cellParts.forEach(cellPart => { - cellPart.renderCell(this.viewCell, this.templateData); - }); + this.cellParts.forEach(cellPart => cellPart.renderCell(this.viewCell, this.templateData)); + this._register(toDisposable(() => { + this.cellParts.forEach(cellPart => cellPart.unrenderCell(this.viewCell, this.templateData)); + })); this.updateForHover(); this.updateForFocusModeChange(); From 3a41eb6bac9dfc6a10cf80a9ae82c521fa4c8eda Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 8 Mar 2022 18:55:12 +0100 Subject: [PATCH 032/175] Fix #144646 --- src/vs/platform/configuration/common/configurationModels.ts | 2 +- .../services/configuration/browser/configuration.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index fac7b51ce1f..8afa3b7f065 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -441,7 +441,7 @@ export class UserSettings extends Disposable { this._register(this.fileService.watch(this.userSettingsResource)); this._register(Event.any( Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.userSettingsResource)), - Event.filter(this.fileService.onDidRunOperation, e => (e.isOperation(FileOperation.CREATE) || e.isOperation(FileOperation.DELETE) || e.isOperation(FileOperation.WRITE)) && extUri.isEqual(e.resource, userSettingsResource)) + Event.filter(this.fileService.onDidRunOperation, e => (e.isOperation(FileOperation.CREATE) || e.isOperation(FileOperation.COPY) || e.isOperation(FileOperation.DELETE) || e.isOperation(FileOperation.WRITE)) && extUri.isEqual(e.resource, userSettingsResource)) )(() => this._onDidChange.fire())); } diff --git a/src/vs/workbench/services/configuration/browser/configuration.ts b/src/vs/workbench/services/configuration/browser/configuration.ts index 8150f798a81..2bd9b092c9a 100644 --- a/src/vs/workbench/services/configuration/browser/configuration.ts +++ b/src/vs/workbench/services/configuration/browser/configuration.ts @@ -307,7 +307,7 @@ class FileServiceBasedConfiguration extends Disposable { private handleFileOperationEvent(event: FileOperationEvent): boolean { // One of the resources has changed - if ((event.isOperation(FileOperation.CREATE) || event.isOperation(FileOperation.DELETE) || event.isOperation(FileOperation.WRITE)) + if ((event.isOperation(FileOperation.CREATE) || event.isOperation(FileOperation.COPY) || event.isOperation(FileOperation.DELETE) || event.isOperation(FileOperation.WRITE)) && this.allResources.some(resource => this.uriIdentityService.extUri.isEqual(event.resource, resource))) { return true; } @@ -504,7 +504,7 @@ class FileServiceBasedRemoteUserConfiguration extends Disposable { } private handleFileOperationEvent(event: FileOperationEvent): void { - if ((event.isOperation(FileOperation.CREATE) || event.isOperation(FileOperation.DELETE) || event.isOperation(FileOperation.WRITE)) + if ((event.isOperation(FileOperation.CREATE) || event.isOperation(FileOperation.COPY) || event.isOperation(FileOperation.DELETE) || event.isOperation(FileOperation.WRITE)) && this.uriIdentityService.extUri.isEqual(event.resource, this.configurationResource)) { this.reloadConfigurationScheduler.schedule(); } @@ -721,7 +721,7 @@ class FileServiceBasedWorkspaceConfiguration extends Disposable { this._register(Event.any( Event.filter(this.fileService.onDidFilesChange, e => !!this._workspaceIdentifier && e.contains(this._workspaceIdentifier.configPath)), - Event.filter(this.fileService.onDidRunOperation, e => !!this._workspaceIdentifier && (e.isOperation(FileOperation.CREATE) || e.isOperation(FileOperation.DELETE) || e.isOperation(FileOperation.WRITE)) && uriIdentityService.extUri.isEqual(e.resource, this._workspaceIdentifier.configPath)) + Event.filter(this.fileService.onDidRunOperation, e => !!this._workspaceIdentifier && (e.isOperation(FileOperation.CREATE) || e.isOperation(FileOperation.COPY) || e.isOperation(FileOperation.DELETE) || e.isOperation(FileOperation.WRITE)) && uriIdentityService.extUri.isEqual(e.resource, this._workspaceIdentifier.configPath)) )(() => this.reloadConfigurationScheduler.schedule())); this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this._onDidChange.fire(), 50)); this.workspaceConfigWatcher = this._register(this.watchWorkspaceConfigurationFile()); From e61c1717783b8285829ae812e85a0408f713b459 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 8 Mar 2022 19:13:39 +0100 Subject: [PATCH 033/175] Improve embedding the web worker iframe --- src/vs/server/node/webClientServer.ts | 2 +- src/vs/workbench/common/webview.ts | 22 ++++ .../browser/webWorkerExtensionHost.ts | 17 ++- .../worker/webWorkerExtensionHostIframe.html | 116 ++++++++++++------ src/vs/workbench/test/common/webview.test.ts | 25 ++++ 5 files changed, 141 insertions(+), 41 deletions(-) create mode 100644 src/vs/workbench/test/common/webview.test.ts diff --git a/src/vs/server/node/webClientServer.ts b/src/vs/server/node/webClientServer.ts index 7e6eef8697b..7ccdc3da56d 100644 --- a/src/vs/server/node/webClientServer.ts +++ b/src/vs/server/node/webClientServer.ts @@ -296,7 +296,7 @@ export class WebClientServer { 'default-src \'self\';', 'img-src \'self\' https: data: blob:;', 'media-src \'self\';', - `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-Luz5WwVrEgqx3ZT5ekNejY0UMaLynWfImiCqdaT6CeQ=' http://${remoteAuthority};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html + `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=' http://${remoteAuthority};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html 'child-src \'self\';', `frame-src 'self' https://*.vscode-webview.net data:;`, 'worker-src \'self\' data:;', diff --git a/src/vs/workbench/common/webview.ts b/src/vs/workbench/common/webview.ts index 0b58f3a5d4e..aa329c850a5 100644 --- a/src/vs/workbench/common/webview.ts +++ b/src/vs/workbench/common/webview.ts @@ -81,3 +81,25 @@ function encodeAuthority(authority: string): string { export function decodeAuthority(authority: string) { return authority.replace(/-([0-9a-f]{4})/g, (_, code) => String.fromCharCode(parseInt(code, 16))); } + +/** + * Returns a sha-256 composed of `parentOrigin` and `salt` converted to base 32 + */ +export async function parentOriginHash(parentOrigin: string, salt: string): Promise { + // This same code is also inlined at `src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html` + if (!crypto.subtle) { + throw new Error(`Can't compute sha-256`); + } + const strData = JSON.stringify({ parentOrigin, salt }); + const encoder = new TextEncoder(); + const arrData = encoder.encode(strData); + const hash = await crypto.subtle.digest('sha-256', arrData); + return sha256AsBase32(hash); +} + +function sha256AsBase32(bytes: ArrayBuffer): string { + const array = Array.from(new Uint8Array(bytes)); + const hexArray = array.map(b => b.toString(16).padStart(2, '0')).join(''); + // sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32 + return BigInt(`0x${hexArray}`).toString(32).padStart(52, '0'); +} diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index 55ee8c884d5..beb62b2910a 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -29,6 +29,7 @@ import { Barrier } from 'vs/base/common/async'; import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { FileAccess } from 'vs/base/common/network'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { parentOriginHash } from 'vs/workbench/common/webview'; export interface IWebWorkerExtensionHostInitData { readonly autoStart: boolean; @@ -76,7 +77,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost this._extensionHostLogFile = joinPath(this._extensionHostLogsLocation, `${ExtensionHostLogFileName}.log`); } - private _getWebWorkerExtensionHostIframeSrc(): string { + private async _getWebWorkerExtensionHostIframeSrc(): Promise { const suffix = this._environmentService.debugExtensionHost && this._environmentService.debugRenderer ? '?debugged=1' : '?'; const iframeModulePath = 'vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html'; if (platform.isWeb) { @@ -91,13 +92,18 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost stableOriginUUID = generateUuid(); this._storageService.store(key, stableOriginUUID, StorageScope.WORKSPACE, StorageTarget.MACHINE); } + const hash = await parentOriginHash(window.origin, stableOriginUUID); const baseUrl = ( webEndpointUrlTemplate - .replace('{{uuid}}', stableOriginUUID) + .replace('{{uuid}}', `v--${hash}`) // using `v--` as a marker to require `parentOrigin`/`salt` verification .replace('{{commit}}', commit) .replace('{{quality}}', quality) ); - return `${baseUrl}/out/${iframeModulePath}${suffix}`; + + const res = new URL(`${baseUrl}/out/${iframeModulePath}${suffix}`); + res.searchParams.set('parentOrigin', window.origin); + res.searchParams.set('salt', stableOriginUUID); + return res.toString(); } console.warn(`The web worker extension host is started in a same-origin iframe!`); @@ -109,13 +115,14 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost public async start(): Promise { if (!this._protocolPromise) { - this._protocolPromise = this._startInsideIframe(this._getWebWorkerExtensionHostIframeSrc()); + this._protocolPromise = this._startInsideIframe(); this._protocolPromise.then(protocol => this._protocol = protocol); } return this._protocolPromise; } - private async _startInsideIframe(webWorkerExtensionHostIframeSrc: string): Promise { + private async _startInsideIframe(): Promise { + const webWorkerExtensionHostIframeSrc = await this._getWebWorkerExtensionHostIframeSrc(); const emitter = this._register(new Emitter()); const iframe = document.createElement('iframe'); diff --git a/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html b/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html index fbf718a6253..11135d5fff1 100644 --- a/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html +++ b/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html @@ -4,7 +4,7 @@ @@ -13,6 +13,45 @@ const searchParams = new URL(document.location.href).searchParams; const vscodeWebWorkerExtHostId = searchParams.get('vscodeWebWorkerExtHostId') || ''; const name = searchParams.get('debugged') ? 'DebugWorkerExtensionHost' : 'WorkerExtensionHost'; + const parentOrigin = searchParams.get('parentOrigin') || window.origin; + const salt = searchParams.get('salt'); + + (async function() { + const hostnameValidationMarker = 'v--'; + const hostname = location.hostname; + if (!hostname.startsWith(hostnameValidationMarker)) { + // validation not requested + return start(); + } + if (!crypto.subtle) { + // cannot validate, not running in a secure context + return sendError(new Error(`Cannot validate in current context!`)); + } + + // Here the `parentOriginHash()` function from `src/vs/workbench/common/webview.ts` is inlined + // compute a sha-256 composed of `parentOrigin` and `salt` converted to base 32 + let parentOriginHash; + try { + const strData = JSON.stringify({ parentOrigin, salt }); + const encoder = new TextEncoder(); + const arrData = encoder.encode(strData); + const hash = await crypto.subtle.digest('sha-256', arrData); + const hashArray = Array.from(new Uint8Array(hash)); + const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); + // sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32 + parentOriginHash = BigInt(`0x${hashHex}`).toString(32).padStart(52, '0'); + } catch(err) { + return sendError(err instanceof Error ? err : new Error(String(err))); + } + + const requiredSubdomain = `${hostnameValidationMarker}${parentOriginHash}.`; + if (hostname.substring(0, requiredSubdomain.length) === requiredSubdomain) { + // validation succeeded! + return start(); + } + + return sendError(new Error(`Expected '${requiredSubdomain}' as subdomain!`)); + })(); function sendError(error) { window.parent.postMessage({ @@ -25,45 +64,52 @@ }, '*'); } - try { - const worker = new Worker('../../../../base/worker/workerMain.js', { name }); - worker.postMessage('vs/workbench/api/worker/extensionHostWorker'); - const nestedWorkers = new Map(); + function start() { + try { + const worker = new Worker('../../../../base/worker/workerMain.js', { name }); + worker.postMessage('vs/workbench/api/worker/extensionHostWorker'); + const nestedWorkers = new Map(); - worker.onmessage = (event) => { - const { data } = event; + worker.onmessage = (event) => { + const { data } = event; - if (data?.type === '_newWorker') { - const { id, port, url, options } = data; - const newWorker = new Worker(url, options); - newWorker.postMessage(port, [port]); - worker.onerror = console.error.bind(console); - nestedWorkers.set(id, newWorker); + if (data?.type === '_newWorker') { + const { id, port, url, options } = data; + const newWorker = new Worker(url, options); + newWorker.postMessage(port, [port]); + worker.onerror = console.error.bind(console); + nestedWorkers.set(id, newWorker); - } else if (data?.type === '_terminateWorker') { - const { id } = data; - if(nestedWorkers.has(id)) { - nestedWorkers.get(id).terminate(); - nestedWorkers.delete(id); + } else if (data?.type === '_terminateWorker') { + const { id } = data; + if(nestedWorkers.has(id)) { + nestedWorkers.get(id).terminate(); + nestedWorkers.delete(id); + } + } else { + worker.onerror = console.error.bind(console); + window.parent.postMessage({ + vscodeWebWorkerExtHostId, + data + }, parentOrigin, [data]); } - } else { - worker.onerror = console.error.bind(console); - window.parent.postMessage({ - vscodeWebWorkerExtHostId, - data - }, '*', [data]); + }; + + worker.onerror = (event) => { + console.error(event.message, event.error); + sendError(event.error); + }; + + self.onmessage = (event) => { + if (event.origin !== parentOrigin) { + return; + } + worker.postMessage(event.data, event.ports); } - }; - - worker.onerror = (event) => { - console.error(event.message, event.error); - sendError(event.error); - }; - - self.onmessage = (event) => worker.postMessage(event.data, event.ports); - } catch(err) { - console.error(err); - sendError(err); + } catch(err) { + console.error(err); + sendError(err); + } } })(); diff --git a/src/vs/workbench/test/common/webview.test.ts b/src/vs/workbench/test/common/webview.test.ts new file mode 100644 index 00000000000..c73afc16c66 --- /dev/null +++ b/src/vs/workbench/test/common/webview.test.ts @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { parentOriginHash } from 'vs/workbench/common/webview'; + +suite('parentOriginHash', () => { + + test('localhost 1', async () => { + const hash = await parentOriginHash('http://localhost:9888', '123456'); + assert.strictEqual(hash, '0fnsiac2jaup1t266qekgr7iuj4pnm31gf8r0h1o6k2lvvmfh6hk'); + }); + + test('localhost 2', async () => { + const hash = await parentOriginHash('http://localhost:9888', '123457'); + assert.strictEqual(hash, '07shf01bmdfrghk96voldpletbh36vj7blnl4td8kdq1sej5kjqs'); + }); + + test('localhost 3', async () => { + const hash = await parentOriginHash('http://localhost:9887', '123456'); + assert.strictEqual(hash, '1v1128i162q0nee9l89360sqan26u3pdnjrkke5ijd0sel8sbtqf'); + }); +}); From bac505d4be694694f309fad43d485166e8209fea Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 8 Mar 2022 10:03:23 -0800 Subject: [PATCH 034/175] Update wording to include "animation" for searching Ref #128595 --- 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 e882bfd521d..865b54ffca7 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -374,7 +374,7 @@ const registry = Registry.as(ConfigurationExtensions.Con }, 'workbench.reduceMotion': { type: 'string', - description: localize('workbench.reduceMotion', "Controls whether the workbench should render with fewer animated effects."), + description: localize('workbench.reduceMotion', "Controls whether the workbench should render with fewer animations."), 'enumDescriptions': [ localize('workbench.reduceMotion.on', "Always render with reduced motion."), localize('workbench.reduceMotion.off', "Do not render with reduced motion"), From bdc97509d2a00fdd2481130b31ba5fe0b2d5717a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 8 Mar 2022 19:19:23 +0100 Subject: [PATCH 035/175] Fix layer violations --- src/vs/workbench/browser/webview.ts | 25 +++++++++++++++++++ src/vs/workbench/common/webview.ts | 22 ---------------- .../browser/webWorkerExtensionHost.ts | 2 +- .../test/{common => browser}/webview.test.ts | 2 +- 4 files changed, 27 insertions(+), 24 deletions(-) create mode 100644 src/vs/workbench/browser/webview.ts rename src/vs/workbench/test/{common => browser}/webview.test.ts (94%) diff --git a/src/vs/workbench/browser/webview.ts b/src/vs/workbench/browser/webview.ts new file mode 100644 index 00000000000..27ad38106b7 --- /dev/null +++ b/src/vs/workbench/browser/webview.ts @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +/** + * Returns a sha-256 composed of `parentOrigin` and `salt` converted to base 32 + */ +export async function parentOriginHash(parentOrigin: string, salt: string): Promise { + // This same code is also inlined at `src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html` + if (!crypto.subtle) { + throw new Error(`Can't compute sha-256`); + } + const strData = JSON.stringify({ parentOrigin, salt }); + const encoder = new TextEncoder(); + const arrData = encoder.encode(strData); + const hash = await crypto.subtle.digest('sha-256', arrData); + return sha256AsBase32(hash); +} + +function sha256AsBase32(bytes: ArrayBuffer): string { + const array = Array.from(new Uint8Array(bytes)); + const hexArray = array.map(b => b.toString(16).padStart(2, '0')).join(''); + // sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32 + return BigInt(`0x${hexArray}`).toString(32).padStart(52, '0'); +} diff --git a/src/vs/workbench/common/webview.ts b/src/vs/workbench/common/webview.ts index aa329c850a5..0b58f3a5d4e 100644 --- a/src/vs/workbench/common/webview.ts +++ b/src/vs/workbench/common/webview.ts @@ -81,25 +81,3 @@ function encodeAuthority(authority: string): string { export function decodeAuthority(authority: string) { return authority.replace(/-([0-9a-f]{4})/g, (_, code) => String.fromCharCode(parseInt(code, 16))); } - -/** - * Returns a sha-256 composed of `parentOrigin` and `salt` converted to base 32 - */ -export async function parentOriginHash(parentOrigin: string, salt: string): Promise { - // This same code is also inlined at `src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html` - if (!crypto.subtle) { - throw new Error(`Can't compute sha-256`); - } - const strData = JSON.stringify({ parentOrigin, salt }); - const encoder = new TextEncoder(); - const arrData = encoder.encode(strData); - const hash = await crypto.subtle.digest('sha-256', arrData); - return sha256AsBase32(hash); -} - -function sha256AsBase32(bytes: ArrayBuffer): string { - const array = Array.from(new Uint8Array(bytes)); - const hexArray = array.map(b => b.toString(16).padStart(2, '0')).join(''); - // sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32 - return BigInt(`0x${hexArray}`).toString(32).padStart(52, '0'); -} diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index beb62b2910a..2503a9db881 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -29,7 +29,7 @@ import { Barrier } from 'vs/base/common/async'; import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { FileAccess } from 'vs/base/common/network'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; -import { parentOriginHash } from 'vs/workbench/common/webview'; +import { parentOriginHash } from 'vs/workbench/browser/webview'; export interface IWebWorkerExtensionHostInitData { readonly autoStart: boolean; diff --git a/src/vs/workbench/test/common/webview.test.ts b/src/vs/workbench/test/browser/webview.test.ts similarity index 94% rename from src/vs/workbench/test/common/webview.test.ts rename to src/vs/workbench/test/browser/webview.test.ts index c73afc16c66..a483b086d8b 100644 --- a/src/vs/workbench/test/common/webview.test.ts +++ b/src/vs/workbench/test/browser/webview.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { parentOriginHash } from 'vs/workbench/common/webview'; +import { parentOriginHash } from 'vs/workbench/browser/webview'; suite('parentOriginHash', () => { From a68c739508a823119bbee45794727a0a3b37312d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 8 Mar 2022 19:22:29 +0100 Subject: [PATCH 036/175] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0395eabaae0..717e6a71995 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.66.0", - "distro": "a946da5062e015d407fd55c37b8fe53db13c639e", + "distro": "3a09d71f5b5e1b47bc85822484123fbfaf983c80", "author": { "name": "Microsoft Corporation" }, From 98e5315c0d92b7c368de15ab3e4af9ccd3c88ee1 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 8 Mar 2022 10:45:03 -0800 Subject: [PATCH 037/175] Better callstack tooltips Fix #144540 --- src/vs/workbench/contrib/debug/browser/callStackView.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index 60129cb91a3..687732063d7 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -587,11 +587,11 @@ class SessionsRenderer implements ICompressibleTreeRenderer, _index: number, data: IThreadTemplateData): void { const thread = element.element; - data.thread.title = localize('thread', "Thread"); + data.thread.title = thread.name; data.label.set(thread.name, createMatches(element.filterData)); data.stateLabel.textContent = thread.stateLabel; data.stateLabel.classList.toggle('exception', thread.stoppedDetails?.reason === 'exception'); From fa6ee6ce918b20a476d344218cc680af7160f419 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 11:16:35 -0800 Subject: [PATCH 038/175] Only allow webviews protocol in top level editor windows --- src/vs/code/electron-main/app.ts | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 9b81454c010..0443e77cd7d 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -195,9 +195,41 @@ export class CodeApplication extends Disposable { return false; }; + const isAllowedWebviewRequest = (details: Electron.OnBeforeRequestListenerDetails): boolean => { + const url = URI.parse(details.url); + + // Only restrict top level page of webviews: index.html + if (url.path !== '/index.html') { + return true; + } + + const frame = details.frame; + if (!frame || !this.windowsMainService) { + return false; + } + + // Check to see if the request comes from one of the main editor windows. + for (const window of this.windowsMainService.getWindows()) { + if (window.win) { + if (frame.processId === window.win.webContents.mainFrame.processId) { + return true; + } + } + } + + return false; + }; + session.defaultSession.webRequest.onBeforeRequest((details, callback) => { const uri = URI.parse(details.url); + if (uri.scheme === Schemas.vscodeWebview) { + if (!isAllowedWebviewRequest(details)) { + this.logService.error('Blocked vscode-webview request', details.url); + return callback({ cancel: true }); + } + } + if (uri.scheme === Schemas.vscodeFileResource) { if (!isAllowedVsCodeFileRequest(details)) { this.logService.error('Blocked vscode-file request', details.url); From c569182d081410046ee6e6938e960d1e83063612 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 11:28:59 -0800 Subject: [PATCH 039/175] Encode webview parent origin in authority Fixes #144703 --- product.json | 2 +- .../contrib/webview/browser/pre/main.js | 40 +++++++++++++++++-- .../contrib/webview/browser/webviewElement.ts | 40 +++++++++++-------- .../electron-sandbox/webviewElement.ts | 4 +- .../environment/browser/environmentService.ts | 2 +- test/automation/src/playwrightDriver.ts | 2 +- test/integration/browser/src/index.ts | 2 +- 7 files changed, 67 insertions(+), 25 deletions(-) diff --git a/product.json b/product.json index b69651d0b5e..b01093caf3a 100644 --- a/product.json +++ b/product.json @@ -27,7 +27,7 @@ "licenseFileName": "LICENSE.txt", "reportIssueUrl": "https://github.com/microsoft/vscode/issues/new", "urlProtocol": "code-oss", - "webviewContentExternalBaseUrlTemplate": "https://{{uuid}}.vscode-webview.net/insider/93a2a2fa12dd3ae0629eec01c05a28cb60ac1c4b/out/vs/workbench/contrib/webview/browser/pre/", + "webviewContentExternalBaseUrlTemplate": "https://{{uuid}}.vscode-webview.net/insider/181b43c0e2949e36ecb623d8cc6de29d4fa2bae8/out/vs/workbench/contrib/webview/browser/pre/", "builtInExtensions": [ { "name": "ms-vscode.references-view", diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js index 1c5712274cf..1ad429ad3be 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/main.js +++ b/src/vs/workbench/contrib/webview/browser/pre/main.js @@ -22,7 +22,6 @@ const searchParams = new URL(location.toString()).searchParams; const ID = searchParams.get('id'); const onElectron = searchParams.get('platform') === 'electron'; const expectedWorkerVersion = parseInt(searchParams.get('swVersion')); -const parentOrigin = searchParams.get('parentOrigin'); /** * Use polling to track focus of main webview and iframes within the webview @@ -309,8 +308,43 @@ const hostMessaging = new class HostMessaging { handlers.push(handler); } - signalReady() { - window.parent.postMessage({ target: ID, channel: 'webview-ready', data: {} }, parentOrigin, [this.channel.port2]); + async signalReady() { + const start = (/** @type {string} */ parentOrigin) => { + window.parent.postMessage({ target: ID, channel: 'webview-ready', data: {} }, parentOrigin, [this.channel.port2]); + }; + + const parentOrigin = searchParams.get('parentOrigin'); + const id = searchParams.get('id'); + + const hostname = location.hostname; + + if (!crypto.subtle) { + // cannot validate, not running in a secure context + throw new Error(`Cannot validate in current context!`); + } + + // Here the `parentOriginHash()` function from `src/vs/workbench/common/webview.ts` is inlined + // compute a sha-256 composed of `parentOrigin` and `salt` converted to base 32 + let parentOriginHash; + try { + const strData = JSON.stringify({ parentOrigin, salt: id }); + const encoder = new TextEncoder(); + const arrData = encoder.encode(strData); + const hash = await crypto.subtle.digest('sha-256', arrData); + const hashArray = Array.from(new Uint8Array(hash)); + const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); + // sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32 + parentOriginHash = BigInt(`0x${hashHex}`).toString(32).padStart(52, '0'); + } catch (err) { + throw err instanceof Error ? err : new Error(String(err)); + } + + if (hostname === parentOriginHash || hostname.startsWith(parentOriginHash + '.')) { + // validation succeeded! + return start(parentOrigin); + } + + throw new Error(`Expected '${parentOriginHash}' as hostname or subdomain!`); } }(); diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index bdbbdefa59b..7fa67f4e678 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -30,6 +30,7 @@ import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remot import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITunnelService } from 'vs/platform/tunnel/common/tunnel'; import { WebviewPortMappingManager } from 'vs/platform/webview/common/webviewPortMapping'; +import { parentOriginHash } from 'vs/workbench/browser/webview'; import { asWebviewUri, decodeAuthority, webviewGenericCspSource, webviewRootResourceAuthority } from 'vs/workbench/common/webview'; import { loadLocalResource, WebviewResourceResponse } from 'vs/workbench/contrib/webview/browser/resourceLoading'; import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/browser/themeing'; @@ -99,7 +100,10 @@ namespace WebviewState { export class WebviewElement extends Disposable implements IWebview, WebviewFindDelegate { public readonly id: string; - protected readonly iframeId: string; + + private readonly iframeId: string; + private readonly encodedWebviewOriginPromise: Promise; + private encodedWebviewOrigin: string | undefined; protected get platform(): string { return 'browser'; } @@ -144,6 +148,8 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD protected readonly _webviewFindWidget: WebviewFindWidget | undefined; public readonly checkImeCompletionState = true; + private _disposed = false; + constructor( id: string, private readonly options: WebviewOptions, @@ -166,6 +172,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD this.id = id; this.iframeId = generateUuid(); + this.encodedWebviewOriginPromise = parentOriginHash(window.origin, this.iframeId).then(id => this.encodedWebviewOrigin = id); this.content = { html: '', @@ -183,11 +190,11 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD const subscription = this._register(addDisposableListener(window, 'message', (e: MessageEvent) => { - if (e?.data?.target !== this.iframeId) { + if (!this.encodedWebviewOrigin || e?.data?.target !== this.iframeId) { return; } - if (e.origin !== this.webviewContentOrigin) { + if (e.origin !== this.webviewContentOrigin(this.encodedWebviewOrigin)) { console.log(`Skipped renderer receiving message due to mismatched origins: ${e.origin} ${this.webviewContentOrigin}`); return; } @@ -342,10 +349,16 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD this.styledFindWidget(); } - this.initElement(extension, options); + this.encodedWebviewOriginPromise.then(encodedWebviewOrigin => { + if (!this._disposed) { + this.initElement(encodedWebviewOrigin, extension, options); + } + }); } override dispose(): void { + this._disposed = true; + this.element?.remove(); this._element = undefined; @@ -425,7 +438,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD return element; } - private initElement(extension: WebviewExtensionDescription | undefined, options: WebviewOptions) { + private initElement(encodedWebviewOrigin: string, extension: WebviewExtensionDescription | undefined, options: WebviewOptions) { // The extensionId and purpose in the URL are used for filtering in js-debug: const params: { [key: string]: string } = { id: this.iframeId, @@ -449,7 +462,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1754872 const fileName = isFirefox ? 'index-no-csp.html' : 'index.html'; - this.element!.setAttribute('src', `${this.webviewContentEndpoint}/${fileName}?${queryString}`); + this.element!.setAttribute('src', `${this.webviewContentEndpoint(encodedWebviewOrigin)}/${fileName}?${queryString}`); } public mountTo(parent: HTMLElement) { @@ -463,22 +476,17 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD parent.appendChild(this.element); } - protected get webviewContentEndpoint(): string { - const endpoint = this._environmentService.webviewExternalEndpoint!.replace('{{uuid}}', this.id); + protected webviewContentEndpoint(encodedWebviewOrigin: string): string { + const endpoint = this._environmentService.webviewExternalEndpoint!.replace('{{uuid}}', encodedWebviewOrigin); if (endpoint[endpoint.length - 1] === '/') { return endpoint.slice(0, endpoint.length - 1); } return endpoint; } - private _webviewContentOrigin?: string; - - private get webviewContentOrigin(): string { - if (!this._webviewContentOrigin) { - const uri = URI.parse(this.webviewContentEndpoint); - this._webviewContentOrigin = uri.scheme + '://' + uri.authority.toLowerCase(); - } - return this._webviewContentOrigin; + private webviewContentOrigin(encodedWebviewOrigin: string): string { + const uri = URI.parse(this.webviewContentEndpoint(encodedWebviewOrigin)); + return uri.scheme + '://' + uri.authority.toLowerCase(); } private doPostMessage(channel: string, data?: any, transferable: Transferable[] = []): void { diff --git a/src/vs/workbench/contrib/webview/electron-sandbox/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-sandbox/webviewElement.ts index 3a756e0c8bc..aa0f3828ff9 100644 --- a/src/vs/workbench/contrib/webview/electron-sandbox/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-sandbox/webviewElement.ts @@ -92,8 +92,8 @@ export class ElectronWebviewElement extends WebviewElement { } } - protected override get webviewContentEndpoint(): string { - return `${Schemas.vscodeWebview}://${this.iframeId}`; + protected override webviewContentEndpoint(iframeId: string): string { + return `${Schemas.vscodeWebview}://${iframeId}`; } protected override streamToBuffer(stream: VSBufferReadableStream): Promise { diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 84c8f48f3fc..838100ee020 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -182,7 +182,7 @@ export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvi const webviewExternalEndpointCommit = this.payload?.get('webviewExternalEndpointCommit'); return endpoint - .replace('{{commit}}', webviewExternalEndpointCommit ?? this.productService.commit ?? '93a2a2fa12dd3ae0629eec01c05a28cb60ac1c4b') + .replace('{{commit}}', webviewExternalEndpointCommit ?? this.productService.commit ?? '181b43c0e2949e36ecb623d8cc6de29d4fa2bae8') .replace('{{quality}}', (webviewExternalEndpointCommit ? 'insider' : this.productService.quality) ?? 'insider'); } diff --git a/test/automation/src/playwrightDriver.ts b/test/automation/src/playwrightDriver.ts index e9e882e9b0a..b0ecb7153d8 100644 --- a/test/automation/src/playwrightDriver.ts +++ b/test/automation/src/playwrightDriver.ts @@ -282,7 +282,7 @@ async function launchBrowser(options: LaunchOptions, endpoint: string) { } }); - const payloadParam = `[["enableProposedApi",""],["webviewExternalEndpointCommit","93a2a2fa12dd3ae0629eec01c05a28cb60ac1c4b"],["skipWelcome","true"]]`; + const payloadParam = `[["enableProposedApi",""],["webviewExternalEndpointCommit","181b43c0e2949e36ecb623d8cc6de29d4fa2bae8"],["skipWelcome","true"]]`; await measureAndLog(page.goto(`${endpoint}&folder=${URI.file(workspacePath!).path}&payload=${payloadParam}`), 'page.goto()', logger); return { browser, context, page }; diff --git a/test/integration/browser/src/index.ts b/test/integration/browser/src/index.ts index 5281ed3ac98..ab92cbb28c4 100644 --- a/test/integration/browser/src/index.ts +++ b/test/integration/browser/src/index.ts @@ -65,7 +65,7 @@ async function runTestsInBrowser(browserType: BrowserType, endpoint: url.UrlWith const testExtensionUri = url.format({ pathname: URI.file(path.resolve(optimist.argv.extensionDevelopmentPath)).path, protocol, host, slashes: true }); const testFilesUri = url.format({ pathname: URI.file(path.resolve(optimist.argv.extensionTestsPath)).path, protocol, host, slashes: true }); - const payloadParam = `[["extensionDevelopmentPath","${testExtensionUri}"],["extensionTestsPath","${testFilesUri}"],["enableProposedApi",""],["webviewExternalEndpointCommit","93a2a2fa12dd3ae0629eec01c05a28cb60ac1c4b"],["skipWelcome","true"]]`; + const payloadParam = `[["extensionDevelopmentPath","${testExtensionUri}"],["extensionTestsPath","${testFilesUri}"],["enableProposedApi",""],["webviewExternalEndpointCommit","181b43c0e2949e36ecb623d8cc6de29d4fa2bae8"],["skipWelcome","true"]]`; if (path.extname(testWorkspacePath) === '.code-workspace') { await page.goto(`${endpoint.href}&workspace=${testWorkspacePath}&payload=${payloadParam}`); From 41a470a3a9621f1d1543891565c9491e41fb9d6e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 11:38:37 -0800 Subject: [PATCH 040/175] Bump distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 717e6a71995..73986475f51 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.66.0", - "distro": "3a09d71f5b5e1b47bc85822484123fbfaf983c80", + "distro": "3256bc7614eaa43a118a42b69f686e5d43954113", "author": { "name": "Microsoft Corporation" }, From a2e8cd7f1c907c607781f1378b93457c9351e5ce Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 8 Mar 2022 19:36:51 +0100 Subject: [PATCH 041/175] Allow passing in strings --- src/vs/base/browser/fastDomNode.ts | 82 ++++++++++--------- .../overlayWidgets/overlayWidgets.ts | 2 +- 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/vs/base/browser/fastDomNode.ts b/src/vs/base/browser/fastDomNode.ts index cbc959e308d..30122d0c4ad 100644 --- a/src/vs/base/browser/fastDomNode.ts +++ b/src/vs/base/browser/fastDomNode.ts @@ -5,21 +5,21 @@ export class FastDomNode { - private _maxWidth: number = -1; - private _width: number = -1; - private _height: number = -1; - private _top: number = -1; - private _left: number = -1; - private _bottom: number = -1; - private _right: number = -1; + private _maxWidth: string = ''; + private _width: string = ''; + private _height: string = ''; + private _top: string = ''; + private _left: string = ''; + private _bottom: string = ''; + private _right: string = ''; private _fontFamily: string = ''; private _fontWeight: string = ''; - private _fontSize: number = -1; + private _fontSize: string = ''; private _fontStyle: string = ''; private _fontFeatureSettings: string = ''; private _textDecoration: string = ''; - private _lineHeight: number = -1; - private _letterSpacing: number = -100; + private _lineHeight: string = ''; + private _letterSpacing: string = ''; private _className: string = ''; private _display: string = ''; private _position: string = ''; @@ -34,68 +34,67 @@ export class FastDomNode { public readonly domNode: T ) { } - public setMaxWidth(maxWidth: number): void { + public setMaxWidth(_maxWidth: number | string): void { + const maxWidth = numberAsPixels(_maxWidth); if (this._maxWidth === maxWidth) { return; } this._maxWidth = maxWidth; - this.domNode.style.maxWidth = this._maxWidth + 'px'; + this.domNode.style.maxWidth = this._maxWidth; } - public setWidth(width: number): void { + public setWidth(_width: number | string): void { + const width = numberAsPixels(_width); if (this._width === width) { return; } this._width = width; - this.domNode.style.width = this._width + 'px'; + this.domNode.style.width = this._width; } - public setHeight(height: number): void { + public setHeight(_height: number | string): void { + const height = numberAsPixels(_height); if (this._height === height) { return; } this._height = height; - this.domNode.style.height = this._height + 'px'; + this.domNode.style.height = this._height; } - public setTop(top: number): void { + public setTop(_top: number | string): void { + const top = numberAsPixels(_top); if (this._top === top) { return; } this._top = top; - this.domNode.style.top = this._top + 'px'; + this.domNode.style.top = this._top; } - public unsetTop(): void { - if (this._top === -1) { - return; - } - this._top = -1; - this.domNode.style.top = ''; - } - - public setLeft(left: number): void { + public setLeft(_left: number | string): void { + const left = numberAsPixels(_left); if (this._left === left) { return; } this._left = left; - this.domNode.style.left = this._left + 'px'; + this.domNode.style.left = this._left; } - public setBottom(bottom: number): void { + public setBottom(_bottom: number | string): void { + const bottom = numberAsPixels(_bottom); if (this._bottom === bottom) { return; } this._bottom = bottom; - this.domNode.style.bottom = this._bottom + 'px'; + this.domNode.style.bottom = this._bottom; } - public setRight(right: number): void { + public setRight(_right: number | string): void { + const right = numberAsPixels(_right); if (this._right === right) { return; } this._right = right; - this.domNode.style.right = this._right + 'px'; + this.domNode.style.right = this._right; } public setFontFamily(fontFamily: string): void { @@ -114,12 +113,13 @@ export class FastDomNode { this.domNode.style.fontWeight = this._fontWeight; } - public setFontSize(fontSize: number): void { + public setFontSize(_fontSize: number | string): void { + const fontSize = numberAsPixels(_fontSize); if (this._fontSize === fontSize) { return; } this._fontSize = fontSize; - this.domNode.style.fontSize = this._fontSize + 'px'; + this.domNode.style.fontSize = this._fontSize; } public setFontStyle(fontStyle: string): void { @@ -146,20 +146,22 @@ export class FastDomNode { this.domNode.style.textDecoration = this._textDecoration; } - public setLineHeight(lineHeight: number): void { + public setLineHeight(_lineHeight: number | string): void { + const lineHeight = numberAsPixels(_lineHeight); if (this._lineHeight === lineHeight) { return; } this._lineHeight = lineHeight; - this.domNode.style.lineHeight = this._lineHeight + 'px'; + this.domNode.style.lineHeight = this._lineHeight; } - public setLetterSpacing(letterSpacing: number): void { + public setLetterSpacing(_letterSpacing: number | string): void { + const letterSpacing = numberAsPixels(_letterSpacing); if (this._letterSpacing === letterSpacing) { return; } this._letterSpacing = letterSpacing; - this.domNode.style.letterSpacing = this._letterSpacing + 'px'; + this.domNode.style.letterSpacing = this._letterSpacing; } public setClassName(className: string): void { @@ -256,6 +258,10 @@ export class FastDomNode { } } +function numberAsPixels(value: number | string): string { + return (typeof value === 'number' ? `${value}px` : value); +} + export function createFastDomNode(domNode: T): FastDomNode { return new FastDomNode(domNode); } diff --git a/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts b/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts index a8ffcdc8363..332bdb83728 100644 --- a/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts +++ b/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts @@ -122,7 +122,7 @@ export class ViewOverlayWidgets extends ViewPart { const domNode = widgetData.domNode; if (widgetData.preference === null) { - domNode.unsetTop(); + domNode.setTop(''); return; } From 41d5806cbf371ea363a27b0342538bf51557e454 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 8 Mar 2022 21:43:25 +0100 Subject: [PATCH 042/175] Fixes #144612: Avoid potentially unreliable `offsetHeight` --- .../browser/viewParts/contentWidgets/contentWidgets.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index 3ac19795247..056c24f5c73 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -469,8 +469,9 @@ class Widget { this._cachedDomNodeOffsetHeight = preferredDimensions.height; } else { const domNode = this.domNode.domNode; - this._cachedDomNodeOffsetWidth = domNode.offsetWidth; - this._cachedDomNodeOffsetHeight = domNode.offsetHeight; + const clientRect = domNode.getBoundingClientRect(); + this._cachedDomNodeOffsetWidth = Math.round(clientRect.width); + this._cachedDomNodeOffsetHeight = Math.round(clientRect.height); } } From eb6050d8a8c8263252f2db8250699c8a71454e25 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 14:32:58 -0800 Subject: [PATCH 043/175] Preserve path item details for JS/TS completions Fixes #144455 --- .../src/languageFeatures/completions.ts | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/completions.ts b/extensions/typescript-language-features/src/languageFeatures/completions.ts index 8cd15f148ea..e505e794279 100644 --- a/extensions/typescript-language-features/src/languageFeatures/completions.ts +++ b/extensions/typescript-language-features/src/languageFeatures/completions.ts @@ -7,6 +7,7 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import { Command, CommandManager } from '../commands/commandManager'; import type * as Proto from '../protocol'; +import protocol = require('../protocol'); import * as PConst from '../protocol.const'; import { ClientCapability, ITypeScriptServiceClient, ServerResponse } from '../typescriptService'; import API from '../utils/api'; @@ -134,18 +135,7 @@ class MyCompletionItem extends vscode.CompletionItem { this.kind = vscode.CompletionItemKind.Color; } - if (tsEntry.kind === PConst.Kind.script) { - for (const extModifier of PConst.KindModifiers.fileExtensionKindModifiers) { - if (kindModifiers.has(extModifier)) { - if (tsEntry.name.toLowerCase().endsWith(extModifier)) { - this.detail = tsEntry.name; - } else { - this.detail = tsEntry.name + extModifier; - } - break; - } - } - } + this.detail = getScriptKindDetails(tsEntry); } this.resolveRange(); @@ -206,7 +196,11 @@ class MyCompletionItem extends vscode.CompletionItem { const detail = response.body[0]; - this.detail = this.getDetails(client, detail); + const newItemDetails = this.getDetails(client, detail); + if (newItemDetails) { + this.detail = newItemDetails; + } + this.documentation = this.getDocumentation(client, detail, this.document.uri); const codeAction = this.getCodeActions(detail, filepath); @@ -253,6 +247,11 @@ class MyCompletionItem extends vscode.CompletionItem { ): string | undefined { const parts: string[] = []; + if (detail.kind === PConst.Kind.script) { + // details were already added + return undefined; + } + for (const action of detail.codeActions ?? []) { parts.push(action.description); } @@ -519,6 +518,24 @@ class MyCompletionItem extends vscode.CompletionItem { } } +function getScriptKindDetails(tsEntry: protocol.CompletionEntry,): string | undefined { + if (!tsEntry.kindModifiers || tsEntry.kind !== PConst.Kind.script) { + return; + } + + const kindModifiers = parseKindModifier(tsEntry.kindModifiers); + for (const extModifier of PConst.KindModifiers.fileExtensionKindModifiers) { + if (kindModifiers.has(extModifier)) { + if (tsEntry.name.toLowerCase().endsWith(extModifier)) { + return tsEntry.name; + } else { + return tsEntry.name + extModifier; + } + } + } + return undefined; +} + class CompletionAcceptedCommand implements Command { public static readonly ID = '_typescript.onCompletionAccepted'; From ec4bbaa5c4314f293542d491293a318fc2021b9d Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 8 Mar 2022 14:40:50 -0800 Subject: [PATCH 044/175] Adopt reduced motion in find (#144645) --- src/vs/editor/contrib/find/browser/findWidget.css | 4 ++++ .../contrib/codeEditor/browser/find/simpleFindWidget.css | 4 ++++ .../browser/contrib/find/notebookFindReplaceWidget.css | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/vs/editor/contrib/find/browser/findWidget.css b/src/vs/editor/contrib/find/browser/findWidget.css index f7ea6fb54ae..126110305bb 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.css +++ b/src/vs/editor/contrib/find/browser/findWidget.css @@ -16,6 +16,10 @@ transform: translateY(calc(-100% - 10px)); /* shadow (10px) */ } +.monaco-workbench.reduce-motion .monaco-editor .find-widget { + transition: transform 0ms linear; +} + .monaco-editor .find-widget textarea { margin: 0px; } diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.css b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.css index 2be494fd722..bdd496042ce 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.css +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.css @@ -27,6 +27,10 @@ transition: top 200ms linear; } +.monaco-workbench.reduce-motion .monaco-editor .find-widget { + transition: top 0ms linear; +} + .monaco-workbench .simple-find-part.visible { visibility: visible; } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.css b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.css index 5710f6c6e63..d9701c95197 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.css +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.css @@ -16,6 +16,10 @@ visibility: hidden; } +.monaco-workbench.reduce-motion .simple-fr-find-part-wrapper { + transition: top 0ms linear; +} + .monaco-workbench .notebookOverlay .simple-fr-find-part-wrapper.visible { z-index: 100; } From becce316b2f614f0820cf795e69a86ec6e286e6b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 14:47:46 -0800 Subject: [PATCH 045/175] Avoid re-parsing uri --- src/vs/code/electron-main/app.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 0443e77cd7d..21f6f2b27da 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -195,11 +195,9 @@ export class CodeApplication extends Disposable { return false; }; - const isAllowedWebviewRequest = (details: Electron.OnBeforeRequestListenerDetails): boolean => { - const url = URI.parse(details.url); - + const isAllowedWebviewRequest = (uri: URI, details: Electron.OnBeforeRequestListenerDetails): boolean => { // Only restrict top level page of webviews: index.html - if (url.path !== '/index.html') { + if (uri.path !== '/index.html') { return true; } @@ -222,9 +220,8 @@ export class CodeApplication extends Disposable { session.defaultSession.webRequest.onBeforeRequest((details, callback) => { const uri = URI.parse(details.url); - if (uri.scheme === Schemas.vscodeWebview) { - if (!isAllowedWebviewRequest(details)) { + if (!isAllowedWebviewRequest(uri, details)) { this.logService.error('Blocked vscode-webview request', details.url); return callback({ cancel: true }); } From 7f39250d49ff41c627b3244ac901454dda6d1dca Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 14:51:45 -0800 Subject: [PATCH 046/175] Remove extra spread --- extensions/markdown-language-features/src/features/preview.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/markdown-language-features/src/features/preview.ts b/extensions/markdown-language-features/src/features/preview.ts index dbe6890912f..f319e8ea364 100644 --- a/extensions/markdown-language-features/src/features/preview.ts +++ b/extensions/markdown-language-features/src/features/preview.ts @@ -425,7 +425,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { const srcs = new Set(containingImages.map(img => img.src)); // Delete stale file watchers. - for (const [src, watcher] of [...this._fileWatchersBySrc]) { + for (const [src, watcher] of this._fileWatchersBySrc) { if (!srcs.has(src)) { watcher.dispose(); this._fileWatchersBySrc.delete(src); From 664c94293aa8b37a4152831c1c947146d0a34b26 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 14:56:16 -0800 Subject: [PATCH 047/175] Update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8590d56e7d4..3919b901747 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.66.0", - "distro": "3256bc7614eaa43a118a42b69f686e5d43954113", + "distro": "991367d8d1e224ddc355f6d948da185c2f30b88e", "author": { "name": "Microsoft Corporation" }, From 6ecba6531fdaf2dd852b6e0b949844502e4f57dc Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 8 Mar 2022 15:34:33 -0800 Subject: [PATCH 048/175] Fix svg's not appearing in getting started --- .../browser/gettingStartedDetailsRenderer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts index 42a0700fb5d..b4d6e89f34a 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts @@ -186,7 +186,7 @@ export class GettingStartedDetailsRenderer { private readAndCacheSVGFile(path: URI): Promise { if (!this.svgCache.has(path)) { - this.svgCache.set(path, this.readContentsOfPath(path)); + this.svgCache.set(path, this.readContentsOfPath(path, false)); } return assertIsDefined(this.svgCache.get(path)); } @@ -200,10 +200,10 @@ export class GettingStartedDetailsRenderer { return assertIsDefined(this.mdCache.get(path)); } - private async readContentsOfPath(path: URI): Promise { + private async readContentsOfPath(path: URI, useModuleId = true): Promise { try { const moduleId = JSON.parse(path.query).moduleId; - if (moduleId) { + if (useModuleId && moduleId) { const contents = await new Promise(c => { require([moduleId], content => { c(content.default()); From 79d381f1dfb76ef8516e492e74861191300089be Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 15:30:44 -0800 Subject: [PATCH 049/175] Use vscode-uri instead of node's path This makes sure we handle other types of uris instead of assuming they are all file uris --- extensions/markdown-language-features/package.json | 5 +++-- .../src/features/documentLinkProvider.ts | 4 ++-- .../markdown-language-features/src/features/preview.ts | 9 +++++---- .../src/features/previewContentProvider.ts | 8 ++++---- .../src/util/openDocumentLink.ts | 6 +++--- extensions/markdown-language-features/src/util/path.ts | 8 -------- extensions/markdown-language-features/yarn.lock | 5 +++++ 7 files changed, 22 insertions(+), 23 deletions(-) delete mode 100644 extensions/markdown-language-features/src/util/path.ts diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index e46dfda8888..3f8a7abca2b 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -430,13 +430,14 @@ "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, "dependencies": { + "@vscode/extension-telemetry": "0.4.6", "dompurify": "^2.3.3", "highlight.js": "^10.4.1", "markdown-it": "^12.3.2", "markdown-it-front-matter": "^0.2.1", "morphdom": "^2.6.1", - "@vscode/extension-telemetry": "0.4.6", - "vscode-nls": "^5.0.0" + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.3" }, "devDependencies": { "@types/dompurify": "^2.3.1", diff --git a/extensions/markdown-language-features/src/features/documentLinkProvider.ts b/extensions/markdown-language-features/src/features/documentLinkProvider.ts index 86be23fdfb9..ee72de7ccb0 100644 --- a/extensions/markdown-language-features/src/features/documentLinkProvider.ts +++ b/extensions/markdown-language-features/src/features/documentLinkProvider.ts @@ -5,10 +5,10 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; +import * as uri from 'vscode-uri'; import { OpenDocumentLinkCommand } from '../commands/openDocumentLink'; import { MarkdownEngine } from '../markdownEngine'; import { getUriForLinkWithKnownExternalScheme, isOfScheme, Schemes } from '../util/links'; -import { dirname } from '../util/path'; const localize = nls.loadMessageBundle(); @@ -46,7 +46,7 @@ function parseLink( resourceUri = vscode.Uri.joinPath(root, tempUri.path); } } else { - const base = document.uri.with({ path: dirname(document.uri.fsPath) }); + const base = uri.Utils.dirname(document.uri); resourceUri = vscode.Uri.joinPath(base, tempUri.path); } } diff --git a/extensions/markdown-language-features/src/features/preview.ts b/extensions/markdown-language-features/src/features/preview.ts index f319e8ea364..371cc64899d 100644 --- a/extensions/markdown-language-features/src/features/preview.ts +++ b/extensions/markdown-language-features/src/features/preview.ts @@ -5,13 +5,13 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; +import * as uri from 'vscode-uri'; import { Logger } from '../logger'; import { MarkdownEngine } from '../markdownEngine'; import { MarkdownContributionProvider } from '../markdownExtensions'; import { Disposable } from '../util/dispose'; import { isMarkdownFile } from '../util/file'; import { openDocumentLink, resolveDocumentLink, resolveUriToMarkdownFile } from '../util/openDocumentLink'; -import * as path from '../util/path'; import { WebviewResourceProvider } from '../util/resources'; import { getVisibleLine, LastScrollLocation, TopmostLineMonitor } from '../util/topmostLineMonitor'; import { urlToUri } from '../util/url'; @@ -464,7 +464,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { baseRoots.push(...workspaceRoots); } } else { - baseRoots.push(this._resource.with({ path: path.dirname(this._resource.path) })); + baseRoots.push(uri.Utils.dirname(this._resource)); } return baseRoots; @@ -792,9 +792,10 @@ export class DynamicMarkdownPreview extends Disposable implements ManagedMarkdow } private static getPreviewTitle(resource: vscode.Uri, locked: boolean): string { + const resourceLabel = uri.Utils.basename(resource); return locked - ? localize('lockedPreviewTitle', '[Preview] {0}', path.basename(resource.fsPath)) - : localize('previewTitle', 'Preview {0}', path.basename(resource.fsPath)); + ? localize('lockedPreviewTitle', '[Preview] {0}', resourceLabel) + : localize('previewTitle', 'Preview {0}', resourceLabel); } public get position(): vscode.ViewColumn | undefined { diff --git a/extensions/markdown-language-features/src/features/previewContentProvider.ts b/extensions/markdown-language-features/src/features/previewContentProvider.ts index 172d37c838a..5c4a16072e2 100644 --- a/extensions/markdown-language-features/src/features/previewContentProvider.ts +++ b/extensions/markdown-language-features/src/features/previewContentProvider.ts @@ -5,11 +5,11 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; +import * as uri from 'vscode-uri'; import { Logger } from '../logger'; import { MarkdownEngine } from '../markdownEngine'; import { MarkdownContributionProvider } from '../markdownExtensions'; import { ContentSecurityPolicyArbiter, MarkdownPreviewSecurityLevel } from '../security'; -import { basename, dirname, isAbsolute, join } from '../util/path'; import { WebviewResourceProvider } from '../util/resources'; import { MarkdownPreviewConfiguration, MarkdownPreviewConfigurationManager } from './previewConfig'; @@ -128,7 +128,7 @@ export class MarkdownContentProvider { public provideFileNotFoundContent( resource: vscode.Uri, ): string { - const resourcePath = basename(resource.fsPath); + const resourcePath = uri.Utils.basename(resource); const body = localize('preview.notFound', '{0} cannot be found', resourcePath); return ` @@ -154,7 +154,7 @@ export class MarkdownContentProvider { } // Assume it must be a local file - if (isAbsolute(href)) { + if (href.startsWith('/') || /^[a-z]:\\/i.test(href)) { return resourceProvider.asWebviewUri(vscode.Uri.file(href)).toString(); } @@ -165,7 +165,7 @@ export class MarkdownContentProvider { } // Otherwise look relative to the markdown file - return resourceProvider.asWebviewUri(vscode.Uri.file(join(dirname(resource.fsPath), href))).toString(); + return resourceProvider.asWebviewUri(vscode.Uri.joinPath(uri.Utils.dirname(resource), href)).toString(); } private computeCustomStyleSheetIncludes(resourceProvider: WebviewResourceProvider, resource: vscode.Uri, config: MarkdownPreviewConfiguration): string { diff --git a/extensions/markdown-language-features/src/util/openDocumentLink.ts b/extensions/markdown-language-features/src/util/openDocumentLink.ts index 542cdbdb763..95a07e2d800 100644 --- a/extensions/markdown-language-features/src/util/openDocumentLink.ts +++ b/extensions/markdown-language-features/src/util/openDocumentLink.ts @@ -5,10 +5,10 @@ import * as path from 'path'; import * as vscode from 'vscode'; +import * as uri from 'vscode-uri'; import { MarkdownEngine } from '../markdownEngine'; import { TableOfContents } from '../tableOfContentsProvider'; import { isMarkdownFile } from './file'; -import { extname } from './path'; export interface OpenDocumentLinkArgs { readonly parts: vscode.Uri; @@ -53,7 +53,7 @@ export async function openDocumentLink(engine: MarkdownEngine, targetResource: v if (typeof targetResourceStat === 'undefined') { // We don't think the file exists. If it doesn't already have an extension, try tacking on a `.md` and using that instead - if (extname(targetResource.path) === '') { + if (uri.Utils.extname(targetResource) === '') { const dotMdResource = targetResource.with({ path: targetResource.path + '.md' }); try { const stat = await vscode.workspace.fs.stat(dotMdResource); @@ -140,7 +140,7 @@ export async function resolveUriToMarkdownFile(resource: vscode.Uri): Promise - -export { basename, dirname, extname, isAbsolute, join } from 'path'; diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index fea78e561e1..5ab0b05f690 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -126,3 +126,8 @@ vscode-nls@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840" integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA== + +vscode-uri@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.3.tgz#a95c1ce2e6f41b7549f86279d19f47951e4f4d84" + integrity sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA== From 2f48496d2b58d06168d49f97b7390a021936680a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 15:47:41 -0800 Subject: [PATCH 050/175] Switch the markdown preview script to use esbuild --- .../{esbuild.js => esbuild-notebook.js} | 0 .../esbuild-preview.js | 33 +++++++++++++++++++ .../markdown-language-features/package.json | 4 +-- .../webpack.config.js | 30 ----------------- 4 files changed, 35 insertions(+), 32 deletions(-) rename extensions/markdown-language-features/{esbuild.js => esbuild-notebook.js} (100%) create mode 100644 extensions/markdown-language-features/esbuild-preview.js delete mode 100644 extensions/markdown-language-features/webpack.config.js diff --git a/extensions/markdown-language-features/esbuild.js b/extensions/markdown-language-features/esbuild-notebook.js similarity index 100% rename from extensions/markdown-language-features/esbuild.js rename to extensions/markdown-language-features/esbuild-notebook.js diff --git a/extensions/markdown-language-features/esbuild-preview.js b/extensions/markdown-language-features/esbuild-preview.js new file mode 100644 index 00000000000..692e45c9252 --- /dev/null +++ b/extensions/markdown-language-features/esbuild-preview.js @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const path = require('path'); +const esbuild = require('esbuild'); + +const args = process.argv.slice(2); + +const isWatch = args.indexOf('--watch') >= 0; + +let outputRoot = __dirname; +const outputRootIndex = args.indexOf('--outputRoot'); +if (outputRootIndex >= 0) { + outputRoot = args[outputRootIndex + 1]; +} + +const outDir = path.join(outputRoot, 'media'); + +esbuild.build({ + entryPoints: [ + path.join(__dirname, 'preview-src', 'index.ts'), + path.join(__dirname, 'preview-src', 'pre'), + ], + bundle: true, + minify: true, + sourcemap: false, + format: 'esm', + outdir: outDir, + platform: 'browser', + target: ['es2020'], + incremental: isWatch, +}).catch(() => process.exit(1)); diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 3f8a7abca2b..7f06a4cedd1 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -424,8 +424,8 @@ "watch": "npm run build-preview && gulp watch-extension:markdown-language-features", "vscode:prepublish": "npm run build-ext && npm run build-preview", "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown-language-features ./tsconfig.json", - "build-preview": "npx webpack-cli --mode production", - "build-notebook": "node ./esbuild", + "build-notebook": "node ./esbuild-notebook", + "build-preview": "node ./esbuild-preview", "compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none", "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, diff --git a/extensions/markdown-language-features/webpack.config.js b/extensions/markdown-language-features/webpack.config.js deleted file mode 100644 index 76012d15be0..00000000000 --- a/extensions/markdown-language-features/webpack.config.js +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -const path = require('path'); - -module.exports = { - context: path.resolve(__dirname), - mode: 'production', - entry: { - index: './preview-src/index.ts', - pre: './preview-src/pre.ts', - }, - module: { - rules: [ - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/ - } - ] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'] - }, - output: { - filename: '[name].js', - path: path.resolve(__dirname, 'media') - } -}; From e65a786a92f5e3f5753e4fc694b475ada20d7335 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 16:09:23 -0800 Subject: [PATCH 051/175] Fix build script to use esbuild --- build/lib/extensions.js | 4 ++-- build/lib/extensions.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/lib/extensions.js b/build/lib/extensions.js index c4ee9d010f3..76d2b8844e5 100644 --- a/build/lib/extensions.js +++ b/build/lib/extensions.js @@ -355,12 +355,12 @@ exports.translatePackageJSON = translatePackageJSON; const extensionsPath = path.join(root, 'extensions'); // Additional projects to webpack. These typically build code for webviews const webpackMediaConfigFiles = [ - 'markdown-language-features/webpack.config.js', 'simple-browser/webpack.config.js', ]; // Additional projects to run esbuild on. These typically build code for webviews const esbuildMediaScripts = [ - 'markdown-language-features/esbuild.js', + 'markdown-language-features/esbuild-notebook.js', + 'markdown-language-features/esbuild-preview.js', 'markdown-math/esbuild.js', 'notebook-renderers/esbuild.js' ]; diff --git a/build/lib/extensions.ts b/build/lib/extensions.ts index 7303b3b151a..405404992de 100644 --- a/build/lib/extensions.ts +++ b/build/lib/extensions.ts @@ -436,13 +436,13 @@ const extensionsPath = path.join(root, 'extensions'); // Additional projects to webpack. These typically build code for webviews const webpackMediaConfigFiles = [ - 'markdown-language-features/webpack.config.js', 'simple-browser/webpack.config.js', ]; // Additional projects to run esbuild on. These typically build code for webviews const esbuildMediaScripts = [ - 'markdown-language-features/esbuild.js', + 'markdown-language-features/esbuild-notebook.js', + 'markdown-language-features/esbuild-preview.js', 'markdown-math/esbuild.js', 'notebook-renderers/esbuild.js' ]; From fb6cf37ea97976926638554d0e454c4b4b394237 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 16:23:14 -0800 Subject: [PATCH 052/175] Move simple-browser to use esbuild for webview scripts --- build/lib/extensions.js | 23 +++------- build/lib/extensions.ts | 24 +++------- .../markdown-language-features/yarn.lock | 8 ++-- extensions/simple-browser/esbuild-preview.js | 41 +++++++++++++++++ extensions/simple-browser/package.json | 3 +- extensions/simple-browser/webpack.config.js | 45 ------------------- 6 files changed, 58 insertions(+), 86 deletions(-) create mode 100644 extensions/simple-browser/esbuild-preview.js delete mode 100644 extensions/simple-browser/webpack.config.js diff --git a/build/lib/extensions.js b/build/lib/extensions.js index 76d2b8844e5..99ebc6dee2b 100644 --- a/build/lib/extensions.js +++ b/build/lib/extensions.js @@ -353,16 +353,13 @@ function translatePackageJSON(packageJSON, packageNLSPath) { } exports.translatePackageJSON = translatePackageJSON; const extensionsPath = path.join(root, 'extensions'); -// Additional projects to webpack. These typically build code for webviews -const webpackMediaConfigFiles = [ - 'simple-browser/webpack.config.js', -]; // Additional projects to run esbuild on. These typically build code for webviews const esbuildMediaScripts = [ 'markdown-language-features/esbuild-notebook.js', 'markdown-language-features/esbuild-preview.js', 'markdown-math/esbuild.js', - 'notebook-renderers/esbuild.js' + 'notebook-renderers/esbuild.js', + 'simple-browser/esbuild-preview.js', ]; async function webpackExtensions(taskName, isWatch, webpackConfigLocations) { const webpack = require('webpack'); @@ -468,17 +465,9 @@ async function esbuildExtensions(taskName, isWatch, scripts) { return Promise.all(tasks); } async function buildExtensionMedia(isWatch, outputRoot) { - return Promise.all([ - webpackExtensions('webpacking extension media', isWatch, webpackMediaConfigFiles.map(p => { - return { - configPath: path.join(extensionsPath, p), - outputRoot: outputRoot ? path.join(root, outputRoot, path.dirname(p)) : undefined - }; - })), - esbuildExtensions('esbuilding extension media', isWatch, esbuildMediaScripts.map(p => ({ - script: path.join(extensionsPath, p), - outputRoot: outputRoot ? path.join(root, outputRoot, path.dirname(p)) : undefined - }))), - ]); + return esbuildExtensions('esbuilding extension media', isWatch, esbuildMediaScripts.map(p => ({ + script: path.join(extensionsPath, p), + outputRoot: outputRoot ? path.join(root, outputRoot, path.dirname(p)) : undefined + }))); } exports.buildExtensionMedia = buildExtensionMedia; diff --git a/build/lib/extensions.ts b/build/lib/extensions.ts index 405404992de..aeea8e68852 100644 --- a/build/lib/extensions.ts +++ b/build/lib/extensions.ts @@ -434,17 +434,13 @@ export function translatePackageJSON(packageJSON: string, packageNLSPath: string const extensionsPath = path.join(root, 'extensions'); -// Additional projects to webpack. These typically build code for webviews -const webpackMediaConfigFiles = [ - 'simple-browser/webpack.config.js', -]; - // Additional projects to run esbuild on. These typically build code for webviews const esbuildMediaScripts = [ 'markdown-language-features/esbuild-notebook.js', 'markdown-language-features/esbuild-preview.js', 'markdown-math/esbuild.js', - 'notebook-renderers/esbuild.js' + 'notebook-renderers/esbuild.js', + 'simple-browser/esbuild-preview.js', ]; export async function webpackExtensions(taskName: string, isWatch: boolean, webpackConfigLocations: { configPath: string; outputRoot?: string }[]) { @@ -554,16 +550,8 @@ async function esbuildExtensions(taskName: string, isWatch: boolean, scripts: { } export async function buildExtensionMedia(isWatch: boolean, outputRoot?: string) { - return Promise.all([ - webpackExtensions('webpacking extension media', isWatch, webpackMediaConfigFiles.map(p => { - return { - configPath: path.join(extensionsPath, p), - outputRoot: outputRoot ? path.join(root, outputRoot, path.dirname(p)) : undefined - }; - })), - esbuildExtensions('esbuilding extension media', isWatch, esbuildMediaScripts.map(p => ({ - script: path.join(extensionsPath, p), - outputRoot: outputRoot ? path.join(root, outputRoot, path.dirname(p)) : undefined - }))), - ]); + return esbuildExtensions('esbuilding extension media', isWatch, esbuildMediaScripts.map(p => ({ + script: path.join(extensionsPath, p), + outputRoot: outputRoot ? path.join(root, outputRoot, path.dirname(p)) : undefined + }))); } diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 5ab0b05f690..ee1ee244500 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -74,10 +74,10 @@ entities@~2.1.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== -highlight.js@^10.4.1: - version "10.4.1" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.4.1.tgz#d48fbcf4a9971c4361b3f95f302747afe19dbad0" - integrity sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg== +highlight.js@^11.4.0: + version "11.4.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.4.0.tgz#34ceadd49e1596ee5aba3d99346cdfd4845ee05a" + integrity sha512-nawlpCBCSASs7EdvZOYOYVkJpGmAOKMYZgZtUqSRqodZE0GRVcFKwo1RcpeOemqh9hyttTdd5wDBwHkuSyUfnA== linkify-it@^3.0.1: version "3.0.3" diff --git a/extensions/simple-browser/esbuild-preview.js b/extensions/simple-browser/esbuild-preview.js new file mode 100644 index 00000000000..cf278788b9b --- /dev/null +++ b/extensions/simple-browser/esbuild-preview.js @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const path = require('path'); +const fs = require('fs'); +const esbuild = require('esbuild'); + +const args = process.argv.slice(2); + +const isWatch = args.indexOf('--watch') >= 0; + +let outputRoot = __dirname; +const outputRootIndex = args.indexOf('--outputRoot'); +if (outputRootIndex >= 0) { + outputRoot = args[outputRootIndex + 1]; +} + +const outDir = path.join(outputRoot, 'media'); + +fs.copyFileSync( + path.join(__dirname, 'node_modules', 'vscode-codicons', 'dist', 'codicon.css'), + path.join(outDir, 'codicon.css')); + +fs.copyFileSync( + path.join(__dirname, 'node_modules', 'vscode-codicons', 'dist', 'codicon.ttf'), + path.join(outDir, 'codicon.ttf')); + +esbuild.build({ + entryPoints: [ + path.join(__dirname, 'preview-src', 'index.ts') + ], + bundle: true, + minify: true, + sourcemap: false, + format: 'esm', + outdir: outDir, + platform: 'browser', + target: ['es2020'], + incremental: isWatch, +}).catch(() => process.exit(1)); diff --git a/extensions/simple-browser/package.json b/extensions/simple-browser/package.json index 6ce11704fa4..3e3424e10cb 100644 --- a/extensions/simple-browser/package.json +++ b/extensions/simple-browser/package.json @@ -62,8 +62,7 @@ "watch": "npm run build-preview && gulp watch-extension:markdown-language-features", "vscode:prepublish": "npm run build-ext && npm run build-preview", "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown-language-features ./tsconfig.json", - "build-preview": "npx webpack-cli --mode development", - "build-preview-production": "npx webpack-cli --mode production", + "build-preview": "node ./esbuild-preview", "compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none", "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, diff --git a/extensions/simple-browser/webpack.config.js b/extensions/simple-browser/webpack.config.js deleted file mode 100644 index fbdf2a6c597..00000000000 --- a/extensions/simple-browser/webpack.config.js +++ /dev/null @@ -1,45 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -const path = require('path'); -const CopyPlugin = require('copy-webpack-plugin'); - -module.exports = { - context: path.resolve(__dirname), - entry: { - index: './preview-src/index.ts', - }, - mode: 'production', - module: { - rules: [ - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/ - } - ] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'] - }, - output: { - filename: '[name].js', - path: path.resolve(__dirname, 'media') - }, - plugins: [ - // @ts-ignore - new CopyPlugin({ - patterns: [ - { - from: './node_modules/vscode-codicons/dist/codicon.css', - to: 'codicon.css' - }, - { - from: './node_modules/vscode-codicons/dist/codicon.ttf', - to: 'codicon.ttf' - }, - ], - }), - ] -}; From 78e1b3cca86e077027721284da2ca8a3f5b0603a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 16:27:42 -0800 Subject: [PATCH 053/175] Bump highlight JS version --- extensions/markdown-language-features/package.json | 2 +- .../markdown-language-features/src/markdownEngine.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 7f06a4cedd1..e7b05bd588f 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -432,7 +432,7 @@ "dependencies": { "@vscode/extension-telemetry": "0.4.6", "dompurify": "^2.3.3", - "highlight.js": "^10.4.1", + "highlight.js": "^11.4.0", "markdown-it": "^12.3.2", "markdown-it-front-matter": "^0.2.1", "morphdom": "^2.6.1", diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index 72bdba51fcb..e49122c03be 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -384,14 +384,18 @@ export class MarkdownEngine { } async function getMarkdownOptions(md: () => MarkdownIt): Promise { - const hljs = await import('highlight.js'); + const hljs = (await import('highlight.js')).default; return { html: true, highlight: (str: string, lang?: string) => { lang = normalizeHighlightLang(lang); if (lang && hljs.getLanguage(lang)) { try { - return `
${hljs.highlight(lang, str, true).value}
`; + const highlighted = hljs.highlight(str, { + language: lang, + ignoreIllegals: true, + }).value; + return `
${highlighted}
`; } catch (error) { } } From 55243d79f745e56a7165221c8dec147380e11f46 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 8 Mar 2022 16:32:01 -0800 Subject: [PATCH 054/175] Remove legacy expand mode --- .../files/browser/views/explorerView.ts | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index 09ad38d8d62..c109d5648b8 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -692,31 +692,18 @@ export class ExplorerView extends ViewPane implements IExplorerView { if (!previousInput && input.length === 1 && this.configurationService.getValue().explorer.expandSingleFolderWorkspaces) { await this.tree.expand(input[0]).catch(() => { }); } - // TODO@jkearl: Hidden & Probably not needed, remove eventaully. - const useOldStyle = this.configurationService.getValue('explorer.legacyWorkspaceFolderExpandMode'); - if (useOldStyle) { - if (Array.isArray(previousInput) && previousInput.length < input.length) { - // Roots added to the explorer -> expand them. - await Promise.all(input.slice(previousInput.length).map(async item => { + if (Array.isArray(previousInput)) { + const previousRoots = new ResourceMap(); + previousInput.forEach(previousRoot => previousRoots.set(previousRoot.resource, true)); + + // Roots added to the explorer -> expand them. + await Promise.all(input.map(async item => { + if (!previousRoots.has(item.resource)) { try { await this.tree.expand(item); } catch (e) { } - })); - } - } else { - if (Array.isArray(previousInput)) { - const previousRoots = new ResourceMap(); - previousInput.forEach(previousRoot => previousRoots.set(previousRoot.resource, true)); - - // Roots added to the explorer -> expand them. - await Promise.all(input.map(async item => { - if (!previousRoots.has(item.resource)) { - try { - await this.tree.expand(item); - } catch (e) { } - } - })); - } + } + })); } } if (initialInputSetup) { From 2076178ec0844f6adfba63221573a1e0bbcdb743 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Wed, 9 Mar 2022 01:41:49 +0100 Subject: [PATCH 055/175] Adds token to make 403s less likely when downloading ripgrep. (#144686) --- build/azure-pipelines/linux/product-build-linux-server.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/azure-pipelines/linux/product-build-linux-server.yml b/build/azure-pipelines/linux/product-build-linux-server.yml index cbda3510d62..ecea0861ee6 100644 --- a/build/azure-pipelines/linux/product-build-linux-server.yml +++ b/build/azure-pipelines/linux/product-build-linux-server.yml @@ -48,6 +48,8 @@ steps: echo "Yarn failed $i, trying again..." done displayName: Install dependencies + env: + GITHUB_TOKEN: "$(github-distro-mixin-password)" condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64')) - script: | From 6be9a400739c529a96d39a200a16e5253e10dd2b Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:48:27 -0800 Subject: [PATCH 056/175] Update src/vs/platform/terminal/node/terminalProcess.ts Co-authored-by: Megan Rogge --- src/vs/platform/terminal/node/terminalProcess.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts index 1c89b047438..23ab10777cb 100644 --- a/src/vs/platform/terminal/node/terminalProcess.ts +++ b/src/vs/platform/terminal/node/terminalProcess.ts @@ -121,12 +121,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess get exitMessage(): string | undefined { return this._exitMessage; } get currentTitle(): string { return this._windowsShellHelper?.shellTitle || this._currentTitle; } - get shellType(): TerminalShellType { - if (isWindows) { - return this._windowsShellHelper?.shellType; - } - return posixShellTypeMap.get(this._currentTitle); - } + get shellType(): TerminalShellType { return isWindows ? this._windowsShellHelper?.shellType : posixShellTypeMap.get(this._currentTitle); } private readonly _onProcessData = this._register(new Emitter()); readonly onProcessData = this._onProcessData.event; From c811becbbbe37dafa5ffa9a261079c19daf21d81 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 8 Mar 2022 16:59:33 -0800 Subject: [PATCH 057/175] Improve Nest Rendering - Force nests to render with a twistie - Resolve alignment issues by hiding nested parent icon to match folders Fixes #142938, #141428, #141359 --- .../files/browser/views/explorerViewer.ts | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index 59355b50c84..a7e6740273c 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -365,28 +365,52 @@ export class FilesRenderer implements ICompressibleTreeRenderer { + + const setResourceData = () => { + const theme = this.themeService.getFileIconTheme(); + // Dont render file icons for nest parents unless folders have both chevrons and icons, otherwise alignment breaks + const hideNestParentFileIcons = theme.hidesExplorerArrows || !theme.hasFolderIcons; + + templateData.label.setResource({ resource: stat.resource, name: label }, { + fileKind: stat.isRoot ? FileKind.ROOT_FOLDER : stat.isDirectory ? FileKind.FOLDER : FileKind.FILE, + extraClasses, + hideIcon: stat.hasNests && hideNestParentFileIcons, + fileDecorations: this.config.explorer.decorations, + matches: createMatches(filterData), + separator: this.labelService.getSeparator(stat.resource.scheme, stat.resource.authority), + domId + }); + }; + + elementDisposables.add(this.themeService.onDidFileIconThemeChange(() => setResourceData())); + setResourceData(); + + elementDisposables.add(templateData.label.onDidRender(() => { try { this.updateWidth(stat); } catch (e) { // noop since the element might no longer be in the tree, no update of width necessary } - }); + })); + + return elementDisposables; } private renderInputBox(container: HTMLElement, stat: ExplorerItem, editableData: IEditableData): IDisposable { From c354462e6662c095ec03b62766a5ad6b110c1274 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 17:40:59 -0800 Subject: [PATCH 058/175] Format file --- src/vs/platform/terminal/node/terminalProcess.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts index 23ab10777cb..a7c1d444d4e 100644 --- a/src/vs/platform/terminal/node/terminalProcess.ts +++ b/src/vs/platform/terminal/node/terminalProcess.ts @@ -121,7 +121,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess get exitMessage(): string | undefined { return this._exitMessage; } get currentTitle(): string { return this._windowsShellHelper?.shellTitle || this._currentTitle; } - get shellType(): TerminalShellType { return isWindows ? this._windowsShellHelper?.shellType : posixShellTypeMap.get(this._currentTitle); } + get shellType(): TerminalShellType { return isWindows ? this._windowsShellHelper?.shellType : posixShellTypeMap.get(this._currentTitle); } private readonly _onProcessData = this._register(new Emitter()); readonly onProcessData = this._onProcessData.event; From acd19fbc30f922f0e5071b243fbfc6a942ac5a64 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 17:44:15 -0800 Subject: [PATCH 059/175] Add notebook-renderer to hygiene filter --- build/filters.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/filters.js b/build/filters.js index 87ded512d05..f462566d0f4 100644 --- a/build/filters.js +++ b/build/filters.js @@ -121,9 +121,12 @@ module.exports.indentationFilter = [ '!**/Dockerfile.*', '!**/*.Dockerfile', '!**/*.dockerfile', + + // except for built files '!extensions/markdown-language-features/media/*.js', '!extensions/markdown-language-features/notebook-out/*.js', '!extensions/markdown-math/notebook-out/*.js', + '!extensions/notebook-renderers/renderer-out/*.js', '!extensions/simple-browser/media/*.js', ]; From eaf352e6d1dc3b9183cb17641260b8bbd35c0702 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 17:54:16 -0800 Subject: [PATCH 060/175] Hook up watch properly for extension build scripts --- extensions/markdown-language-features/esbuild-notebook.js | 1 + extensions/markdown-language-features/esbuild-preview.js | 1 + extensions/markdown-math/esbuild.js | 1 + extensions/notebook-renderers/esbuild.js | 1 + extensions/simple-browser/esbuild-preview.js | 1 + 5 files changed, 5 insertions(+) diff --git a/extensions/markdown-language-features/esbuild-notebook.js b/extensions/markdown-language-features/esbuild-notebook.js index 202e4677042..bd5a325438d 100644 --- a/extensions/markdown-language-features/esbuild-notebook.js +++ b/extensions/markdown-language-features/esbuild-notebook.js @@ -28,5 +28,6 @@ esbuild.build({ outdir: outDir, platform: 'browser', target: ['es2020'], + watch: isWatch, incremental: isWatch, }).catch(() => process.exit(1)); diff --git a/extensions/markdown-language-features/esbuild-preview.js b/extensions/markdown-language-features/esbuild-preview.js index 692e45c9252..727353c6e44 100644 --- a/extensions/markdown-language-features/esbuild-preview.js +++ b/extensions/markdown-language-features/esbuild-preview.js @@ -29,5 +29,6 @@ esbuild.build({ outdir: outDir, platform: 'browser', target: ['es2020'], + watch: isWatch, incremental: isWatch, }).catch(() => process.exit(1)); diff --git a/extensions/markdown-math/esbuild.js b/extensions/markdown-math/esbuild.js index ab5ee7b75c3..dd94d2e1eed 100644 --- a/extensions/markdown-math/esbuild.js +++ b/extensions/markdown-math/esbuild.js @@ -30,6 +30,7 @@ esbuild.build({ outdir: outDir, platform: 'browser', target: ['es2020'], + watch: isWatch, incremental: isWatch, }).catch(() => process.exit(1)); diff --git a/extensions/notebook-renderers/esbuild.js b/extensions/notebook-renderers/esbuild.js index 5b54e668b3b..11a04a0a982 100644 --- a/extensions/notebook-renderers/esbuild.js +++ b/extensions/notebook-renderers/esbuild.js @@ -28,5 +28,6 @@ esbuild.build({ outdir: outDir, platform: 'browser', target: ['es2020'], + watch: isWatch, incremental: isWatch, }).catch(() => process.exit(1)); diff --git a/extensions/simple-browser/esbuild-preview.js b/extensions/simple-browser/esbuild-preview.js index cf278788b9b..d6447532501 100644 --- a/extensions/simple-browser/esbuild-preview.js +++ b/extensions/simple-browser/esbuild-preview.js @@ -37,5 +37,6 @@ esbuild.build({ outdir: outDir, platform: 'browser', target: ['es2020'], + watch: isWatch, incremental: isWatch, }).catch(() => process.exit(1)); From bd36b7d6a3ef41ef7b5a3cbcd01dbd859ed70a50 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 18:08:47 -0800 Subject: [PATCH 061/175] Make sure we set html on markdown preview when it is not visible Fixes #138630 If the webview does not exist, we need to update the html on it instead of posting a message to it. This makes sure the correct content is shown when the webview is created again This also removes a previous workaround for this issue that I no longer believe is required --- .../src/features/preview.ts | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/extensions/markdown-language-features/src/features/preview.ts b/extensions/markdown-language-features/src/features/preview.ts index 371cc64899d..3b3f1fe6c8c 100644 --- a/extensions/markdown-language-features/src/features/preview.ts +++ b/extensions/markdown-language-features/src/features/preview.ts @@ -179,31 +179,6 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { } })); - this._register(this._webviewPanel.onDidChangeViewState(async () => { - if (this._disposed) { - return; - } - - if (this._webviewPanel.active) { - let document: vscode.TextDocument; - try { - document = await vscode.workspace.openTextDocument(this._resource); - } catch { - return; - } - - if (this._disposed) { - return; - } - - const content = await this._contentProvider.provideTextDocumentContent(document, this, this._previewConfigurations, this.line, this.state); - if (!this._webviewPanel.active && !this._disposed) { - // Update the html so we can show it properly when restoring it - this._webviewPanel.webview.html = content.html; - } - } - })); - this._register(this._webviewPanel.webview.onDidReceiveMessage((e: CacheImageSizesMessage | RevealLineMessage | DidClickMessage | ClickLinkMessage | ShowPreviewSecuritySelectorMessage | PreviewStyleLoadErrorMessage) => { if (e.source !== this._resource.toString()) { return; @@ -343,7 +318,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { return; } - const shouldReloadPage = forceUpdate || !this.currentVersion || this.currentVersion.resource.toString() !== pendingVersion.resource.toString(); + const shouldReloadPage = forceUpdate || !this.currentVersion || this.currentVersion.resource.toString() !== pendingVersion.resource.toString() || !this._webviewPanel.visible; this.currentVersion = pendingVersion; const content = await (shouldReloadPage From ebce8177871092930240af20da73a4bafff7e472 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 8 Mar 2022 18:15:21 -0800 Subject: [PATCH 062/175] Show CompletionItem detail in debug console suggest widget Fix #142124 --- src/vs/workbench/contrib/debug/browser/repl.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 30bc1358e30..f8b5d4466f3 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -261,6 +261,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { suggestions.push({ label: item.label, insertText, + detail: item.detail, kind: CompletionItemKinds.fromString(item.type || 'property'), filterText: (item.start && item.length) ? text.substring(item.start, item.start + item.length).concat(item.label) : undefined, range: computeRange(item.length || overwriteBefore), From 886ab068601d62b51933103da51cc4995338b346 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 18:45:04 -0800 Subject: [PATCH 063/175] Try to have more explicit error when we don't have a server Fixes #143032 This change removes a call that would automatically restart the TS server when invoking a command. Instead we now return a `NoServer` response When this happens, the server still should be restarted. This change stops us from logging a large number of errors when we get into this state where the server has crashed too many times and we no longer want to automatically restart it --- .../src/typescriptService.ts | 4 +- .../src/typescriptServiceClient.ts | 67 +++++++++---------- 2 files changed, 33 insertions(+), 38 deletions(-) diff --git a/extensions/typescript-language-features/src/typescriptService.ts b/extensions/typescript-language-features/src/typescriptService.ts index f80ff04f61f..616131b26d8 100644 --- a/extensions/typescript-language-features/src/typescriptService.ts +++ b/extensions/typescript-language-features/src/typescriptService.ts @@ -30,7 +30,9 @@ export namespace ServerResponse { export const NoContent = { type: 'noContent' } as const; - export type Response = T | Cancelled | typeof NoContent; + export const NoServer = { type: 'noServer' } as const; + + export type Response = T | Cancelled | typeof NoContent | typeof NoServer; } interface StandardTsServerRequests { diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index 13a584d9b18..2fd3f93b74d 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -340,20 +340,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType this.telemetryReporter.logTelemetry(eventName, properties); } - private service(): ServerState.Running { - if (this.serverState.type === ServerState.Type.Running) { - return this.serverState; - } - if (this.serverState.type === ServerState.Type.Errored) { - throw this.serverState.error; - } - const newState = this.startService(); - if (newState.type === ServerState.Type.Running) { - return newState; - } - throw new Error(`Could not create TS service. Service state:${JSON.stringify(newState)}`); - } - public ensureServiceStarted() { if (this.serverState.type !== ServerState.Type.Running) { this.startService(); @@ -767,31 +753,34 @@ export default class TypeScriptServiceClient extends Disposable implements IType } public execute(command: keyof TypeScriptRequests, args: any, token: vscode.CancellationToken, config?: ExecConfig): Promise> { - let executions: Array> | undefined>; + let executions: Array> | undefined> | undefined; if (config?.cancelOnResourceChange) { - const runningServerState = this.service(); + const runningServerState = this.serverState; + if (runningServerState.type === ServerState.Type.Running) { + const source = new vscode.CancellationTokenSource(); + token.onCancellationRequested(() => source.cancel()); - const source = new vscode.CancellationTokenSource(); - token.onCancellationRequested(() => source.cancel()); + const inFlight: ToCancelOnResourceChanged = { + resource: config.cancelOnResourceChange, + cancel: () => source.cancel(), + }; + runningServerState.toCancelOnResourceChange.add(inFlight); - const inFlight: ToCancelOnResourceChanged = { - resource: config.cancelOnResourceChange, - cancel: () => source.cancel(), - }; - runningServerState.toCancelOnResourceChange.add(inFlight); + executions = this.executeImpl(command, args, { + isAsync: false, + token: source.token, + expectsResult: true, + ...config, + }); + executions[0]!.finally(() => { + runningServerState.toCancelOnResourceChange.delete(inFlight); + source.dispose(); + }); + } + } - executions = this.executeImpl(command, args, { - isAsync: false, - token: source.token, - expectsResult: true, - ...config, - }); - executions[0]!.finally(() => { - runningServerState.toCancelOnResourceChange.delete(inFlight); - source.dispose(); - }); - } else { + if (!executions) { executions = this.executeImpl(command, args, { isAsync: false, token, @@ -831,9 +820,13 @@ export default class TypeScriptServiceClient extends Disposable implements IType } private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean; token?: vscode.CancellationToken; expectsResult: boolean; lowPriority?: boolean; requireSemantic?: boolean }): Array> | undefined> { - this.bufferSyncSupport.beforeCommand(command); - const runningServerState = this.service(); - return runningServerState.server.executeImpl(command, args, executeInfo); + const serverState = this.serverState; + if (serverState.type === ServerState.Type.Running) { + this.bufferSyncSupport.beforeCommand(command); + return serverState.server.executeImpl(command, args, executeInfo); + } else { + return [Promise.resolve(ServerResponse.NoServer)]; + } } public interruptGetErr(f: () => R): R { From 9d41c706c69758348ac5ec86cae86adf61b1ff49 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Mar 2022 18:48:31 -0800 Subject: [PATCH 064/175] Allow manually restarting TS Server even if it has crashed too many times Currently if the server crashes too many times, the user has to restart VS Code. It's possible the user could fix something (such as a bad plugin) and then run this command to just restart the server without needing to restart the entire editor --- .../src/commands/restartTsServer.ts | 2 +- .../src/typescriptServiceClient.ts | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/extensions/typescript-language-features/src/commands/restartTsServer.ts b/extensions/typescript-language-features/src/commands/restartTsServer.ts index 77dcae870ee..a6cc47758a8 100644 --- a/extensions/typescript-language-features/src/commands/restartTsServer.ts +++ b/extensions/typescript-language-features/src/commands/restartTsServer.ts @@ -15,6 +15,6 @@ export class RestartTsServerCommand implements Command { ) { } public execute() { - this.lazyClientHost.value.serviceClient.restartTsServer(); + this.lazyClientHost.value.serviceClient.restartTsServer(true); } } diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index 2fd3f93b74d..172a61301fd 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -280,13 +280,20 @@ export default class TypeScriptServiceClient extends Disposable implements IType this.loadingIndicator.reset(); } - public restartTsServer(): void { + public restartTsServer(fromUserAction = false): void { if (this.serverState.type === ServerState.Type.Running) { this.info('Killing TS Server'); this.isRestarting = true; this.serverState.server.kill(); } + if (fromUserAction) { + // Reset crash trackers + this.hasServerFatallyCrashedTooManyTimes = false; + this.numberRestarts = 0; + this.lastStart = Date.now(); + } + this.serverState = this.startService(true); } From ad00660de062f771d3645204109629c1093e322e Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 8 Mar 2022 19:53:12 -0800 Subject: [PATCH 065/175] Revert "Improve Nest Rendering" Concerns were raised over the removing of file icons entirely. Will be out for next few days so reverting this to explore more when I get back. This reverts commit c811becbbbe37dafa5ffa9a261079c19daf21d81. --- .../files/browser/views/explorerViewer.ts | 44 +++++-------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index a7e6740273c..59355b50c84 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -365,52 +365,28 @@ export class FilesRenderer implements ICompressibleTreeRenderer { - const theme = this.themeService.getFileIconTheme(); - // Dont render file icons for nest parents unless folders have both chevrons and icons, otherwise alignment breaks - const hideNestParentFileIcons = theme.hidesExplorerArrows || !theme.hasFolderIcons; - - templateData.label.setResource({ resource: stat.resource, name: label }, { - fileKind: stat.isRoot ? FileKind.ROOT_FOLDER : stat.isDirectory ? FileKind.FOLDER : FileKind.FILE, - extraClasses, - hideIcon: stat.hasNests && hideNestParentFileIcons, - fileDecorations: this.config.explorer.decorations, - matches: createMatches(filterData), - separator: this.labelService.getSeparator(stat.resource.scheme, stat.resource.authority), - domId - }); - }; - - elementDisposables.add(this.themeService.onDidFileIconThemeChange(() => setResourceData())); - setResourceData(); - - elementDisposables.add(templateData.label.onDidRender(() => { + return templateData.label.onDidRender(() => { try { this.updateWidth(stat); } catch (e) { // noop since the element might no longer be in the tree, no update of width necessary } - })); - - return elementDisposables; + }); } private renderInputBox(container: HTMLElement, stat: ExplorerItem, editableData: IEditableData): IDisposable { From 0a138fbe26e6147392867fb7df8c794d8ef37777 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Wed, 9 Mar 2022 08:35:30 +0100 Subject: [PATCH 066/175] Support @prerelease (#143540) --- .../schemas/devContainer.schema.generated.json | 10 +++++----- .../schemas/devContainer.schema.src.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/configuration-editing/schemas/devContainer.schema.generated.json b/extensions/configuration-editing/schemas/devContainer.schema.generated.json index 936ea50ce7a..dfee9dea40c 100644 --- a/extensions/configuration-editing/schemas/devContainer.schema.generated.json +++ b/extensions/configuration-editing/schemas/devContainer.schema.generated.json @@ -116,7 +116,7 @@ "description": "An array of extensions that should be installed into the container.", "items": { "type": "string", - "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$", + "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)((@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)|@prerelease)?$", "errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'." } }, @@ -519,7 +519,7 @@ "description": "An array of extensions that should be installed into the container.", "items": { "type": "string", - "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$", + "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)((@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)|@prerelease)?$", "errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'." } }, @@ -888,7 +888,7 @@ "description": "An array of extensions that should be installed into the container.", "items": { "type": "string", - "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$", + "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)((@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)|@prerelease)?$", "errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'." } }, @@ -1231,7 +1231,7 @@ "description": "An array of extensions that should be installed into the container.", "items": { "type": "string", - "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$", + "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)((@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)|@prerelease)?$", "errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'." } }, @@ -1539,7 +1539,7 @@ "description": "An array of extensions that should be installed into the container.", "items": { "type": "string", - "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$", + "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)((@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)|@prerelease)?$", "errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'." } }, diff --git a/extensions/configuration-editing/schemas/devContainer.schema.src.json b/extensions/configuration-editing/schemas/devContainer.schema.src.json index 1e1e6c860aa..cea8472e8f6 100644 --- a/extensions/configuration-editing/schemas/devContainer.schema.src.json +++ b/extensions/configuration-editing/schemas/devContainer.schema.src.json @@ -16,7 +16,7 @@ "description": "An array of extensions that should be installed into the container.", "items": { "type": "string", - "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$", + "pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)((@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)|@prerelease)?$", "errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'." } }, From 6402452a2e0affae8f511bedf089e18399ad179c Mon Sep 17 00:00:00 2001 From: Christophe Bliard Date: Wed, 9 Mar 2022 08:56:23 +0100 Subject: [PATCH 067/175] Add expected type for selectionLines property of editor.fold command --- src/vs/editor/contrib/folding/browser/folding.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/folding/browser/folding.ts b/src/vs/editor/contrib/folding/browser/folding.ts index e714b54aeb6..0e7f51a71cf 100644 --- a/src/vs/editor/contrib/folding/browser/folding.ts +++ b/src/vs/editor/contrib/folding/browser/folding.ts @@ -633,7 +633,7 @@ class UnfoldAction extends FoldingAction { description: `Property-value pairs that can be passed through this argument: * 'levels': Number of levels to unfold. If not set, defaults to 1. * 'direction': If 'up', unfold given number of levels up otherwise unfolds down. - * 'selectionLines': The start lines (0-based) of the editor selections to apply the unfold action to. If not set, the active selection(s) will be used. + * 'selectionLines': Array of the start lines (0-based) of the editor selections to apply the unfold action to. If not set, the active selection(s) will be used. `, constraint: foldingArgumentsConstraint, schema: { @@ -718,7 +718,7 @@ class FoldAction extends FoldingAction { description: `Property-value pairs that can be passed through this argument: * 'levels': Number of levels to fold. * 'direction': If 'up', folds given number of levels up otherwise folds down. - * 'selectionLines': The start lines (0-based) of the editor selections to apply the fold action to. If not set, the active selection(s) will be used. + * 'selectionLines': Array of the start lines (0-based) of the editor selections to apply the fold action to. If not set, the active selection(s) will be used. If no levels or direction is set, folds the region at the locations or if already collapsed, the first uncollapsed parent instead. `, constraint: foldingArgumentsConstraint, From f57c9e5bf5aa724d8c83702abd2b2dd65f86a05c Mon Sep 17 00:00:00 2001 From: Quan Zhuo Date: Wed, 9 Mar 2022 18:50:55 +0800 Subject: [PATCH 068/175] #144671, fix some non localized strings in git extension (#144712) Signed-off-by: Quan Zhuo --- extensions/git/src/timelineProvider.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/extensions/git/src/timelineProvider.ts b/extensions/git/src/timelineProvider.ts index f6e543257e2..bfedf9155c5 100644 --- a/extensions/git/src/timelineProvider.ts +++ b/extensions/git/src/timelineProvider.ts @@ -155,6 +155,7 @@ export class GitTimelineProvider implements TimelineProvider { const dateType = config.get<'committed' | 'authored'>('date'); const showAuthor = config.get('showAuthor'); + const openComparison = localize('git.timeline.openComparison', "Open Comparison"); const items = commits.map((c, i) => { const date = dateType === 'authored' ? c.authorDate : c.commitDate; @@ -171,7 +172,7 @@ export class GitTimelineProvider implements TimelineProvider { const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri); if (cmd) { item.command = { - title: 'Open Comparison', + title: openComparison, command: cmd.command, arguments: cmd.arguments, }; @@ -196,7 +197,7 @@ export class GitTimelineProvider implements TimelineProvider { const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri); if (cmd) { item.command = { - title: 'Open Comparison', + title: openComparison, command: cmd.command, arguments: cmd.arguments, }; @@ -218,7 +219,7 @@ export class GitTimelineProvider implements TimelineProvider { const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri); if (cmd) { item.command = { - title: 'Open Comparison', + title: openComparison, command: cmd.command, arguments: cmd.arguments, }; From 9dc64401c35508cf03475c4deea9690810f8bca1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 9 Mar 2022 10:36:10 +0100 Subject: [PATCH 069/175] don't check feature registry if there are smart select providers, there is always the word based one, https://github.com/microsoft/vscode/issues/144297 --- src/vs/editor/contrib/smartSelect/browser/smartSelect.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/vs/editor/contrib/smartSelect/browser/smartSelect.ts b/src/vs/editor/contrib/smartSelect/browser/smartSelect.ts index 2bdc82c8cbe..fd8a9537b54 100644 --- a/src/vs/editor/contrib/smartSelect/browser/smartSelect.ts +++ b/src/vs/editor/contrib/smartSelect/browser/smartSelect.ts @@ -79,9 +79,6 @@ class SmartSelectController implements IEditorContribution { const selections = this._editor.getSelections(); const model = this._editor.getModel(); - if (!this._languageFeaturesService.selectionRangeProvider.has(model)) { - return; - } if (!this._state) { From d898eb7689c47b161c5f41baa4314c34da136978 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 9 Mar 2022 13:15:21 +0100 Subject: [PATCH 070/175] some jsdoc for https://github.com/microsoft/vscode/issues/144662 --- .../vscode.proposed.notebookDocumentEvents.d.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts b/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts index 92052dced75..ff3c14e7d87 100644 --- a/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts +++ b/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +// https://github.com/microsoft/vscode/issues/144662 + declare module 'vscode' { export interface NotebookDocumentContentCellChange { @@ -18,8 +20,17 @@ declare module 'vscode' { } export interface NotebookDocumentContentChange { + /** + * The range at which cells have been either and or removed. + */ readonly range: NotebookRange; + /** + * Cells that have been added to the document. + */ readonly addedCells: NotebookCell[]; + /** + * Cells that have been removed from the document. + */ readonly removedCells: NotebookCell[]; } From d4c26aa154f2506614f5a292bc598c7ce07dbf36 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 9 Mar 2022 13:29:19 +0100 Subject: [PATCH 071/175] a little more jsdoc, https://github.com/microsoft/vscode/issues/144662 --- src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts b/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts index ff3c14e7d87..947067c29e9 100644 --- a/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts +++ b/src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts @@ -14,6 +14,9 @@ declare module 'vscode' { */ readonly cell: NotebookCell; + /** + * The metadata of the cell or `undefined` when it didn't change + */ readonly metadata: { [key: string]: any } | undefined; readonly outputs: readonly NotebookCellOutput[] | undefined; readonly executionSummary: NotebookCellExecutionSummary | undefined; From c08eb1947902be6f7e4d069bb529a91985045f77 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 9 Mar 2022 13:58:41 +0100 Subject: [PATCH 072/175] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3919b901747..3ce42353bc8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.66.0", - "distro": "991367d8d1e224ddc355f6d948da185c2f30b88e", + "distro": "f398eb6db587d4065b4572461768f9c652aef963", "author": { "name": "Microsoft Corporation" }, From c0d5f3efb65bfde3c2ab50ce2d84fddc8536ff30 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 9 Mar 2022 15:45:08 +0100 Subject: [PATCH 073/175] Show comments view when file with comments is opened Fixes #143948 --- .../comments/browser/comments.contribution.ts | 13 ++++++++----- .../browser/commentsEditorContribution.ts | 19 +++++++++++++++++-- .../contrib/comments/browser/timestamp.ts | 5 ++--- .../comments/common/commentsConfiguration.ts | 11 +++++++++++ 4 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/vs/workbench/contrib/comments/common/commentsConfiguration.ts diff --git a/src/vs/workbench/contrib/comments/browser/comments.contribution.ts b/src/vs/workbench/contrib/comments/browser/comments.contribution.ts index f2c6b1d3b4b..0d515f2ae79 100644 --- a/src/vs/workbench/contrib/comments/browser/comments.contribution.ts +++ b/src/vs/workbench/contrib/comments/browser/comments.contribution.ts @@ -10,10 +10,6 @@ import 'vs/workbench/contrib/comments/browser/commentsEditorContribution'; import { ICommentService, CommentService } from 'vs/workbench/contrib/comments/browser/commentService'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -export interface ICommentsConfiguration { - openPanel: 'neverOpen' | 'openOnSessionStart' | 'openOnSessionStartWithComments'; -} - Registry.as(ConfigurationExtensions.Configuration).registerConfiguration({ id: 'comments', order: 20, @@ -24,13 +20,20 @@ Registry.as(ConfigurationExtensions.Configuration).regis enum: ['neverOpen', 'openOnSessionStart', 'openOnSessionStartWithComments'], default: 'openOnSessionStartWithComments', description: nls.localize('openComments', "Controls when the comments panel should open."), + restricted: false, + markdownDeprecationMessage: nls.localize('comments.openPanel.deprecated', "This setting is deprecated in favor of `comments.openView`.") + }, + 'comments.openView': { + enum: ['never', 'file'], + enumDescriptions: [nls.localize('comments.openView.never', "The comments view will never be opened."), nls.localize('comments.openView.file', "The comments view will open when a file with comments is active.")], + default: 'file', + description: nls.localize('comments.openView', "Controls when the comments view should open."), restricted: false }, 'comments.useRelativeTime': { type: 'boolean', default: true, description: nls.localize('useRelativeTime', "Determines if relative time will be used in comment timestamps (ex. '1 day ago').") - } } }); diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index e8abd1ef104..f967fcde19f 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -36,6 +36,10 @@ import { ctxCommentEditorFocused, SimpleCommentEditor } from 'vs/workbench/contr import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { IViewsService } from 'vs/workbench/common/views'; +import { COMMENTS_VIEW_ID } from 'vs/workbench/contrib/comments/browser/commentsTreeViewer'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { COMMENTS_SECTION, ICommentsConfiguration } from 'vs/workbench/contrib/comments/common/commentsConfiguration'; export const ID = 'editor.contrib.review'; @@ -167,7 +171,9 @@ export class CommentController implements IEditorContribution { @IInstantiationService private readonly instantiationService: IInstantiationService, @ICodeEditorService private readonly codeEditorService: ICodeEditorService, @IContextMenuService readonly contextMenuService: IContextMenuService, - @IQuickInputService private readonly quickInputService: IQuickInputService + @IQuickInputService private readonly quickInputService: IQuickInputService, + @IViewsService private readonly viewsService: IViewsService, + @IConfigurationService private readonly configurationService: IConfigurationService ) { this._commentInfos = []; this._commentWidgets = []; @@ -399,7 +405,12 @@ export class CommentController implements IEditorContribution { })); - this.beginCompute(); + this.beginCompute().then(() => { + if (this._commentWidgets.length + && (this.configurationService.getValue(COMMENTS_SECTION).openView === 'file')) { + this.viewsService.openView(COMMENTS_VIEW_ID); + } + }); } private displayCommentThread(owner: string, thread: languages.CommentThread, pendingComment: string | null): void { @@ -630,6 +641,10 @@ export class CommentController implements IEditorContribution { this._commentWidgets = []; } + + public hasComments(): boolean { + return !!this._commentWidgets.length; + } } export class NextCommentThreadAction extends EditorAction { diff --git a/src/vs/workbench/contrib/comments/browser/timestamp.ts b/src/vs/workbench/contrib/comments/browser/timestamp.ts index ad7ae7fbd38..cf68da654d6 100644 --- a/src/vs/workbench/contrib/comments/browser/timestamp.ts +++ b/src/vs/workbench/contrib/comments/browser/timestamp.ts @@ -7,8 +7,7 @@ import * as dom from 'vs/base/browser/dom'; import { fromNow } from 'vs/base/common/date'; import { Disposable } from 'vs/base/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; - -const USE_RELATIVE_TIME_CONFIGURATION = 'comments.useRelativeTime'; +import { COMMENTS_SECTION, ICommentsConfiguration } from 'vs/workbench/contrib/comments/common/commentsConfiguration'; export class TimestampWidget extends Disposable { private _date: HTMLElement; @@ -24,7 +23,7 @@ export class TimestampWidget extends Disposable { } private get useRelativeTimeSetting(): boolean { - return this.configurationService.getValue(USE_RELATIVE_TIME_CONFIGURATION); + return this.configurationService.getValue(COMMENTS_SECTION).useRelativeTime; } public async setTimestamp(timestamp: Date | undefined) { diff --git a/src/vs/workbench/contrib/comments/common/commentsConfiguration.ts b/src/vs/workbench/contrib/comments/common/commentsConfiguration.ts new file mode 100644 index 00000000000..1ef2ba67cb7 --- /dev/null +++ b/src/vs/workbench/contrib/comments/common/commentsConfiguration.ts @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface ICommentsConfiguration { + openView: 'never' | 'file'; + useRelativeTime: boolean; +} + +export const COMMENTS_SECTION = 'comments'; From b890074c91d7f25dd322ecf64d5dce1818298bd7 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 9 Mar 2022 16:17:00 +0100 Subject: [PATCH 074/175] Reveal comment threads in active diff editor from view Part of #143948 --- .../contrib/comments/browser/commentsView.ts | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/contrib/comments/browser/commentsView.ts b/src/vs/workbench/contrib/comments/browser/commentsView.ts index de0206fb60c..ad852ea3b7e 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsView.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsView.ts @@ -7,7 +7,7 @@ import 'vs/css!./media/panel'; import * as nls from 'vs/nls'; import * as dom from 'vs/base/browser/dom'; import { basename } from 'vs/base/common/resources'; -import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; +import { isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { CommentNode, CommentsModel, ResourceWithCommentThreads, ICommentThreadChangedEvent } from 'vs/workbench/contrib/comments/common/commentModel'; @@ -29,6 +29,8 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; import { Codicon } from 'vs/base/common/codicons'; +import { IEditor } from 'vs/editor/common/editorCommon'; +import { TextModel } from 'vs/editor/common/model/textModel'; const CONTEXT_KEY_HAS_COMMENTS = new RawContextKey('commentsView.hasComments', false); @@ -211,18 +213,24 @@ export class CommentsPanel extends ViewPane { const range = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].range : element.range; - const activeEditor = this.editorService.activeEditor; - let currentActiveResource = activeEditor ? activeEditor.resource : undefined; - if (this.uriIdentityService.extUri.isEqual(element.resource, currentActiveResource)) { - const threadToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].threadId : element.threadId; - const commentToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].comment.uniqueIdInThread : element.comment.uniqueIdInThread; - const control = this.editorService.activeTextEditorControl; - if (threadToReveal && isCodeEditor(control)) { - const controller = CommentController.get(control); - controller?.revealCommentThread(threadToReveal, commentToReveal, false); - } + const activeEditor = this.editorService.activeTextEditorControl; + // If the active editor is a diff editor where one of the sides has the comment, + // then we try to reveal the comment in the diff editor. + let currentActiveResources: IEditor[] = isDiffEditor(activeEditor) ? [activeEditor.getOriginalEditor(), activeEditor.getModifiedEditor()] + : (activeEditor ? [activeEditor] : []); - return true; + for (const editor of currentActiveResources) { + const model = editor.getModel(); + if ((model instanceof TextModel) && this.uriIdentityService.extUri.isEqual(element.resource, model.uri)) { + const threadToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].threadId : element.threadId; + const commentToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].comment.uniqueIdInThread : element.comment.uniqueIdInThread; + if (threadToReveal && isCodeEditor(editor)) { + const controller = CommentController.get(editor); + controller?.revealCommentThread(threadToReveal, commentToReveal, false); + } + + return true; + } } const threadToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].threadId : element.threadId; From bb1b3c39555b19cd079a9b8de33fca2f063302d7 Mon Sep 17 00:00:00 2001 From: Johannes Date: Wed, 9 Mar 2022 16:38:45 +0100 Subject: [PATCH 075/175] add trace logging for notebook serializer --- src/vs/workbench/api/browser/mainThreadNotebook.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index dfcb29b1f39..db80199bc2f 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -15,6 +15,8 @@ import { INotebookCellStatusBarItemProvider, INotebookContributionData, Notebook import { INotebookContentProvider, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier'; import { ExtHostContext, ExtHostNotebookShape, MainContext, MainThreadNotebookShape } from '../common/extHost.protocol'; +import { ILogService } from 'vs/platform/log/common/log'; +import { StopWatch } from 'vs/base/common/stopwatch'; @extHostNamedCustomer(MainContext.MainThreadNotebook) export class MainThreadNotebooks implements MainThreadNotebookShape { @@ -30,6 +32,7 @@ export class MainThreadNotebooks implements MainThreadNotebookShape { extHostContext: IExtHostContext, @INotebookService private readonly _notebookService: INotebookService, @INotebookCellStatusBarService private readonly _cellStatusBarService: INotebookCellStatusBarService, + @ILogService private readonly _logService: ILogService, ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebook); } @@ -107,11 +110,17 @@ export class MainThreadNotebooks implements MainThreadNotebookShape { const registration = this._notebookService.registerNotebookSerializer(viewType, extension, { options, dataToNotebook: async (data: VSBuffer): Promise => { + const sw = new StopWatch(true); const dto = await this._proxy.$dataToNotebook(handle, data, CancellationToken.None); - return NotebookDto.fromNotebookDataDto(dto.value); + const result = NotebookDto.fromNotebookDataDto(dto.value); + this._logService.trace('[NotebookSerializer] dataToNotebook DONE', extension.id, sw.elapsed()); + return result; }, notebookToData: (data: NotebookData): Promise => { - return this._proxy.$notebookToData(handle, new SerializableObjectWithBuffers(NotebookDto.toNotebookDataDto(data)), CancellationToken.None); + const sw = new StopWatch(true); + const result = this._proxy.$notebookToData(handle, new SerializableObjectWithBuffers(NotebookDto.toNotebookDataDto(data)), CancellationToken.None); + this._logService.trace('[NotebookSerializer] notebookToData DONE', extension.id, sw.elapsed()); + return result; } }); const disposables = new DisposableStore(); From a8ed28d4c8894036945f4944f2e965051e02fb79 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 9 Mar 2022 19:17:40 +0100 Subject: [PATCH 076/175] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ce42353bc8..95be12c4ed8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.66.0", - "distro": "f398eb6db587d4065b4572461768f9c652aef963", + "distro": "8a079bdc7fc729d6acfb948ef85b931abcbfad12", "author": { "name": "Microsoft Corporation" }, From 04850d10a8adb7549306df8cbe2333de10d107b1 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 9 Mar 2022 12:46:56 -0600 Subject: [PATCH 077/175] xterm@4.19.0-beta.2 fix #144142 --- package.json | 8 ++++---- remote/package.json | 8 ++++---- remote/web/package.json | 4 ++-- remote/web/yarn.lock | 16 ++++++++-------- remote/yarn.lock | 32 ++++++++++++++++---------------- yarn.lock | 32 ++++++++++++++++---------------- 6 files changed, 50 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index 95be12c4ed8..b46c5602a28 100644 --- a/package.json +++ b/package.json @@ -85,12 +85,12 @@ "vscode-proxy-agent": "^0.12.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "6.0.0", - "xterm": "4.18.0-beta.15", - "xterm-addon-search": "0.9.0-beta.10", - "xterm-addon-serialize": "0.7.0-beta.9", + "xterm": "4.19.0-beta.2", + "xterm-addon-search": "0.9.0-beta.11", + "xterm-addon-serialize": "0.7.0-beta.10", "xterm-addon-unicode11": "0.4.0-beta.3", "xterm-addon-webgl": "0.12.0-beta.24", - "xterm-headless": "4.18.0-beta.15", + "xterm-headless": "4.19.0-beta.2", "yauzl": "^2.9.2", "yazl": "^2.4.3" }, diff --git a/remote/package.json b/remote/package.json index 7339e21ada2..f353b702051 100644 --- a/remote/package.json +++ b/remote/package.json @@ -24,12 +24,12 @@ "vscode-proxy-agent": "^0.12.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "6.0.0", - "xterm": "4.18.0-beta.15", - "xterm-addon-search": "0.9.0-beta.10", - "xterm-addon-serialize": "0.7.0-beta.9", + "xterm": "4.19.0-beta.2", + "xterm-addon-search": "0.9.0-beta.11", + "xterm-addon-serialize": "0.7.0-beta.10", "xterm-addon-unicode11": "0.4.0-beta.3", "xterm-addon-webgl": "0.12.0-beta.24", - "xterm-headless": "4.18.0-beta.15", + "xterm-headless": "4.19.0-beta.2", "yauzl": "^2.9.2", "yazl": "^2.4.3" }, diff --git a/remote/web/package.json b/remote/web/package.json index c5d937caac7..45735c96060 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -10,8 +10,8 @@ "tas-client-umd": "0.1.4", "vscode-oniguruma": "1.6.1", "vscode-textmate": "6.0.0", - "xterm": "4.18.0-beta.15", - "xterm-addon-search": "0.9.0-beta.10", + "xterm": "4.19.0-beta.2", + "xterm-addon-search": "0.9.0-beta.11", "xterm-addon-unicode11": "0.4.0-beta.3", "xterm-addon-webgl": "0.12.0-beta.24" } diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index 32714eaae4a..08bce4d8573 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -113,10 +113,10 @@ vscode-textmate@6.0.0: resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-6.0.0.tgz#a3777197235036814ac9a92451492f2748589210" integrity sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ== -xterm-addon-search@0.9.0-beta.10: - version "0.9.0-beta.10" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.10.tgz#80677a5e105d4410feae92b90fcdd5b538067070" - integrity sha512-fxKwbsu+ZNgZ689sAX1PHhWAW+8/abAGD8B7SMWwelKhJmbRybHoaLAYCeUrZJlJHljwjgW3Ptk7OpONNydh1A== +xterm-addon-search@0.9.0-beta.11: + version "0.9.0-beta.11" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.11.tgz#e6af723903e470564682eb80e5f0ca7e5d291c60" + integrity sha512-sUaOrgqFJvN7oI20ruKVOEqN5t4UK9q/pAR7FSjH5vVl6h0Hhtndh9bhrgoKCSe+Do1YfZCcpWx0Sbs9Y+2Ptg== xterm-addon-unicode11@0.4.0-beta.3: version "0.4.0-beta.3" @@ -128,7 +128,7 @@ xterm-addon-webgl@0.12.0-beta.24: resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.24.tgz#5c17256933991856554c95c9bd1eaab42e9727a0" integrity sha512-+wZxKReEOlfN9JRHyikoffA6Do61/THR7QY35ajkQo0lLutKr6hTd/TLTuZh0PhFVelgTgudpXqlP++Lc0WFIA== -xterm@4.18.0-beta.15: - version "4.18.0-beta.15" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.18.0-beta.15.tgz#99d40cfbd2e7f3343b2a125fd7d4b3bb864ca2f5" - integrity sha512-e3JkreKDjXNZcpQsHybaroTGXTtq7Lu1Bx+wuviBBllhz9CxI+uHzwMNHPgdFaZ+zwJq85hyeVHn354ooJ8nzA== +xterm@4.19.0-beta.2: + version "4.19.0-beta.2" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.19.0-beta.2.tgz#abc63abba8ee5e3dec88f4ebae13b8198151acbf" + integrity sha512-pi9hUmkwRbOOJlbG5pNiTDaBXNsTq2+Kh6V7cs9i7j8sW3QMDk66dc/ZFNh0293/U987u87NdFWljD/V+g068g== diff --git a/remote/yarn.lock b/remote/yarn.lock index cb3a9fb85a1..cf092242bda 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -908,15 +908,15 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -xterm-addon-search@0.9.0-beta.10: - version "0.9.0-beta.10" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.10.tgz#80677a5e105d4410feae92b90fcdd5b538067070" - integrity sha512-fxKwbsu+ZNgZ689sAX1PHhWAW+8/abAGD8B7SMWwelKhJmbRybHoaLAYCeUrZJlJHljwjgW3Ptk7OpONNydh1A== +xterm-addon-search@0.9.0-beta.11: + version "0.9.0-beta.11" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.11.tgz#e6af723903e470564682eb80e5f0ca7e5d291c60" + integrity sha512-sUaOrgqFJvN7oI20ruKVOEqN5t4UK9q/pAR7FSjH5vVl6h0Hhtndh9bhrgoKCSe+Do1YfZCcpWx0Sbs9Y+2Ptg== -xterm-addon-serialize@0.7.0-beta.9: - version "0.7.0-beta.9" - resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.7.0-beta.9.tgz#122dcc1b764fad1a9970079c690e0810c7936a2d" - integrity sha512-a9DIC624nmJKcY8e8ykzib9Lefli/ea/87JFtUBDZPe5w12NM0XlQgDkcyCS1MhcTQKA1RYoEp9003QDkmIybQ== +xterm-addon-serialize@0.7.0-beta.10: + version "0.7.0-beta.10" + resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.7.0-beta.10.tgz#52e85fc4a4ad127d24e18cf33034aedc65201973" + integrity sha512-nWaU6GKv3cKZUpU/lM/u3ehYwO4EZMMJF5mOlPJXAgqwSWHoUCyR559ikk4UsKyRPfJxmnhPXiijfJyijqvNqw== xterm-addon-unicode11@0.4.0-beta.3: version "0.4.0-beta.3" @@ -928,15 +928,15 @@ xterm-addon-webgl@0.12.0-beta.24: resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.24.tgz#5c17256933991856554c95c9bd1eaab42e9727a0" integrity sha512-+wZxKReEOlfN9JRHyikoffA6Do61/THR7QY35ajkQo0lLutKr6hTd/TLTuZh0PhFVelgTgudpXqlP++Lc0WFIA== -xterm-headless@4.18.0-beta.15: - version "4.18.0-beta.15" - resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-4.18.0-beta.15.tgz#f710959af0aea37f8395a8011e431f2341405473" - integrity sha512-uIrWvVSdZzDneDPD9/u4mZ+OvnPDpsI/bvUzQ923/9GEyLO2UlJGipJUBhMB5W+xhox5PZJIAJJxCHnXo8Vx2Q== +xterm-headless@4.19.0-beta.2: + version "4.19.0-beta.2" + resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-4.19.0-beta.2.tgz#6749d7377b9b0cc3d73001857fb05da6ae1994e5" + integrity sha512-vn+YE1L6geAOSHFiaengIaHQXgNLTGdSssFnJTshmZv404KiPOfDNxspUMxBOKJdWlqoyD2wCtkD/sFiX7+F9A== -xterm@4.18.0-beta.15: - version "4.18.0-beta.15" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.18.0-beta.15.tgz#99d40cfbd2e7f3343b2a125fd7d4b3bb864ca2f5" - integrity sha512-e3JkreKDjXNZcpQsHybaroTGXTtq7Lu1Bx+wuviBBllhz9CxI+uHzwMNHPgdFaZ+zwJq85hyeVHn354ooJ8nzA== +xterm@4.19.0-beta.2: + version "4.19.0-beta.2" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.19.0-beta.2.tgz#abc63abba8ee5e3dec88f4ebae13b8198151acbf" + integrity sha512-pi9hUmkwRbOOJlbG5pNiTDaBXNsTq2+Kh6V7cs9i7j8sW3QMDk66dc/ZFNh0293/U987u87NdFWljD/V+g068g== yauzl@^2.9.2: version "2.10.0" diff --git a/yarn.lock b/yarn.lock index 03396cf5de0..8b7937639c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12342,15 +12342,15 @@ xtend@~2.1.1: dependencies: object-keys "~0.4.0" -xterm-addon-search@0.9.0-beta.10: - version "0.9.0-beta.10" - resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.10.tgz#80677a5e105d4410feae92b90fcdd5b538067070" - integrity sha512-fxKwbsu+ZNgZ689sAX1PHhWAW+8/abAGD8B7SMWwelKhJmbRybHoaLAYCeUrZJlJHljwjgW3Ptk7OpONNydh1A== +xterm-addon-search@0.9.0-beta.11: + version "0.9.0-beta.11" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.11.tgz#e6af723903e470564682eb80e5f0ca7e5d291c60" + integrity sha512-sUaOrgqFJvN7oI20ruKVOEqN5t4UK9q/pAR7FSjH5vVl6h0Hhtndh9bhrgoKCSe+Do1YfZCcpWx0Sbs9Y+2Ptg== -xterm-addon-serialize@0.7.0-beta.9: - version "0.7.0-beta.9" - resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.7.0-beta.9.tgz#122dcc1b764fad1a9970079c690e0810c7936a2d" - integrity sha512-a9DIC624nmJKcY8e8ykzib9Lefli/ea/87JFtUBDZPe5w12NM0XlQgDkcyCS1MhcTQKA1RYoEp9003QDkmIybQ== +xterm-addon-serialize@0.7.0-beta.10: + version "0.7.0-beta.10" + resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.7.0-beta.10.tgz#52e85fc4a4ad127d24e18cf33034aedc65201973" + integrity sha512-nWaU6GKv3cKZUpU/lM/u3ehYwO4EZMMJF5mOlPJXAgqwSWHoUCyR559ikk4UsKyRPfJxmnhPXiijfJyijqvNqw== xterm-addon-unicode11@0.4.0-beta.3: version "0.4.0-beta.3" @@ -12362,15 +12362,15 @@ xterm-addon-webgl@0.12.0-beta.24: resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.24.tgz#5c17256933991856554c95c9bd1eaab42e9727a0" integrity sha512-+wZxKReEOlfN9JRHyikoffA6Do61/THR7QY35ajkQo0lLutKr6hTd/TLTuZh0PhFVelgTgudpXqlP++Lc0WFIA== -xterm-headless@4.18.0-beta.15: - version "4.18.0-beta.15" - resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-4.18.0-beta.15.tgz#f710959af0aea37f8395a8011e431f2341405473" - integrity sha512-uIrWvVSdZzDneDPD9/u4mZ+OvnPDpsI/bvUzQ923/9GEyLO2UlJGipJUBhMB5W+xhox5PZJIAJJxCHnXo8Vx2Q== +xterm-headless@4.19.0-beta.2: + version "4.19.0-beta.2" + resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-4.19.0-beta.2.tgz#6749d7377b9b0cc3d73001857fb05da6ae1994e5" + integrity sha512-vn+YE1L6geAOSHFiaengIaHQXgNLTGdSssFnJTshmZv404KiPOfDNxspUMxBOKJdWlqoyD2wCtkD/sFiX7+F9A== -xterm@4.18.0-beta.15: - version "4.18.0-beta.15" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.18.0-beta.15.tgz#99d40cfbd2e7f3343b2a125fd7d4b3bb864ca2f5" - integrity sha512-e3JkreKDjXNZcpQsHybaroTGXTtq7Lu1Bx+wuviBBllhz9CxI+uHzwMNHPgdFaZ+zwJq85hyeVHn354ooJ8nzA== +xterm@4.19.0-beta.2: + version "4.19.0-beta.2" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.19.0-beta.2.tgz#abc63abba8ee5e3dec88f4ebae13b8198151acbf" + integrity sha512-pi9hUmkwRbOOJlbG5pNiTDaBXNsTq2+Kh6V7cs9i7j8sW3QMDk66dc/ZFNh0293/U987u87NdFWljD/V+g068g== y18n@^3.2.1: version "3.2.2" From 5a7db04b8968ed16b3b6fdd17f77288e824550b4 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 9 Mar 2022 10:48:11 -0800 Subject: [PATCH 078/175] Fix #144043 --- .../src/singlefolder-tests/notebook.test.ts | 27 ------------ .../browser/contrib/execute/execution.ts | 42 ------------------- .../notebook/browser/notebook.contribution.ts | 1 - 3 files changed, 70 deletions(-) delete mode 100644 src/vs/workbench/contrib/notebook/browser/contrib/execute/execution.ts diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index 5c5d0c88143..2e3a32cd9ce 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -902,33 +902,6 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { assert.strictEqual(executionWasCancelled, true); }); - - test('execution cancelled when kernel changed', async () => { - await openRandomNotebookDocument(); - let executionWasCancelled = false; - const cancelledKernel = new class extends Kernel { - constructor() { - super('cancelledKernel', ''); - } - - override async _execute(cells: vscode.NotebookCell[]) { - const [cell] = cells; - const exe = this.controller.createNotebookCellExecution(cell); - exe.token.onCancellationRequested(() => executionWasCancelled = true); - } - }; - - const notebook = await openRandomNotebookDocument(); - await vscode.window.showNotebookDocument(notebook); - testDisposables.push(cancelledKernel.controller); - await assertKernel(cancelledKernel, notebook); - await vscode.commands.executeCommand('notebook.cell.execute'); - - const newKernel = new Kernel('newKernel', 'kernel'); - testDisposables.push(newKernel.controller); - await assertKernel(newKernel, notebook); - assert.strictEqual(executionWasCancelled, true); - }); }); (vscode.env.uiKind === vscode.UIKind.Web ? suite.skip : suite)('statusbar', () => { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/execute/execution.ts b/src/vs/workbench/contrib/notebook/browser/contrib/execute/execution.ts deleted file mode 100644 index 0572d8ae0e2..00000000000 --- a/src/vs/workbench/contrib/notebook/browser/contrib/execute/execution.ts +++ /dev/null @@ -1,42 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Disposable } from 'vs/base/common/lifecycle'; -import { ILogService } from 'vs/platform/log/common/log'; -import { INotebookEditor, INotebookEditorContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { registerNotebookContribution } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; -import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService'; -import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; -import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; - -export class ExecutionContrib extends Disposable implements INotebookEditorContribution { - static id: string = 'workbench.notebook.executionContrib'; - - constructor( - private readonly _notebookEditor: INotebookEditor, - @INotebookExecutionStateService private readonly _notebookExecutionStateService: INotebookExecutionStateService, - @INotebookExecutionService private readonly _notebookExecutionService: INotebookExecutionService, - @ILogService private readonly _logService: ILogService, - @INotebookKernelService private readonly _notebookKernelService: INotebookKernelService, - ) { - super(); - - this._register(this._notebookKernelService.onDidChangeSelectedNotebooks(e => { - if (e.newKernel && this._notebookEditor.textModel?.uri.toString() === e.notebook.toString()) { - this.cancelAll(); - this._notebookExecutionStateService.forceCancelNotebookExecutions(e.notebook); - } - })); - } - - private cancelAll(): void { - this._logService.debug(`ExecutionContrib#cancelAll`); - const exes = this._notebookExecutionStateService.getCellExecutionStatesForNotebook(this._notebookEditor.textModel!.uri); - this._notebookExecutionService.cancelNotebookCellHandles(this._notebookEditor.textModel!, exes.map(exe => exe.cellHandle)); - } -} - - -registerNotebookContribution(ExecutionContrib.id, ExecutionContrib); diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 1b066da0104..b751908a22d 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -88,7 +88,6 @@ import 'vs/workbench/contrib/notebook/browser/contrib/viewportCustomMarkdown/vie import 'vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout'; import 'vs/workbench/contrib/notebook/browser/contrib/breakpoints/notebookBreakpoints'; import 'vs/workbench/contrib/notebook/browser/contrib/execute/executionEditorProgress'; -import 'vs/workbench/contrib/notebook/browser/contrib/execute/execution'; // Diff Editor Contribution import 'vs/workbench/contrib/notebook/browser/diff/notebookDiffActions'; From fa5aa53695fa4b72c36fcb83133a4b6e62a1d63c Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Wed, 9 Mar 2022 20:28:36 +0100 Subject: [PATCH 079/175] Revert "Fix #121914" This reverts commit 6011bf7e7ad87a06908e9947fd5ccd948739f953. --- extensions/git/src/git.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index b4d26d99a10..0e71140326e 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -2028,6 +2028,7 @@ export class Repository { if (branchName.startsWith('refs/heads/')) { branchName = branchName.substring(11); + const index = upstream.indexOf('/'); let ahead; let behind; @@ -2040,8 +2041,8 @@ export class Repository { type: RefType.Head, name: branchName, upstream: upstream ? { - name: upstream.substring(upstream.length - branchName.length), - remote: upstream.substring(0, upstream.length - branchName.length - 1) + name: upstream.substring(index + 1), + remote: upstream.substring(0, index) } : undefined, commit: ref || undefined, ahead: Number(ahead) || 0, From 61ad5b6eefa1babce1c51154c4a5220262e986cd Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 9 Mar 2022 13:08:04 +0100 Subject: [PATCH 080/175] Consider error-telemetry to be a type label --- .vscode/notebooks/my-work.github-issues | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/notebooks/my-work.github-issues b/.vscode/notebooks/my-work.github-issues index 5c931c263b3..b298da45049 100644 --- a/.vscode/notebooks/my-work.github-issues +++ b/.vscode/notebooks/my-work.github-issues @@ -92,7 +92,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repos assignee:@me is:open type:issue -label:bug -label:\"needs more info\" -label:feature-request -label:under-discussion -label:debt -label:plan-item -label:upstream -label:polish -label:testplan-item" + "value": "$repos assignee:@me is:open type:issue -label:bug -label:\"needs more info\" -label:feature-request -label:under-discussion -label:debt -label:plan-item -label:upstream -label:polish -label:testplan-item -label:error-telemetry" }, { "kind": 1, From d7ffa37a73c2122bd3e99683dcedece10b352180 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 9 Mar 2022 15:41:49 +0100 Subject: [PATCH 081/175] Add tests for `ExtensionsActivator` --- .../api/common/extHostExtensionActivator.ts | 14 +- .../common/extHostExtensionActivator.test.ts | 243 ++++++++++++++++++ 2 files changed, 250 insertions(+), 7 deletions(-) create mode 100644 src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts diff --git a/src/vs/workbench/api/common/extHostExtensionActivator.ts b/src/vs/workbench/api/common/extHostExtensionActivator.ts index 59ff5889c3f..cbadfee1900 100644 --- a/src/vs/workbench/api/common/extHostExtensionActivator.ts +++ b/src/vs/workbench/api/common/extHostExtensionActivator.ts @@ -170,7 +170,7 @@ export class ExtensionsActivator implements IDisposable { private readonly _registry: ExtensionDescriptionRegistry; private readonly _resolvedExtensionsSet: Set; - private readonly _hostExtensionsMap: Map; + private readonly _externalExtensionsMap: Map; private readonly _host: IExtensionsActivatorHost; private readonly _activatingExtensions: Map>; private readonly _activatedExtensions: Map; @@ -182,7 +182,7 @@ export class ExtensionsActivator implements IDisposable { constructor( registry: ExtensionDescriptionRegistry, resolvedExtensions: ExtensionIdentifier[], - hostExtensions: ExtensionIdentifier[], + externalExtensions: ExtensionIdentifier[], host: IExtensionsActivatorHost, @ILogService private readonly _logService: ILogService ) { @@ -190,8 +190,8 @@ export class ExtensionsActivator implements IDisposable { this._registry = registry; this._resolvedExtensionsSet = new Set(); resolvedExtensions.forEach((extensionId) => this._resolvedExtensionsSet.add(ExtensionIdentifier.toKey(extensionId))); - this._hostExtensionsMap = new Map(); - hostExtensions.forEach((extensionId) => this._hostExtensionsMap.set(ExtensionIdentifier.toKey(extensionId), extensionId)); + this._externalExtensionsMap = new Map(); + externalExtensions.forEach((extensionId) => this._externalExtensionsMap.set(ExtensionIdentifier.toKey(extensionId), extensionId)); this._host = host; this._activatingExtensions = new Map>(); this._activatedExtensions = new Map(); @@ -248,7 +248,7 @@ export class ExtensionsActivator implements IDisposable { * semantics: `redExtensions` must wait for `greenExtensions`. */ private _handleActivateRequest(currentActivation: ActivationIdAndReason, greenExtensions: { [id: string]: ActivationIdAndReason }, redExtensions: ActivationIdAndReason[]): void { - if (this._hostExtensionsMap.has(ExtensionIdentifier.toKey(currentActivation.id))) { + if (this._externalExtensionsMap.has(ExtensionIdentifier.toKey(currentActivation.id))) { greenExtensions[ExtensionIdentifier.toKey(currentActivation.id)] = currentActivation; return; } @@ -299,11 +299,11 @@ export class ExtensionsActivator implements IDisposable { return; } - if (this._hostExtensionsMap.has(ExtensionIdentifier.toKey(depId))) { + if (this._externalExtensionsMap.has(ExtensionIdentifier.toKey(depId))) { // must first wait for the dependency to activate currentExtensionGetsGreenLight = false; greenExtensions[ExtensionIdentifier.toKey(depId)] = { - id: this._hostExtensionsMap.get(ExtensionIdentifier.toKey(depId))!, + id: this._externalExtensionsMap.get(ExtensionIdentifier.toKey(depId))!, reason: currentActivation.reason }; continue; diff --git a/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts b/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts new file mode 100644 index 00000000000..91f286d238d --- /dev/null +++ b/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts @@ -0,0 +1,243 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { timeout } from 'vs/base/common/async'; +import { URI } from 'vs/base/common/uri'; +import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { NullLogService } from 'vs/platform/log/common/log'; +import { ActivatedExtension, EmptyExtension, ExtensionActivationTimes, ExtensionsActivator, IExtensionsActivatorHost } from 'vs/workbench/api/common/extHostExtensionActivator'; +import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; +import { ExtensionActivationReason, MissingExtensionDependency } from 'vs/workbench/services/extensions/common/extensions'; + +suite('ExtensionsActivator', () => { + + const idA = new ExtensionIdentifier(`a`); + const idB = new ExtensionIdentifier(`b`); + const idC = new ExtensionIdentifier(`c`); + + test('calls activate only once with sequential activations', async () => { + const host = new SimpleExtensionsActivatorHost(); + const activator = createActivator(host, [ + desc(idA) + ]); + + await activator.activateByEvent('*', false); + assert.deepStrictEqual(host.activateCalls, [idA]); + + await activator.activateByEvent('*', false); + assert.deepStrictEqual(host.activateCalls, [idA]); + }); + + test('calls activate only once with parallel activations', async () => { + const extActivation = new ExtensionActivationPromiseSource(); + const host = new PromiseExtensionsActivatorHost([ + [idA, extActivation] + ]); + const activator = createActivator(host, [ + desc(idA, [], ['evt1', 'evt2']) + ]); + + const activate1 = activator.activateByEvent('evt1', false); + const activate2 = activator.activateByEvent('evt2', false); + + extActivation.resolve(); + + await activate1; + await activate2; + + assert.deepStrictEqual(host.activateCalls, [idA]); + }); + + test('activates dependencies first', async () => { + const extActivationA = new ExtensionActivationPromiseSource(); + const extActivationB = new ExtensionActivationPromiseSource(); + const host = new PromiseExtensionsActivatorHost([ + [idA, extActivationA], + [idB, extActivationB] + ]); + const activator = createActivator(host, [ + desc(idA, [idB], ['evt1']), + desc(idB, [], ['evt1']), + ]); + + const activate = activator.activateByEvent('evt1', false); + + await timeout(0); + assert.deepStrictEqual(host.activateCalls, [idB]); + extActivationB.resolve(); + + await timeout(0); + assert.deepStrictEqual(host.activateCalls, [idB, idA]); + extActivationA.resolve(); + + await timeout(0); + await activate; + + assert.deepStrictEqual(host.activateCalls, [idB, idA]); + }); + + test('Supports having resolved extensions', async () => { + const host = new SimpleExtensionsActivatorHost(); + const activator = createActivator(host, [ + desc(idA, [idB]) + ], [idB]); + + await activator.activateByEvent('*', false); + assert.deepStrictEqual(host.activateCalls, [idA]); + }); + + test('Supports having external extensions', async () => { + const extActivationA = new ExtensionActivationPromiseSource(); + const extActivationB = new ExtensionActivationPromiseSource(); + const host = new PromiseExtensionsActivatorHost([ + [idA, extActivationA], + [idB, extActivationB] + ]); + const activator = createActivator(host, [ + desc(idA, [idB]) + ], [], [idB]); + + const activate = activator.activateByEvent('*', false); + + await timeout(0); + assert.deepStrictEqual(host.activateCalls, [idB]); + extActivationB.resolve(); + + await timeout(0); + assert.deepStrictEqual(host.activateCalls, [idB, idA]); + extActivationA.resolve(); + + await activate; + assert.deepStrictEqual(host.activateCalls, [idB, idA]); + }); + + test('Error: activateById with missing extension', async () => { + const host = new SimpleExtensionsActivatorHost(); + const activator = createActivator(host, [ + desc(idA), + desc(idB), + ]); + + let error: Error | undefined = undefined; + try { + await activator.activateById(idC, { startup: false, extensionId: idC, activationEvent: 'none' }); + } catch (err) { + error = err; + } + + assert.strictEqual(typeof error === 'undefined', false); + }); + + test('Error: dependency missing', async () => { + const host = new SimpleExtensionsActivatorHost(); + const activator = createActivator(host, [ + desc(idA, [idB]), + ]); + + await activator.activateByEvent('*', false); + + assert.deepStrictEqual(host.errors.length, 1); + assert.deepStrictEqual(host.errors[0][0], idA); + }); + + test('Error: dependency activation failed', async () => { + const extActivationA = new ExtensionActivationPromiseSource(); + const extActivationB = new ExtensionActivationPromiseSource(); + const host = new PromiseExtensionsActivatorHost([ + [idA, extActivationA], + [idB, extActivationB] + ]); + const activator = createActivator(host, [ + desc(idA, [idB]), + desc(idB) + ]); + + const activate = activator.activateByEvent('*', false); + extActivationB.reject(new Error(`b fails!`)); + + await activate; + assert.deepStrictEqual(host.errors.length, 2); + assert.deepStrictEqual(host.errors[0][0], idB); + assert.deepStrictEqual(host.errors[1][0], idA); + }); + + class SimpleExtensionsActivatorHost implements IExtensionsActivatorHost { + public readonly activateCalls: ExtensionIdentifier[] = []; + public readonly errors: [ExtensionIdentifier, Error | null, MissingExtensionDependency | null][] = []; + + onExtensionActivationError(extensionId: ExtensionIdentifier, error: Error | null, missingExtensionDependency: MissingExtensionDependency | null): void { + this.errors.push([extensionId, error, missingExtensionDependency]); + } + + actualActivateExtension(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise { + this.activateCalls.push(extensionId); + return Promise.resolve(new EmptyExtension(ExtensionActivationTimes.NONE)); + } + } + + class PromiseExtensionsActivatorHost extends SimpleExtensionsActivatorHost { + + constructor( + private readonly _promises: [ExtensionIdentifier, ExtensionActivationPromiseSource][] + ) { + super(); + } + + override actualActivateExtension(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise { + this.activateCalls.push(extensionId); + for (const [id, promiseSource] of this._promises) { + if (id.value === extensionId.value) { + return promiseSource.promise; + } + } + throw new Error(`Unexpected!`); + } + } + + class ExtensionActivationPromiseSource { + private _resolve!: (value: ActivatedExtension) => void; + private _reject!: (err: Error) => void; + public readonly promise: Promise; + + constructor() { + this.promise = new Promise((resolve, reject) => { + this._resolve = resolve; + this._reject = reject; + }); + } + + public resolve(): void { + this._resolve(new EmptyExtension(ExtensionActivationTimes.NONE)); + } + + public reject(err: Error): void { + this._reject(err); + } + } + + function createActivator(host: IExtensionsActivatorHost, extensionDescriptions: IExtensionDescription[], resolvedExtensions: ExtensionIdentifier[] = [], hostExtensions: ExtensionIdentifier[] = []): ExtensionsActivator { + const registry = new ExtensionDescriptionRegistry(extensionDescriptions); + return new ExtensionsActivator(registry, resolvedExtensions, hostExtensions, host, new NullLogService()); + } + + function desc(id: ExtensionIdentifier, deps: ExtensionIdentifier[] = [], activationEvents: string[] = ['*']): IExtensionDescription { + return { + name: id.value, + publisher: 'test', + version: '0.0.0', + engines: { vscode: '^1.0.0' }, + identifier: id, + extensionLocation: URI.parse(`nothing://nowhere`), + isBuiltin: false, + isUnderDevelopment: false, + isUserBuiltin: false, + activationEvents, + main: 'index.js', + extensionDependencies: deps.map(d => d.value) + }; + } + +}); From 24344687a2dacfdc753e870009585d0b008fecb7 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 9 Mar 2022 12:08:16 -0800 Subject: [PATCH 082/175] experiment running notebooks in dedicated process. --- .../browser/extensions.contribution.ts | 7 +++++ .../browser/contrib/troubleshoot/layout.ts | 22 ++++++++++++++++ .../common/abstractExtensionService.ts | 12 ++++++++- .../services/extensions/common/extensions.ts | 5 ++++ .../electron-browser/extensionService.ts | 26 +++++++++++++++++-- .../localProcessExtensionHost.ts | 2 +- 6 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index 5183cae9573..b893c1705b1 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -198,6 +198,13 @@ Registry.as(ConfigurationExtensions.Configuration) 'pub.name': false } }, + 'extensions.experimental.dedicatedNotebookProcess': { + type: 'boolean', + description: localize('extensionsExperimentalDedicatedNotebookProcess', "Experimental. When enabled, notebook extensions would run in dedicated extension host."), + default: false, + scope: ConfigurationScope.APPLICATION, + ignoreSync: true + }, [WORKSPACE_TRUST_EXTENSION_SUPPORT]: { type: 'object', scope: ConfigurationScope.APPLICATION, diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout.ts b/src/vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout.ts index 29d4e867f65..daeb34afb90 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout.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 { Disposable, DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle'; import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -12,6 +13,9 @@ import { registerNotebookContribution } from 'vs/workbench/contrib/notebook/brow import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidget'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { ReloadWindowAction } from 'vs/workbench/browser/actions/windowActions'; export class TroubleshootController extends Disposable implements INotebookEditorContribution { static id: string = 'workbench.notebook.troubleshoot'; @@ -146,3 +150,21 @@ registerAction2(class extends Action2 { notebookService.clearEditorCache(); } }); + +registerAction2(class DedicatedExtensionHostAction extends Action2 { + constructor() { + super({ + id: 'notebook.experiment.runInDedicatedExtensionHost', + title: localize('notebook.experiment.runInDedicatedExtensionHost', 'Run Notebook Extensions In Dedicated Extension Host'), + f1: true, + category: CATEGORIES.Developer + }); + } + + async run(accessor: ServicesAccessor) { + const service = accessor.get(IConfigurationService); + const commandService = accessor.get(ICommandService); + await service.updateValue('extensions.experimental.dedicatedNotebookProcess', true); + await commandService.executeCommand(ReloadWindowAction.ID); + } +}); diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index aeb23b01d1e..8e8503e4617 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -188,6 +188,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx super(); this._runningLocationClassifier = new ExtensionRunningLocationClassifier( + _configurationService, (extension) => this._getExtensionKind(extension), (extensionId, extensionKinds, isInstalledLocally, isInstalledRemotely, preference) => this._pickRunningLocation(extensionId, extensionKinds, isInstalledLocally, isInstalledRemotely, preference) ); @@ -666,6 +667,11 @@ export abstract class AbstractExtensionService extends Disposable implements IEx if (localProcessExtensionHost) { await localProcessExtensionHost.ready(); } + + const notebookProcessExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalNotebook); + if (notebookProcessExtensionHost) { + await notebookProcessExtensionHost.ready(); + } } finally { lock.dispose(); } @@ -1096,6 +1102,7 @@ class ExtensionInfo { class ExtensionRunningLocationClassifier { constructor( + private readonly configurationService: IConfigurationService, private readonly getExtensionKind: (extensionDescription: IExtensionDescription) => ExtensionKind[], private readonly pickRunningLocation: (extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference) => ExtensionRunningLocation, ) { @@ -1127,6 +1134,7 @@ class ExtensionRunningLocationClassifier { localExtensions.forEach((ext) => collectExtension(ext)); remoteExtensions.forEach((ext) => collectExtension(ext)); + const isDedicatedNotebookProcessEnabled = this.configurationService.getValue('extensions.experimental.dedicatedNotebookProcess'); const runningLocation = new Map(); allExtensions.forEach((ext) => { const isInstalledLocally = Boolean(ext.local); @@ -1142,7 +1150,9 @@ class ExtensionRunningLocationClassifier { preference = ExtensionRunningPreference.Remote; } - runningLocation.set(ext.key, this.pickRunningLocation(ext.identifier, ext.kind, isInstalledLocally, isInstalledRemotely, preference)); + const location = isDedicatedNotebookProcessEnabled && (ext.local?.desc.categories ?? []).indexOf('Notebooks') >= 0 ? ExtensionRunningLocation.LocalNotebookProcess : this.pickRunningLocation(ext.identifier, ext.kind, isInstalledLocally, isInstalledRemotely, preference); + + runningLocation.set(ext.key, location); }); return runningLocation; diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 6398b447a1a..2ef2d31ac41 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -39,6 +39,7 @@ export interface IMessage { export const enum ExtensionRunningLocation { None, LocalProcess, + LocalNotebookProcess, LocalWebWorker, Remote } @@ -49,6 +50,8 @@ export function extensionRunningLocationToString(location: ExtensionRunningLocat return 'None'; case ExtensionRunningLocation.LocalProcess: return 'LocalProcess'; + case ExtensionRunningLocation.LocalNotebookProcess: + return 'NotebookProcess'; case ExtensionRunningLocation.LocalWebWorker: return 'LocalWebWorker'; case ExtensionRunningLocation.Remote: @@ -110,6 +113,7 @@ export interface IExtensionHostProfile { export const enum ExtensionHostKind { LocalProcess, LocalWebWorker, + LocalNotebook, Remote } @@ -117,6 +121,7 @@ export function extensionHostKindToString(kind: ExtensionHostKind): string { switch (kind) { case ExtensionHostKind.LocalProcess: return 'LocalProcess'; case ExtensionHostKind.LocalWebWorker: return 'LocalWebWorker'; + case ExtensionHostKind.LocalNotebook: return 'LocalNotebook'; case ExtensionHostKind.Remote: return 'Remote'; } } diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 783fe97db1d..9b0731cb92f 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -231,12 +231,28 @@ export class ExtensionService extends AbstractExtensionService implements IExten return (result.length > 0 ? result[0] : ExtensionRunningLocation.None); } + /** + * FYI. + * This is an experiment for running notebook extensions in a dedicated extension host to prevent it from being affected + * by starving extension host, or slowing down / blocking other extensions as it performs heavy compution when converting + * notebook output data from nbformat to vsbuffer (or vise versa). + * It's not an attempt to introduce a generic solution for running abitrary extensions in a dedicated extension host. + */ + private _isDedicatedNotebookExtensionHostExperimentEnabled() { + return this._configurationService.getValue('extensions.experimental.dedicatedNotebookProcess'); + } + protected _createExtensionHosts(isInitialStart: boolean): IExtensionHost[] { const result: IExtensionHost[] = []; - const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionRunningLocation.LocalProcess)); + const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, ExtensionHostKind.LocalProcess, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionRunningLocation.LocalProcess)); result.push(localProcessExtHost); + if (this._isDedicatedNotebookExtensionHostExperimentEnabled()) { + const notebookProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, ExtensionHostKind.LocalNotebook, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionRunningLocation.LocalNotebookProcess)); + result.push(notebookProcessExtHost); + } + if (this._enableLocalWebWorker) { const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, this._lazyLocalWebWorker, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionRunningLocation.LocalWebWorker)); result.push(webWorkerExtHost); @@ -475,10 +491,11 @@ export class ExtensionService extends AbstractExtensionService implements IExten // remove non-UI extensions from the local extensions const localProcessExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionRunningLocation.LocalProcess); + const loaclNotebookProcessExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionRunningLocation.LocalNotebookProcess); const localWebWorkerExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionRunningLocation.LocalWebWorker); remoteExtensions = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionRunningLocation.Remote); - const result = this._registry.deltaExtensions(remoteExtensions.concat(localProcessExtensions).concat(localWebWorkerExtensions), []); + const result = this._registry.deltaExtensions(remoteExtensions.concat(localProcessExtensions).concat(loaclNotebookProcessExtensions).concat(localWebWorkerExtensions), []); if (result.removedDueToLooping.length > 0) { this._logOrShowMessage(Severity.Error, nls.localize('looping', "The following extensions contain dependency loops and have been disabled: {0}", result.removedDueToLooping.map(e => `'${e.identifier.value}'`).join(', '))); } @@ -503,6 +520,11 @@ export class ExtensionService extends AbstractExtensionService implements IExten localProcessExtensionHost.start(localProcessExtensions.map(extension => extension.identifier).filter(id => this._registry.containsExtension(id))); } + const localNotebookExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalNotebook); + if (localNotebookExtensionHost) { + localNotebookExtensionHost.start(loaclNotebookProcessExtensions.map(extension => extension.identifier).filter(id => this._registry.containsExtension(id))); + } + const localWebWorkerExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalWebWorker); if (localWebWorkerExtensionHost) { localWebWorkerExtensionHost.start(localWebWorkerExtensions.map(extension => extension.identifier).filter(id => this._registry.containsExtension(id))); diff --git a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts index 79556450046..e9dc6541714 100644 --- a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts @@ -105,7 +105,6 @@ class ExtensionHostProcess { export class LocalProcessExtensionHost implements IExtensionHost { - public readonly kind = ExtensionHostKind.LocalProcess; public readonly remoteAuthority = null; public readonly lazyStart = false; @@ -135,6 +134,7 @@ export class LocalProcessExtensionHost implements IExtensionHost { private readonly _extensionHostLogFile: URI; constructor( + readonly kind: ExtensionHostKind, private readonly _initDataProvider: ILocalProcessExtensionHostDataProvider, @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService, @INotificationService private readonly _notificationService: INotificationService, From 5c20802742906dc9cd6aa225334033edf9dbc004 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 9 Mar 2022 21:42:59 +0100 Subject: [PATCH 083/175] Fixes #144518: Improve activation logic around handling dependencies --- .../api/common/extHostExtensionActivator.ts | 269 +++++++++--------- .../common/extHostExtensionActivator.test.ts | 25 ++ 2 files changed, 161 insertions(+), 133 deletions(-) diff --git a/src/vs/workbench/api/common/extHostExtensionActivator.ts b/src/vs/workbench/api/common/extHostExtensionActivator.ts index cbadfee1900..a0a16865ab2 100644 --- a/src/vs/workbench/api/common/extHostExtensionActivator.ts +++ b/src/vs/workbench/api/common/extHostExtensionActivator.ts @@ -10,8 +10,7 @@ import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/c import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { ExtensionActivationReason, MissingExtensionDependency } from 'vs/workbench/services/extensions/common/extensions'; import { ILogService } from 'vs/platform/log/common/log'; - -const NO_OP_VOID_PROMISE = Promise.resolve(undefined); +import { Barrier } from 'vs/base/common/async'; /** * Represents the source code (module) of an extension. @@ -166,14 +165,11 @@ type ActivationIdAndReason = { id: ExtensionIdentifier; reason: ExtensionActivat export class ExtensionsActivator implements IDisposable { - private _isDisposed: boolean; - private readonly _registry: ExtensionDescriptionRegistry; private readonly _resolvedExtensionsSet: Set; private readonly _externalExtensionsMap: Map; private readonly _host: IExtensionsActivatorHost; - private readonly _activatingExtensions: Map>; - private readonly _activatedExtensions: Map; + private readonly _operations: Map; /** * A map of already activated events to speed things up if the same activation event is triggered multiple times. */ @@ -186,126 +182,111 @@ export class ExtensionsActivator implements IDisposable { host: IExtensionsActivatorHost, @ILogService private readonly _logService: ILogService ) { - this._isDisposed = false; this._registry = registry; this._resolvedExtensionsSet = new Set(); resolvedExtensions.forEach((extensionId) => this._resolvedExtensionsSet.add(ExtensionIdentifier.toKey(extensionId))); this._externalExtensionsMap = new Map(); externalExtensions.forEach((extensionId) => this._externalExtensionsMap.set(ExtensionIdentifier.toKey(extensionId), extensionId)); this._host = host; - this._activatingExtensions = new Map>(); - this._activatedExtensions = new Map(); + this._operations = new Map(); this._alreadyActivatedEvents = Object.create(null); } public dispose(): void { - this._isDisposed = true; + for (const [_, op] of this._operations) { + op.dispose(); + } } public isActivated(extensionId: ExtensionIdentifier): boolean { - const extensionKey = ExtensionIdentifier.toKey(extensionId); - - return this._activatedExtensions.has(extensionKey); + const op = this._operations.get(ExtensionIdentifier.toKey(extensionId)); + return Boolean(op && op.value); } public getActivatedExtension(extensionId: ExtensionIdentifier): ActivatedExtension { - const extensionKey = ExtensionIdentifier.toKey(extensionId); - - const activatedExtension = this._activatedExtensions.get(extensionKey); - if (!activatedExtension) { - throw new Error('Extension `' + extensionId.value + '` is not known or not activated'); + const op = this._operations.get(ExtensionIdentifier.toKey(extensionId)); + if (!op || !op.value) { + throw new Error(`Extension '${extensionId.value}' is not known or not activated`); } - return activatedExtension; + return op.value; } - public activateByEvent(activationEvent: string, startup: boolean): Promise { + public async activateByEvent(activationEvent: string, startup: boolean): Promise { if (this._alreadyActivatedEvents[activationEvent]) { - return NO_OP_VOID_PROMISE; + return; } + const activateExtensions = this._registry.getExtensionDescriptionsForActivationEvent(activationEvent); - return this._activateExtensions(activateExtensions.map(e => ({ + await this._activateExtensions(activateExtensions.map(e => ({ id: e.identifier, reason: { startup, extensionId: e.identifier, activationEvent } - }))).then(() => { - this._alreadyActivatedEvents[activationEvent] = true; - }); + }))); + + this._alreadyActivatedEvents[activationEvent] = true; } public activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise { const desc = this._registry.getExtensionDescription(extensionId); if (!desc) { - throw new Error('Extension `' + extensionId + '` is not known'); + throw new Error(`Extension '${extensionId}' is not known`); } + return this._activateExtensions([{ id: desc.identifier, reason }]); + } - return this._activateExtensions([{ - id: desc.identifier, - reason - }]); + private async _activateExtensions(extensions: ActivationIdAndReason[]): Promise { + const operations = extensions + .filter((p) => !this.isActivated(p.id)) + .map(ext => this._handleActivationRequest(ext)); + await Promise.all(operations.map(op => op.wait())); } /** * Handle semantics related to dependencies for `currentExtension`. - * semantics: `redExtensions` must wait for `greenExtensions`. + * We don't need to worry about dependency loops because they are handled by the registry. */ - private _handleActivateRequest(currentActivation: ActivationIdAndReason, greenExtensions: { [id: string]: ActivationIdAndReason }, redExtensions: ActivationIdAndReason[]): void { + private _handleActivationRequest(currentActivation: ActivationIdAndReason): ActivationOperation { + if (this._operations.has(ExtensionIdentifier.toKey(currentActivation.id))) { + return this._operations.get(ExtensionIdentifier.toKey(currentActivation.id))!; + } + if (this._externalExtensionsMap.has(ExtensionIdentifier.toKey(currentActivation.id))) { - greenExtensions[ExtensionIdentifier.toKey(currentActivation.id)] = currentActivation; - return; + return this._createAndSaveOperation(currentActivation, null, [], null); } const currentExtension = this._registry.getExtensionDescription(currentActivation.id); if (!currentExtension) { // Error condition 0: unknown extension const error = new Error(`Cannot activate unknown extension '${currentActivation.id.value}'`); + const result = this._createAndSaveOperation(currentActivation, null, [], new FailedExtension(error)); this._host.onExtensionActivationError( currentActivation.id, error, new MissingExtensionDependency(currentActivation.id.value) ); - this._activatedExtensions.set(ExtensionIdentifier.toKey(currentActivation.id), new FailedExtension(error)); - return; + return result; } + const deps: ActivationOperation[] = []; const depIds = (typeof currentExtension.extensionDependencies === 'undefined' ? [] : currentExtension.extensionDependencies); - let currentExtensionGetsGreenLight = true; - - for (let j = 0, lenJ = depIds.length; j < lenJ; j++) { - const depId = depIds[j]; + for (const depId of depIds) { if (this._resolvedExtensionsSet.has(ExtensionIdentifier.toKey(depId))) { // This dependency is already resolved continue; } - const dep = this._activatedExtensions.get(ExtensionIdentifier.toKey(depId)); - if (dep && !dep.activationFailed) { - // the dependency is already activated OK + const dep = this._operations.get(ExtensionIdentifier.toKey(depId)); + if (dep) { + deps.push(dep); continue; } - if (dep && dep.activationFailed) { - // Error condition 2: a dependency has already failed activation - const currentExtensionFriendlyName = currentExtension.displayName || currentExtension.identifier.value; - const depDesc = this._registry.getExtensionDescription(depId); - const depFriendlyName = (depDesc ? depDesc.displayName || depId : depId); - const error = new Error(`Cannot activate the '${currentExtensionFriendlyName}' extension because its dependency '${depFriendlyName}' failed to activate`); - (error).detail = dep.activationFailedError; - this._host.onExtensionActivationError( - currentExtension.identifier, - error, - null - ); - this._activatedExtensions.set(ExtensionIdentifier.toKey(currentExtension.identifier), new FailedExtension(error)); - return; - } - if (this._externalExtensionsMap.has(ExtensionIdentifier.toKey(depId))) { // must first wait for the dependency to activate - currentExtensionGetsGreenLight = false; - greenExtensions[ExtensionIdentifier.toKey(depId)] = { + deps.push(this._handleActivationRequest({ id: this._externalExtensionsMap.get(ExtensionIdentifier.toKey(depId))!, reason: currentActivation.reason - }; + })); continue; } @@ -317,118 +298,140 @@ export class ExtensionsActivator implements IDisposable { } // must first wait for the dependency to activate - currentExtensionGetsGreenLight = false; - greenExtensions[ExtensionIdentifier.toKey(depId)] = { + deps.push(this._handleActivationRequest({ id: depDesc.identifier, reason: currentActivation.reason - }; + })); continue; } // Error condition 1: unknown dependency const currentExtensionFriendlyName = currentExtension.displayName || currentExtension.identifier.value; const error = new Error(`Cannot activate the '${currentExtensionFriendlyName}' extension because it depends on unknown extension '${depId}'`); + const result = this._createAndSaveOperation(currentActivation, currentExtension.displayName, [], new FailedExtension(error)); this._host.onExtensionActivationError( currentExtension.identifier, error, new MissingExtensionDependency(depId) ); - this._activatedExtensions.set(ExtensionIdentifier.toKey(currentExtension.identifier), new FailedExtension(error)); + return result; + } + + return this._createAndSaveOperation(currentActivation, currentExtension.displayName, deps, null); + } + + private _createAndSaveOperation(activation: ActivationIdAndReason, displayName: string | null | undefined, deps: ActivationOperation[], value: ActivatedExtension | null): ActivationOperation { + const operation = new ActivationOperation(activation.id, displayName, activation.reason, deps, value, this._host, this._logService); + this._operations.set(ExtensionIdentifier.toKey(activation.id), operation); + return operation; + } +} + +class ActivationOperation { + + private readonly _barrier = new Barrier(); + private _isDisposed = false; + + public get value(): ActivatedExtension | null { + return this._value; + } + + public get friendlyName(): string { + return this._displayName || this._id.value; + } + + constructor( + private readonly _id: ExtensionIdentifier, + private readonly _displayName: string | null | undefined, + private readonly _reason: ExtensionActivationReason, + private readonly _deps: ActivationOperation[], + private _value: ActivatedExtension | null, + private readonly _host: IExtensionsActivatorHost, + @ILogService private readonly _logService: ILogService + ) { + this._initialize(); + } + + public dispose(): void { + this._isDisposed = true; + } + + public wait() { + return this._barrier.wait(); + } + + private async _initialize(): Promise { + await this._waitForDepsThenActivate(); + this._barrier.open(); + } + + private async _waitForDepsThenActivate(): Promise { + if (this._value) { + // this operation is already finished return; } - if (currentExtensionGetsGreenLight) { - greenExtensions[ExtensionIdentifier.toKey(currentExtension.identifier)] = currentActivation; - } else { - redExtensions.push(currentActivation); - } - } + while (this._deps.length > 0) { + // remove completed deps + for (let i = 0; i < this._deps.length; i++) { + const dep = this._deps[i]; - private _activateExtensions(extensions: ActivationIdAndReason[]): Promise { - if (extensions.length === 0) { - return Promise.resolve(undefined); - } + if (dep.value && !dep.value.activationFailed) { + // the dependency is already activated OK + this._deps.splice(i, 1); + i--; + continue; + } - extensions = extensions.filter((p) => !this._activatedExtensions.has(ExtensionIdentifier.toKey(p.id))); - if (extensions.length === 0) { - return Promise.resolve(undefined); - } + if (dep.value && dep.value.activationFailed) { + // Error condition 2: a dependency has already failed activation + const error = new Error(`Cannot activate the '${this.friendlyName}' extension because its dependency '${dep.friendlyName}' failed to activate`); + (error).detail = dep.value.activationFailedError; + this._value = new FailedExtension(error); + this._host.onExtensionActivationError(this._id, error, null); + return; + } + } - const greenMap: { [id: string]: ActivationIdAndReason } = Object.create(null), - red: ActivationIdAndReason[] = []; - - for (let i = 0, len = extensions.length; i < len; i++) { - this._handleActivateRequest(extensions[i], greenMap, red); - } - - // Make sure no red is also green - for (let i = 0, len = red.length; i < len; i++) { - const redExtensionKey = ExtensionIdentifier.toKey(red[i].id); - if (greenMap[redExtensionKey]) { - delete greenMap[redExtensionKey]; + if (this._deps.length > 0) { + // wait for one dependency + await Promise.race(this._deps.map(dep => dep.wait())); } } - const green = Object.keys(greenMap).map(id => greenMap[id]); - - if (red.length === 0) { - // Finally reached only leafs! - return Promise.all(green.map((p) => this._activateExtension(p.id, p.reason))).then(_ => undefined); - } - - return this._activateExtensions(green).then(_ => { - return this._activateExtensions(red); - }); + await this._activate(); } - private _activateExtension(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise { - const extensionKey = ExtensionIdentifier.toKey(extensionId); - - if (this._activatedExtensions.has(extensionKey)) { - return Promise.resolve(undefined); - } - - const currentlyActivatingExtension = this._activatingExtensions.get(extensionKey); - if (currentlyActivatingExtension) { - return currentlyActivatingExtension; - } - - const newlyActivatingExtension = this._host.actualActivateExtension(extensionId, reason).then(undefined, (err) => { + private async _activate(): Promise { + try { + this._value = await this._host.actualActivateExtension(this._id, this._reason); + } catch (err) { const error = new Error(); if (err && err.name) { error.name = err.name; } if (err && err.message) { - error.message = `Activating extension '${extensionId.value}' failed: ${err.message}.`; + error.message = `Activating extension '${this._id.value}' failed: ${err.message}.`; } else { - error.message = `Activating extension '${extensionId.value}' failed: ${err}.`; + error.message = `Activating extension '${this._id.value}' failed: ${err}.`; } if (err && err.stack) { error.stack = err.stack; } + // Treat the extension as being empty + this._value = new FailedExtension(error); + if (this._isDisposed && errors.isCancellationError(err)) { // It is expected for ongoing activations to fail if the extension host is going down // So simply ignore and don't log canceled errors in this case - return new FailedExtension(err); + return; } - this._host.onExtensionActivationError( - extensionId, - error, - null - ); - this._logService.error(`Activating extension ${extensionId.value} failed due to an error:`); + this._host.onExtensionActivationError(this._id, error, null); + this._logService.error(`Activating extension ${this._id.value} failed due to an error:`); this._logService.error(err); - // Treat the extension as being empty - return new FailedExtension(err); - }).then((x: ActivatedExtension) => { - this._activatedExtensions.set(extensionKey, x); - this._activatingExtensions.delete(extensionKey); - }); - - this._activatingExtensions.set(extensionKey, newlyActivatingExtension); - return newlyActivatingExtension; + } } } diff --git a/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts b/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts index 91f286d238d..18850a98dd2 100644 --- a/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts +++ b/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts @@ -164,6 +164,31 @@ suite('ExtensionsActivator', () => { assert.deepStrictEqual(host.errors[1][0], idA); }); + test('issue #144518: Problem with git extension and vscode-icons', async () => { + const extActivationA = new ExtensionActivationPromiseSource(); + const extActivationB = new ExtensionActivationPromiseSource(); + const extActivationC = new ExtensionActivationPromiseSource(); + const host = new PromiseExtensionsActivatorHost([ + [idA, extActivationA], + [idB, extActivationB], + [idC, extActivationC] + ]); + const activator = createActivator(host, [ + desc(idA, [idB]), + desc(idB), + desc(idC), + ]); + + activator.activateByEvent('*', false); + assert.deepStrictEqual(host.activateCalls, [idB, idC]); + + extActivationB.resolve(); + await timeout(0); + + assert.deepStrictEqual(host.activateCalls, [idB, idC, idA]); + extActivationA.resolve(); + }); + class SimpleExtensionsActivatorHost implements IExtensionsActivatorHost { public readonly activateCalls: ExtensionIdentifier[] = []; public readonly errors: [ExtensionIdentifier, Error | null, MissingExtensionDependency | null][] = []; From d282cd8625d25631f655709ed28e27edad2e3ad8 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 9 Mar 2022 22:11:16 +0100 Subject: [PATCH 084/175] consider target platform while installing, uninstalling and loading extensions --- .../abstractExtensionManagementService.ts | 15 ++++--- .../common/extensionManagementUtil.ts | 30 +++++++++---- .../node/extensionDownloader.ts | 16 +++---- .../node/extensionManagementService.ts | 44 +++++++++---------- .../node/extensionsScanner.ts | 35 +++++++-------- .../platform/extensions/common/extensions.ts | 2 + .../browser/extensionsWorkbenchService.ts | 20 ++++----- .../extensions/common/extensionPoints.ts | 5 ++- 8 files changed, 87 insertions(+), 80 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts index 7f175cb3ab6..ab363c1457d 100644 --- a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts +++ b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts @@ -17,7 +17,7 @@ import { DidUninstallExtensionEvent, ExtensionManagementError, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementParticipant, IExtensionManagementService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallExtensionEvent, InstallExtensionResult, InstallOperation, InstallOptions, InstallVSIXOptions, IExtensionsControlManifest, StatisticType, UninstallOptions, TargetPlatform, isTargetPlatformCompatible, TargetPlatformToString, ExtensionManagementErrorCode } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { areSameExtensions, ExtensionIdentifierWithVersion, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { areSameExtensions, ExtensionKey, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; import { ILogService } from 'vs/platform/log/common/log'; import { IProductService } from 'vs/platform/product/common/productService'; @@ -138,7 +138,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl protected async installExtension(manifest: IExtensionManifest, extension: URI | IGalleryExtension, options: InstallOptions & InstallVSIXOptions): Promise { // only cache gallery extensions tasks if (!URI.isUri(extension)) { - let installExtensionTask = this.installingExtensions.get(new ExtensionIdentifierWithVersion(extension.identifier, extension.version).key()); + let installExtensionTask = this.installingExtensions.get(ExtensionKey.create(extension).toString()); if (installExtensionTask) { this.logService.info('Extensions is already requested to install', extension.identifier.id); return installExtensionTask.waitUntilTaskIsFinished(); @@ -150,7 +150,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl const installResults: (InstallExtensionResult & { local: ILocalExtension })[] = []; const installExtensionTask = this.createInstallExtensionTask(manifest, extension, options); if (!URI.isUri(extension)) { - this.installingExtensions.set(new ExtensionIdentifierWithVersion(installExtensionTask.identifier, manifest.version).key(), installExtensionTask); + this.installingExtensions.set(ExtensionKey.create(extension).toString(), installExtensionTask); } this._onInstallExtension.fire({ identifier: installExtensionTask.identifier, source: extension }); this.logService.info('Installing extension:', installExtensionTask.identifier.id); @@ -165,11 +165,12 @@ export abstract class AbstractExtensionManagementService extends Disposable impl const allDepsAndPackExtensionsToInstall = await this.getAllDepsAndPackExtensionsToInstall(installExtensionTask.identifier, manifest, !!options.installOnlyNewlyAddedFromExtensionPack, !!options.installPreReleaseVersion); for (const { gallery, manifest } of allDepsAndPackExtensionsToInstall) { installExtensionHasDependents = installExtensionHasDependents || !!manifest.extensionDependencies?.some(id => areSameExtensions({ id }, installExtensionTask.identifier)); - if (this.installingExtensions.has(new ExtensionIdentifierWithVersion(gallery.identifier, gallery.version).key())) { + const key = ExtensionKey.create(gallery).toString(); + if (this.installingExtensions.has(key)) { this.logService.info('Extension is already requested to install', gallery.identifier.id); } else { const task = this.createInstallExtensionTask(manifest, gallery, { ...options, donotIncludePackAndDependencies: true }); - this.installingExtensions.set(new ExtensionIdentifierWithVersion(task.identifier, manifest.version).key(), task); + this.installingExtensions.set(key, task); this._onInstallExtension.fire({ identifier: task.identifier, source: gallery }); this.logService.info('Installing extension:', task.identifier.id); allInstallExtensionTasks.push({ task, manifest }); @@ -268,9 +269,9 @@ export abstract class AbstractExtensionManagementService extends Disposable impl throw error; } finally { /* Remove the gallery tasks from the cache */ - for (const { task, manifest } of allInstallExtensionTasks) { + for (const { task } of allInstallExtensionTasks) { if (!URI.isUri(task.source)) { - const key = new ExtensionIdentifierWithVersion(task.identifier, manifest.version).key(); + const key = ExtensionKey.create(task.source).toString(); if (!this.installingExtensions.delete(key)) { this.logService.warn('Installation task is not found in the cache', key); } diff --git a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts index c38d117ec20..66c2b407a10 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { compareIgnoreCase } from 'vs/base/common/strings'; -import { IExtensionIdentifier, IGalleryExtension, ILocalExtension, IExtensionsControlManifest } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionIdentifier, IGalleryExtension, ILocalExtension, IExtensionsControlManifest, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionIdentifier, IExtension } from 'vs/platform/extensions/common/extensions'; export function areSameExtensions(a: IExtensionIdentifier, b: IExtensionIdentifier): boolean { @@ -17,28 +17,40 @@ export function areSameExtensions(a: IExtensionIdentifier, b: IExtensionIdentifi return compareIgnoreCase(a.id, b.id) === 0; } -export class ExtensionIdentifierWithVersion { +const ExtensionKeyRegex = /^([^.]+\..+)-(\d+\.\d+\.\d+)(-(.+))?$/; + +export class ExtensionKey { + + static create(extension: ILocalExtension | IGalleryExtension): ExtensionKey { + const version = (extension as ILocalExtension).manifest ? (extension as ILocalExtension).manifest.version : (extension as IGalleryExtension).version; + const targetPlatform = (extension as ILocalExtension).targetPlatform ? (extension as ILocalExtension).targetPlatform : (extension as IGalleryExtension).properties.targetPlatform; + return new ExtensionKey(extension.identifier, version, targetPlatform); + } + + static parse(key: string): ExtensionKey | null { + const matches = ExtensionKeyRegex.exec(key); + return matches && matches[1] && matches[2] ? new ExtensionKey({ id: matches[1] }, matches[2], matches[3] as TargetPlatform || undefined) : null; + } readonly id: string; - readonly uuid?: string; constructor( identifier: IExtensionIdentifier, - readonly version: string + readonly version: string, + readonly targetPlatform: TargetPlatform = TargetPlatform.UNDEFINED, ) { this.id = identifier.id; - this.uuid = identifier.uuid; } - key(): string { - return `${this.id}-${this.version}`; + toString(): string { + return `${this.id}-${this.version}${this.targetPlatform !== TargetPlatform.UNDEFINED ? `-${this.targetPlatform}` : ''}`; } equals(o: any): boolean { - if (!(o instanceof ExtensionIdentifierWithVersion)) { + if (!(o instanceof ExtensionKey)) { return false; } - return areSameExtensions(this, o) && this.version === o.version; + return areSameExtensions(this, o) && this.version === o.version && this.targetPlatform === o.targetPlatform; } } diff --git a/src/vs/platform/extensionManagement/node/extensionDownloader.ts b/src/vs/platform/extensionManagement/node/extensionDownloader.ts index f7efcb113af..c37857b3dce 100644 --- a/src/vs/platform/extensionManagement/node/extensionDownloader.ts +++ b/src/vs/platform/extensionManagement/node/extensionDownloader.ts @@ -13,13 +13,11 @@ import { URI } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; import { Promises as FSPromises } from 'vs/base/node/pfs'; import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IExtensionGalleryService, IGalleryExtension, InstallOperation, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { ExtensionIdentifierWithVersion, groupByExtension } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { IExtensionGalleryService, IGalleryExtension, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionKey, groupByExtension } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IFileService, IFileStatWithMetadata } from 'vs/platform/files/common/files'; import { ILogService } from 'vs/platform/log/common/log'; -const ExtensionIdVersionRegex = /^([^.]+\..+)-(\d+\.\d+\.\d+)$/; - export class ExtensionsDownloader extends Disposable { private readonly extensionsDownloadDir: URI; @@ -97,9 +95,9 @@ export class ExtensionsDownloader extends Disposable { const folderStat = await this.fileService.resolve(this.extensionsDownloadDir, { resolveMetadata: true }); if (folderStat.children) { const toDelete: URI[] = []; - const all: [ExtensionIdentifierWithVersion, IFileStatWithMetadata][] = []; + const all: [ExtensionKey, IFileStatWithMetadata][] = []; for (const stat of folderStat.children) { - const extension = this.parse(stat.name); + const extension = ExtensionKey.parse(stat.name); if (extension) { all.push([extension, stat]); } @@ -124,11 +122,7 @@ export class ExtensionsDownloader extends Disposable { } private getName(extension: IGalleryExtension): string { - return this.cache ? `${new ExtensionIdentifierWithVersion(extension.identifier, extension.version).key().toLowerCase()}${extension.properties.targetPlatform !== TargetPlatform.UNDEFINED ? `-${extension.properties.targetPlatform}` : ''}` : generateUuid(); + return this.cache ? ExtensionKey.create(extension).toString().toLowerCase() : generateUuid(); } - private parse(name: string): ExtensionIdentifierWithVersion | null { - const matches = ExtensionIdVersionRegex.exec(name); - return matches && matches[1] && matches[2] ? new ExtensionIdentifierWithVersion({ id: matches[1] }, matches[2]) : null; - } } diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 98a4571640e..d946e6a4941 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -25,7 +25,7 @@ import { ExtensionManagementError, ExtensionManagementErrorCode, getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallOperation, InstallOptions, InstallVSIXOptions, Metadata, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { areSameExtensions, ExtensionIdentifierWithVersion, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { areSameExtensions, ExtensionKey, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionsDownloader } from 'vs/platform/extensionManagement/node/extensionDownloader'; import { ExtensionsLifecycle } from 'vs/platform/extensionManagement/node/extensionLifecycle'; import { getManifest } from 'vs/platform/extensionManagement/node/extensionManagementUtil'; @@ -43,7 +43,7 @@ import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity' interface InstallableExtension { zipPath: string; - identifierWithVersion: ExtensionIdentifierWithVersion; + key: ExtensionKey; metadata?: Metadata; } @@ -229,7 +229,7 @@ abstract class AbstractInstallExtensionTask extends AbstractExtensionTask { try { - const local = await this.unsetUninstalledAndGetLocal(installableExtension.identifierWithVersion); + const local = await this.unsetUninstalledAndGetLocal(installableExtension.key); if (local) { return installableExtension.metadata ? this.extensionsScanner.saveMetadataForLocalExtension(local, { ...((local.manifest).__metadata || {}), ...installableExtension.metadata }) : local; } @@ -243,28 +243,28 @@ abstract class AbstractInstallExtensionTask extends AbstractExtensionTask { - const isUninstalled = await this.isUninstalled(identifierWithVersion); + protected async unsetUninstalledAndGetLocal(extensionKey: ExtensionKey): Promise { + const isUninstalled = await this.isUninstalled(extensionKey); if (!isUninstalled) { return null; } - this.logService.trace('Removing the extension from uninstalled list:', identifierWithVersion.id); + this.logService.trace('Removing the extension from uninstalled list:', extensionKey.id); // If the same version of extension is marked as uninstalled, remove it from there and return the local. - const local = await this.extensionsScanner.setInstalled(identifierWithVersion); - this.logService.info('Removed the extension from uninstalled list:', identifierWithVersion.id); + const local = await this.extensionsScanner.setInstalled(extensionKey); + this.logService.info('Removed the extension from uninstalled list:', extensionKey.id); return local; } - private async isUninstalled(identifier: ExtensionIdentifierWithVersion): Promise { + private async isUninstalled(extensionId: ExtensionKey): Promise { const uninstalled = await this.extensionsScanner.getUninstalledExtensions(); - return !!uninstalled[identifier.key()]; + return !!uninstalled[extensionId.toString()]; } - private async extract({ zipPath, identifierWithVersion, metadata }: InstallableExtension, token: CancellationToken): Promise { - let local = await this.extensionsScanner.extractUserExtension(identifierWithVersion, zipPath, metadata, token); - this.logService.info('Extracting completed.', identifierWithVersion.id); + private async extract({ zipPath, key, metadata }: InstallableExtension, token: CancellationToken): Promise { + let local = await this.extensionsScanner.extractUserExtension(key, zipPath, metadata, token); + this.logService.info('Extracting completed.', key.id); return local; } @@ -300,7 +300,7 @@ class InstallGalleryExtensionTask extends AbstractInstallExtensionTask { try { const local = await this.installExtension(installableExtension, token); - if (existingExtension && semver.neq(existingExtension.manifest.version, this.gallery.version)) { + if (existingExtension && (existingExtension.targetPlatform !== local.targetPlatform || semver.neq(existingExtension.manifest.version, local.manifest.version))) { await this.extensionsScanner.setUninstalled(existingExtension); } return local; @@ -337,8 +337,8 @@ class InstallGalleryExtensionTask extends AbstractInstallExtensionTask { } try { - const manifest = await getManifest(zipPath); - return (>{ zipPath, identifierWithVersion: new ExtensionIdentifierWithVersion(extension.identifier, manifest.version), metadata }); + await getManifest(zipPath); + return (>{ zipPath, key: ExtensionKey.create(extension), metadata }); } catch (error) { await this.deleteDownloadedVSIX(zipPath); throw new ExtensionManagementError(joinErrors(error).message, ExtensionManagementErrorCode.Invalid); @@ -360,7 +360,7 @@ class InstallVSIXTask extends AbstractInstallExtensionTask { } protected async doRun(token: CancellationToken): Promise { - const identifierWithVersion = new ExtensionIdentifierWithVersion(this.identifier, this.manifest.version); + const extensionKey = new ExtensionKey(this.identifier, this.manifest.version); const installedExtensions = await this.extensionsScanner.scanExtensions(ExtensionType.User); const existing = installedExtensions.find(i => areSameExtensions(this.identifier, i.identifier)); const metadata = await this.getMetadata(this.identifier.id, this.manifest.version, token); @@ -369,7 +369,7 @@ class InstallVSIXTask extends AbstractInstallExtensionTask { if (existing) { this._operation = InstallOperation.Update; - if (identifierWithVersion.equals(new ExtensionIdentifierWithVersion(existing.identifier, existing.manifest.version))) { + if (extensionKey.equals(new ExtensionKey(existing.identifier, existing.manifest.version))) { try { await this.extensionsScanner.removeExtension(existing, 'existing'); } catch (e) { @@ -381,7 +381,7 @@ class InstallVSIXTask extends AbstractInstallExtensionTask { } else { // Remove the extension with same version if it is already uninstalled. // Installing a VSIX extension shall replace the existing extension always. - const existing = await this.unsetUninstalledAndGetLocal(identifierWithVersion); + const existing = await this.unsetUninstalledAndGetLocal(extensionKey); if (existing) { try { await this.extensionsScanner.removeExtension(existing, 'existing'); @@ -391,7 +391,7 @@ class InstallVSIXTask extends AbstractInstallExtensionTask { } } - return this.installExtension({ zipPath: path.resolve(this.location.fsPath), identifierWithVersion, metadata }, token); + return this.installExtension({ zipPath: path.resolve(this.location.fsPath), key: extensionKey, metadata }, token); } private async getMetadata(id: string, version: string, token: CancellationToken): Promise { @@ -428,8 +428,8 @@ class UninstallExtensionTask extends AbstractExtensionTask implements IUni const toUninstall: ILocalExtension[] = []; const userExtensions = await this.extensionsScanner.scanUserExtensions(false); if (this.options.versionOnly) { - const extensionIdentifierWithVersion = new ExtensionIdentifierWithVersion(this.extension.identifier, this.extension.manifest.version); - toUninstall.push(...userExtensions.filter(u => extensionIdentifierWithVersion.equals(new ExtensionIdentifierWithVersion(u.identifier, u.manifest.version)))); + const extensionKey = ExtensionKey.create(this.extension); + toUninstall.push(...userExtensions.filter(u => extensionKey.equals(ExtensionKey.create(u)))); } else { toUninstall.push(...userExtensions.filter(u => areSameExtensions(u.identifier, this.extension.identifier))); } diff --git a/src/vs/platform/extensionManagement/node/extensionsScanner.ts b/src/vs/platform/extensionManagement/node/extensionsScanner.ts index 07b924e45bd..99a6e495a50 100644 --- a/src/vs/platform/extensionManagement/node/extensionsScanner.ts +++ b/src/vs/platform/extensionManagement/node/extensionsScanner.ts @@ -21,7 +21,7 @@ import { extract, ExtractError } from 'vs/base/node/zip'; import { localize } from 'vs/nls'; import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; import { ExtensionManagementError, ExtensionManagementErrorCode, Metadata, ILocalExtension, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { areSameExtensions, ExtensionIdentifierWithVersion, getGalleryExtensionId, groupByExtension } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { areSameExtensions, ExtensionKey, getGalleryExtensionId, groupByExtension } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls'; import { ExtensionType, IExtensionIdentifier, IExtensionManifest, UNDEFINED_PUBLISHER } from 'vs/platform/extensions/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; @@ -80,7 +80,7 @@ export class ExtensionsScanner extends Disposable { async scanUserExtensions(excludeOutdated: boolean): Promise { this.logService.trace('Started scanning user extensions'); let [uninstalled, extensions] = await Promise.all([this.getUninstalledExtensions(), this.scanAllUserExtensions()]); - extensions = extensions.filter(e => !uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]); + extensions = extensions.filter(e => !uninstalled[ExtensionKey.create(e).toString()]); if (excludeOutdated) { const byExtension: ILocalExtension[][] = groupByExtension(extensions, e => e.identifier); extensions = byExtension.map(p => p.sort((a, b) => semver.rcompare(a.manifest.version, b.manifest.version))[0]); @@ -93,21 +93,18 @@ export class ExtensionsScanner extends Disposable { return this.scanExtensionsInDir(this.extensionsPath, ExtensionType.User); } - async extractUserExtension(identifierWithVersion: ExtensionIdentifierWithVersion, zipPath: string, metadata: Metadata | undefined, token: CancellationToken): Promise { - const folderName = identifierWithVersion.key(); + async extractUserExtension(extensionKey: ExtensionKey, zipPath: string, metadata: Metadata | undefined, token: CancellationToken): Promise { + const folderName = extensionKey.toString(); const tempPath = path.join(this.extensionsPath, `.${generateUuid()}`); const extensionPath = path.join(this.extensionsPath, folderName); try { await pfs.Promises.rm(extensionPath); } catch (error) { - try { - await pfs.Promises.rm(extensionPath); - } catch (e) { /* ignore */ } - throw new ExtensionManagementError(localize('errorDeleting', "Unable to delete the existing folder '{0}' while installing the extension '{1}'. Please delete the folder manually and try again", extensionPath, identifierWithVersion.id), ExtensionManagementErrorCode.Delete); + throw new ExtensionManagementError(localize('errorDeleting', "Unable to delete the existing folder '{0}' while installing the extension '{1}'. Please delete the folder manually and try again", extensionPath, extensionKey.id), ExtensionManagementErrorCode.Delete); } - await this.extractAtLocation(identifierWithVersion, zipPath, tempPath, token); + await this.extractAtLocation(extensionKey, zipPath, tempPath, token); let local = await this.scanExtension(URI.file(tempPath), ExtensionType.User); if (!local) { throw new Error(localize('cannot read', "Cannot read the extension from {0}", tempPath)); @@ -115,14 +112,14 @@ export class ExtensionsScanner extends Disposable { await this.storeMetadata(local, { ...metadata, installedTimestamp: Date.now() }); try { - await this.rename(identifierWithVersion, tempPath, extensionPath, Date.now() + (2 * 60 * 1000) /* Retry for 2 minutes */); + await this.rename(extensionKey, tempPath, extensionPath, Date.now() + (2 * 60 * 1000) /* Retry for 2 minutes */); this.logService.info('Renamed to', extensionPath); } catch (error) { try { await pfs.Promises.rm(tempPath); } catch (e) { /* ignore */ } if (error.code === 'ENOTEMPTY') { - this.logService.info(`Rename failed because extension was installed by another source. So ignoring renaming.`, identifierWithVersion.id); + this.logService.info(`Rename failed because extension was installed by another source. So ignoring renaming.`, extensionKey.id); } else { this.logService.info(`Rename failed because of ${getErrorMessage(error)}. Deleted from extracted location`, tempPath); throw error; @@ -163,16 +160,16 @@ export class ExtensionsScanner extends Disposable { } async setUninstalled(...extensions: ILocalExtension[]): Promise { - const ids: ExtensionIdentifierWithVersion[] = extensions.map(e => new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version)); + const extensionKeys: ExtensionKey[] = extensions.map(e => ExtensionKey.create(e)); await this.withUninstalledExtensions(uninstalled => { - ids.forEach(id => uninstalled[id.key()] = true); + extensionKeys.forEach(extensionKey => uninstalled[extensionKey.toString()] = true); }); } - async setInstalled(identifierWithVersion: ExtensionIdentifierWithVersion): Promise { - await this.withUninstalledExtensions(uninstalled => delete uninstalled[identifierWithVersion.key()]); + async setInstalled(extensionKey: ExtensionKey): Promise { + await this.withUninstalledExtensions(uninstalled => delete uninstalled[extensionKey.toString()]); const installed = await this.scanExtensions(ExtensionType.User); - const localExtension = installed.find(i => new ExtensionIdentifierWithVersion(i.identifier, i.manifest.version).equals(identifierWithVersion)) || null; + const localExtension = installed.find(i => ExtensionKey.create(i).equals(extensionKey)) || null; if (!localExtension) { return null; } @@ -219,7 +216,7 @@ export class ExtensionsScanner extends Disposable { async removeUninstalledExtension(extension: ILocalExtension): Promise { await this.removeExtension(extension, 'uninstalled'); - await this.withUninstalledExtensions(uninstalled => delete uninstalled[new ExtensionIdentifierWithVersion(extension.identifier, extension.manifest.version).key()]); + await this.withUninstalledExtensions(uninstalled => delete uninstalled[ExtensionKey.create(extension).toString()]); } private async extractAtLocation(identifier: IExtensionIdentifier, zipPath: string, location: string, token: CancellationToken): Promise { @@ -344,7 +341,7 @@ export class ExtensionsScanner extends Disposable { const extensions = await this.scanAllUserExtensions(); // All user extensions const installed: Set = new Set(); for (const e of extensions) { - if (!uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]) { + if (!uninstalled[ExtensionKey.create(e).toString()]) { installed.add(e.identifier.id.toLowerCase()); } } @@ -355,7 +352,7 @@ export class ExtensionsScanner extends Disposable { await this.beforeRemovingExtension(latest); } })); - const toRemove: ILocalExtension[] = extensions.filter(e => uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]); + const toRemove: ILocalExtension[] = extensions.filter(e => uninstalled[ExtensionKey.create(e).toString()]); await Promises.settled(toRemove.map(e => this.removeUninstalledExtension(e))); } diff --git a/src/vs/platform/extensions/common/extensions.ts b/src/vs/platform/extensions/common/extensions.ts index 5aa0a9b745e..cfa20e0799d 100644 --- a/src/vs/platform/extensions/common/extensions.ts +++ b/src/vs/platform/extensions/common/extensions.ts @@ -6,6 +6,7 @@ import * as strings from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { ExtensionKind } from 'vs/platform/environment/common/environment'; +import { TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { getRemoteName } from 'vs/platform/remote/common/remoteHosts'; @@ -355,6 +356,7 @@ export class ExtensionIdentifier { export interface IExtensionDescription extends IExtensionManifest { readonly identifier: ExtensionIdentifier; readonly uuid?: string; + readonly targetPlatform?: TargetPlatform; readonly isBuiltin: boolean; readonly isUserBuiltin: boolean; readonly isUnderDevelopment: boolean; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 264bb9fbc74..1f50eb92db9 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -18,7 +18,7 @@ import { IExtensionsControlManifest, InstallVSIXOptions, IExtensionInfo, IExtensionQueryOptions, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService, DefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; -import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, groupByExtension, ExtensionIdentifierWithVersion, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, groupByExtension, ExtensionKey, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IHostService } from 'vs/workbench/services/host/browser/host'; @@ -1123,7 +1123,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension } const toUpdate = this.outdated.filter(e => - !this.isAutoUpdateIgnored(new ExtensionIdentifierWithVersion(e.identifier, e.version)) && + !this.isAutoUpdateIgnored(new ExtensionKey(e.identifier, e.version)) && (this.getAutoUpdateValue() === true || (e.local && this.extensionEnablementService.isEnabled(e.local))) ); @@ -1217,7 +1217,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension installOptions.installGivenVersion = true; const installed = await this.installFromGallery(extension, gallery, installOptions); if (extension.latestVersion !== version) { - this.ignoreAutoUpdate(new ExtensionIdentifierWithVersion(gallery.identifier, version)); + this.ignoreAutoUpdate(new ExtensionKey(gallery.identifier, version)); } return installed; }, gallery.displayName); @@ -1288,7 +1288,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension const { identifier } = await this.extensionManagementService.install(vsix, installOptions); if (existingExtension && existingExtension.latestVersion !== manifest.version) { - this.ignoreAutoUpdate(new ExtensionIdentifierWithVersion(identifier, manifest.version)); + this.ignoreAutoUpdate(new ExtensionKey(identifier, manifest.version)); } return this.local.filter(local => areSameExtensions(local.identifier, identifier))[0]; @@ -1529,18 +1529,18 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension this.storageService.store('extensions.ignoredAutoUpdateExtension', JSON.stringify(this._ignoredAutoUpdateExtensions), StorageScope.GLOBAL, StorageTarget.MACHINE); } - private ignoreAutoUpdate(identifierWithVersion: ExtensionIdentifierWithVersion): void { - if (!this.isAutoUpdateIgnored(identifierWithVersion)) { - this.ignoredAutoUpdateExtensions = [...this.ignoredAutoUpdateExtensions, identifierWithVersion.key()]; + private ignoreAutoUpdate(extensionKey: ExtensionKey): void { + if (!this.isAutoUpdateIgnored(extensionKey)) { + this.ignoredAutoUpdateExtensions = [...this.ignoredAutoUpdateExtensions, extensionKey.toString()]; } } - private isAutoUpdateIgnored(identifierWithVersion: ExtensionIdentifierWithVersion): boolean { - return this.ignoredAutoUpdateExtensions.indexOf(identifierWithVersion.key()) !== -1; + private isAutoUpdateIgnored(extensionKey: ExtensionKey): boolean { + return this.ignoredAutoUpdateExtensions.indexOf(extensionKey.toString()) !== -1; } private resetIgnoreAutoUpdateExtensions(): void { - this.ignoredAutoUpdateExtensions = this.ignoredAutoUpdateExtensions.filter(extensionId => this.local.some(local => !!local.local && new ExtensionIdentifierWithVersion(local.identifier, local.version).key() === extensionId)); + this.ignoredAutoUpdateExtensions = this.ignoredAutoUpdateExtensions.filter(extensionId => this.local.some(local => !!local.local && new ExtensionKey(local.identifier, local.version).toString() === extensionId)); } } diff --git a/src/vs/workbench/services/extensions/common/extensionPoints.ts b/src/vs/workbench/services/extensions/common/extensionPoints.ts index 887640645d6..95ebdd0691f 100644 --- a/src/vs/workbench/services/extensions/common/extensionPoints.ts +++ b/src/vs/workbench/services/extensions/common/extensionPoints.ts @@ -12,7 +12,7 @@ import * as arrays from 'vs/base/common/arrays'; import { getParseErrorMessage } from 'vs/base/common/jsonErrorMessages'; import * as types from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; -import { getGalleryExtensionId, groupByExtension, ExtensionIdentifierWithVersion, getExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { getGalleryExtensionId, groupByExtension, getExtensionId, ExtensionKey } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { isValidExtensionVersion } from 'vs/platform/extensions/common/extensionValidator'; import { ExtensionIdentifier, IExtensionDescription, UNDEFINED_PUBLISHER } from 'vs/platform/extensions/common/extensions'; @@ -135,6 +135,7 @@ class ExtensionManifestParser extends ExtensionManifestHandler { } else if (errors.length === 0) { if (manifest.__metadata) { manifest.uuid = manifest.__metadata.id; + manifest.targetPlatform = manifest.__metadata.targetPlatform; } manifest.isUserBuiltin = !!manifest.__metadata?.isBuiltin; delete manifest.__metadata; @@ -658,7 +659,7 @@ export class ExtensionScanner { const nlsConfig = ExtensionScannerInput.createNLSConfig(input); let _extensionDescriptions = await Promise.all(refs.map(r => this.scanExtension(input.ourVersion, input.ourProductDate, host, r.path, isBuiltin, isUnderDevelopment, nlsConfig))); let extensionDescriptions = arrays.coalesce(_extensionDescriptions); - extensionDescriptions = extensionDescriptions.filter(item => item !== null && !obsolete[new ExtensionIdentifierWithVersion({ id: getGalleryExtensionId(item.publisher, item.name) }, item.version).key()]); + extensionDescriptions = extensionDescriptions.filter(item => item !== null && !obsolete[new ExtensionKey({ id: getGalleryExtensionId(item.publisher, item.name) }, item.version, item.targetPlatform).toString()]); if (!isBuiltin) { // Filter out outdated extensions From dffa71af994ce24e6f3fa8c440f44afc961c5dc2 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 9 Mar 2022 22:18:16 +0100 Subject: [PATCH 085/175] show reload button when extension with different targetplatform is updated --- .../workbench/contrib/extensions/browser/extensionsActions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index e4d00340619..d3cfdba7cda 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -1427,8 +1427,8 @@ export class ReloadAction extends ExtensionAction { const runningExtensionServer = this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension)); if (isSameExtensionRunning) { - // Different version of same extension is running. Requires reload to run the current version - if (this.extension.version !== runningExtension.version) { + // Different version or target platform of same extension is running. Requires reload to run the current version + if (this.extension.version !== runningExtension.version || this.extension.local.targetPlatform !== runningExtension.targetPlatform) { this.enabled = true; this.label = localize('reloadRequired', "Reload Required"); this.tooltip = localize('postUpdateTooltip', "Please reload Visual Studio Code to enable the updated extension."); From d1e59b8fc534fd31a0065820f8697bab503ec28c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 9 Mar 2022 22:24:06 +0100 Subject: [PATCH 086/175] Move Monaco Editor checks to a separate GH action --- .github/workflows/ci.yml | 35 ----------- .github/workflows/monaco-editor.yml | 91 +++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 35 deletions(-) create mode 100644 .github/workflows/monaco-editor.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf302f72493..2e837bb4b72 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -318,43 +318,8 @@ jobs: - name: Run eslint run: yarn eslint - - name: Run Monaco Editor Checks - run: yarn monaco-compile-check - - name: Run vscode-dts Compile Checks run: yarn vscode-dts-compile-check - name: Run Trusted Types Checks run: yarn tsec-compile-check - - - name: Editor Distro & ESM Bundle - run: yarn gulp editor-esm-bundle - - - name: Editor ESM sources check - working-directory: ./test/monaco - run: yarn run esm-check - - - name: Typings validation prep - run: | - mkdir typings-test - - - name: Typings validation - working-directory: ./typings-test - run: | - yarn init -yp - ../node_modules/.bin/tsc --init - echo "import '../out-monaco-editor-core';" > a.ts - ../node_modules/.bin/tsc --noEmit - - - name: Package Editor with Webpack - working-directory: ./test/monaco - run: yarn run bundle-webpack - - - name: Compile Editor Tests - working-directory: ./test/monaco - run: yarn run compile - - - name: Run Editor Tests - timeout-minutes: 5 - working-directory: ./test/monaco - run: yarn test diff --git a/.github/workflows/monaco-editor.yml b/.github/workflows/monaco-editor.yml new file mode 100644 index 00000000000..84955eca85c --- /dev/null +++ b/.github/workflows/monaco-editor.yml @@ -0,0 +1,91 @@ +name: Monaco Editor checks + +on: + push: + branches: + - main + - release/* + pull_request: + branches: + - main + - release/* + +jobs: + main: + name: Monaco Editor checks + runs-on: ubuntu-latest + timeout-minutes: 40 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2 + with: + node-version: 14 + + - name: Compute node modules cache key + id: nodeModulesCacheKey + run: echo "::set-output name=value::$(node build/azure-pipelines/common/computeNodeModulesCacheKey.js)" + - name: Cache node modules + id: cacheNodeModules + uses: actions/cache@v2 + with: + path: "**/node_modules" + key: ${{ runner.os }}-cacheNodeModules20-${{ steps.nodeModulesCacheKey.outputs.value }} + restore-keys: ${{ runner.os }}-cacheNodeModules20- + - name: Get yarn cache directory path + id: yarnCacheDirPath + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} + run: echo "::set-output name=dir::$(yarn cache dir)" + - name: Cache yarn directory + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} + uses: actions/cache@v2 + with: + path: ${{ steps.yarnCacheDirPath.outputs.dir }} + key: ${{ runner.os }}-yarnCacheDir-${{ steps.nodeModulesCacheKey.outputs.value }} + restore-keys: ${{ runner.os }}-yarnCacheDir- + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + run: yarn --frozen-lockfile --network-timeout 180000 + + - name: Download Playwright + run: yarn playwright-install + + - name: Run Monaco Editor Checks + run: yarn monaco-compile-check + + - name: Editor Distro & ESM Bundle + run: yarn gulp editor-esm-bundle + + - name: Editor ESM sources check + working-directory: ./test/monaco + run: yarn run esm-check + + - name: Typings validation prep + run: | + mkdir typings-test + + - name: Typings validation + working-directory: ./typings-test + run: | + yarn init -yp + ../node_modules/.bin/tsc --init + echo "import '../out-monaco-editor-core';" > a.ts + ../node_modules/.bin/tsc --noEmit + + - name: Package Editor with Webpack + working-directory: ./test/monaco + run: yarn run bundle-webpack + + - name: Compile Editor Tests + working-directory: ./test/monaco + run: yarn run compile + + - name: Run Editor Tests + timeout-minutes: 5 + working-directory: ./test/monaco + run: yarn test From 560c458387590ca536b887751f2372bc419f0a08 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 9 Mar 2022 13:34:13 -0800 Subject: [PATCH 087/175] Revert "experiment running notebooks in dedicated process." This reverts commit 24344687a2dacfdc753e870009585d0b008fecb7. --- .../browser/extensions.contribution.ts | 7 ----- .../browser/contrib/troubleshoot/layout.ts | 22 ---------------- .../common/abstractExtensionService.ts | 12 +-------- .../services/extensions/common/extensions.ts | 5 ---- .../electron-browser/extensionService.ts | 26 ++----------------- .../localProcessExtensionHost.ts | 2 +- 6 files changed, 4 insertions(+), 70 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index b893c1705b1..5183cae9573 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -198,13 +198,6 @@ Registry.as(ConfigurationExtensions.Configuration) 'pub.name': false } }, - 'extensions.experimental.dedicatedNotebookProcess': { - type: 'boolean', - description: localize('extensionsExperimentalDedicatedNotebookProcess', "Experimental. When enabled, notebook extensions would run in dedicated extension host."), - default: false, - scope: ConfigurationScope.APPLICATION, - ignoreSync: true - }, [WORKSPACE_TRUST_EXTENSION_SUPPORT]: { type: 'object', scope: ConfigurationScope.APPLICATION, diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout.ts b/src/vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout.ts index daeb34afb90..29d4e867f65 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout.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 { Disposable, DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle'; import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -13,9 +12,6 @@ import { registerNotebookContribution } from 'vs/workbench/contrib/notebook/brow import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidget'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ICommandService } from 'vs/platform/commands/common/commands'; -import { ReloadWindowAction } from 'vs/workbench/browser/actions/windowActions'; export class TroubleshootController extends Disposable implements INotebookEditorContribution { static id: string = 'workbench.notebook.troubleshoot'; @@ -150,21 +146,3 @@ registerAction2(class extends Action2 { notebookService.clearEditorCache(); } }); - -registerAction2(class DedicatedExtensionHostAction extends Action2 { - constructor() { - super({ - id: 'notebook.experiment.runInDedicatedExtensionHost', - title: localize('notebook.experiment.runInDedicatedExtensionHost', 'Run Notebook Extensions In Dedicated Extension Host'), - f1: true, - category: CATEGORIES.Developer - }); - } - - async run(accessor: ServicesAccessor) { - const service = accessor.get(IConfigurationService); - const commandService = accessor.get(ICommandService); - await service.updateValue('extensions.experimental.dedicatedNotebookProcess', true); - await commandService.executeCommand(ReloadWindowAction.ID); - } -}); diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 8e8503e4617..aeb23b01d1e 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -188,7 +188,6 @@ export abstract class AbstractExtensionService extends Disposable implements IEx super(); this._runningLocationClassifier = new ExtensionRunningLocationClassifier( - _configurationService, (extension) => this._getExtensionKind(extension), (extensionId, extensionKinds, isInstalledLocally, isInstalledRemotely, preference) => this._pickRunningLocation(extensionId, extensionKinds, isInstalledLocally, isInstalledRemotely, preference) ); @@ -667,11 +666,6 @@ export abstract class AbstractExtensionService extends Disposable implements IEx if (localProcessExtensionHost) { await localProcessExtensionHost.ready(); } - - const notebookProcessExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalNotebook); - if (notebookProcessExtensionHost) { - await notebookProcessExtensionHost.ready(); - } } finally { lock.dispose(); } @@ -1102,7 +1096,6 @@ class ExtensionInfo { class ExtensionRunningLocationClassifier { constructor( - private readonly configurationService: IConfigurationService, private readonly getExtensionKind: (extensionDescription: IExtensionDescription) => ExtensionKind[], private readonly pickRunningLocation: (extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference) => ExtensionRunningLocation, ) { @@ -1134,7 +1127,6 @@ class ExtensionRunningLocationClassifier { localExtensions.forEach((ext) => collectExtension(ext)); remoteExtensions.forEach((ext) => collectExtension(ext)); - const isDedicatedNotebookProcessEnabled = this.configurationService.getValue('extensions.experimental.dedicatedNotebookProcess'); const runningLocation = new Map(); allExtensions.forEach((ext) => { const isInstalledLocally = Boolean(ext.local); @@ -1150,9 +1142,7 @@ class ExtensionRunningLocationClassifier { preference = ExtensionRunningPreference.Remote; } - const location = isDedicatedNotebookProcessEnabled && (ext.local?.desc.categories ?? []).indexOf('Notebooks') >= 0 ? ExtensionRunningLocation.LocalNotebookProcess : this.pickRunningLocation(ext.identifier, ext.kind, isInstalledLocally, isInstalledRemotely, preference); - - runningLocation.set(ext.key, location); + runningLocation.set(ext.key, this.pickRunningLocation(ext.identifier, ext.kind, isInstalledLocally, isInstalledRemotely, preference)); }); return runningLocation; diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 2ef2d31ac41..6398b447a1a 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -39,7 +39,6 @@ export interface IMessage { export const enum ExtensionRunningLocation { None, LocalProcess, - LocalNotebookProcess, LocalWebWorker, Remote } @@ -50,8 +49,6 @@ export function extensionRunningLocationToString(location: ExtensionRunningLocat return 'None'; case ExtensionRunningLocation.LocalProcess: return 'LocalProcess'; - case ExtensionRunningLocation.LocalNotebookProcess: - return 'NotebookProcess'; case ExtensionRunningLocation.LocalWebWorker: return 'LocalWebWorker'; case ExtensionRunningLocation.Remote: @@ -113,7 +110,6 @@ export interface IExtensionHostProfile { export const enum ExtensionHostKind { LocalProcess, LocalWebWorker, - LocalNotebook, Remote } @@ -121,7 +117,6 @@ export function extensionHostKindToString(kind: ExtensionHostKind): string { switch (kind) { case ExtensionHostKind.LocalProcess: return 'LocalProcess'; case ExtensionHostKind.LocalWebWorker: return 'LocalWebWorker'; - case ExtensionHostKind.LocalNotebook: return 'LocalNotebook'; case ExtensionHostKind.Remote: return 'Remote'; } } diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 9b0731cb92f..783fe97db1d 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -231,28 +231,12 @@ export class ExtensionService extends AbstractExtensionService implements IExten return (result.length > 0 ? result[0] : ExtensionRunningLocation.None); } - /** - * FYI. - * This is an experiment for running notebook extensions in a dedicated extension host to prevent it from being affected - * by starving extension host, or slowing down / blocking other extensions as it performs heavy compution when converting - * notebook output data from nbformat to vsbuffer (or vise versa). - * It's not an attempt to introduce a generic solution for running abitrary extensions in a dedicated extension host. - */ - private _isDedicatedNotebookExtensionHostExperimentEnabled() { - return this._configurationService.getValue('extensions.experimental.dedicatedNotebookProcess'); - } - protected _createExtensionHosts(isInitialStart: boolean): IExtensionHost[] { const result: IExtensionHost[] = []; - const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, ExtensionHostKind.LocalProcess, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionRunningLocation.LocalProcess)); + const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionRunningLocation.LocalProcess)); result.push(localProcessExtHost); - if (this._isDedicatedNotebookExtensionHostExperimentEnabled()) { - const notebookProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, ExtensionHostKind.LocalNotebook, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionRunningLocation.LocalNotebookProcess)); - result.push(notebookProcessExtHost); - } - if (this._enableLocalWebWorker) { const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, this._lazyLocalWebWorker, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionRunningLocation.LocalWebWorker)); result.push(webWorkerExtHost); @@ -491,11 +475,10 @@ export class ExtensionService extends AbstractExtensionService implements IExten // remove non-UI extensions from the local extensions const localProcessExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionRunningLocation.LocalProcess); - const loaclNotebookProcessExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionRunningLocation.LocalNotebookProcess); const localWebWorkerExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionRunningLocation.LocalWebWorker); remoteExtensions = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionRunningLocation.Remote); - const result = this._registry.deltaExtensions(remoteExtensions.concat(localProcessExtensions).concat(loaclNotebookProcessExtensions).concat(localWebWorkerExtensions), []); + const result = this._registry.deltaExtensions(remoteExtensions.concat(localProcessExtensions).concat(localWebWorkerExtensions), []); if (result.removedDueToLooping.length > 0) { this._logOrShowMessage(Severity.Error, nls.localize('looping', "The following extensions contain dependency loops and have been disabled: {0}", result.removedDueToLooping.map(e => `'${e.identifier.value}'`).join(', '))); } @@ -520,11 +503,6 @@ export class ExtensionService extends AbstractExtensionService implements IExten localProcessExtensionHost.start(localProcessExtensions.map(extension => extension.identifier).filter(id => this._registry.containsExtension(id))); } - const localNotebookExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalNotebook); - if (localNotebookExtensionHost) { - localNotebookExtensionHost.start(loaclNotebookProcessExtensions.map(extension => extension.identifier).filter(id => this._registry.containsExtension(id))); - } - const localWebWorkerExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalWebWorker); if (localWebWorkerExtensionHost) { localWebWorkerExtensionHost.start(localWebWorkerExtensions.map(extension => extension.identifier).filter(id => this._registry.containsExtension(id))); diff --git a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts index e9dc6541714..79556450046 100644 --- a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts @@ -105,6 +105,7 @@ class ExtensionHostProcess { export class LocalProcessExtensionHost implements IExtensionHost { + public readonly kind = ExtensionHostKind.LocalProcess; public readonly remoteAuthority = null; public readonly lazyStart = false; @@ -134,7 +135,6 @@ export class LocalProcessExtensionHost implements IExtensionHost { private readonly _extensionHostLogFile: URI; constructor( - readonly kind: ExtensionHostKind, private readonly _initDataProvider: ILocalProcessExtensionHostDataProvider, @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService, @INotificationService private readonly _notificationService: INotificationService, From b3832713dbc75b4872a2195ecba8aa3a7c93f358 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Mar 2022 14:33:14 -0800 Subject: [PATCH 088/175] Use esnext as implicit js/ts module For https://github.com/microsoft/TypeScript/issues/46698 Also adds new settings for the target and module in implicit projects --- .../typescript-language-features/package.json | 40 +++++++++++++++++++ .../package.nls.json | 2 + .../src/utils/configuration.ts | 12 ++++++ .../src/utils/tsconfig.ts | 22 +++++++--- 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index d5b9bb4df3c..15e218f5683 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -636,6 +636,46 @@ "%format.semicolons.remove%" ] }, + "js/ts.implicitProjectConfig.module": { + "type": "string", + "markdownDescription": "%configuration.implicitProjectConfig.module%", + "default": "ESNext", + "enum": [ + "CommonJS", + "AMD", + "System", + "UMD", + "ES6", + "ES2015", + "ES2020", + "ESNext", + "None", + "ES2022", + "Node12", + "NodeNext" + ], + "scope": "window" + }, + "js/ts.implicitProjectConfig.target": { + "type": "string", + "default": "ES2020", + "markdownDescription": "%configuration.implicitProjectConfig.target%", + "enum": [ + "ES3", + "ES5", + "ES6", + "ES2015", + "ES2016", + "ES2017", + "ES2018", + "ES2019", + "ES2020", + "ES2021", + "ES2022", + "ESNext" + ], + "scope": "window" + }, "javascript.implicitProjectConfig.checkJs": { "type": "boolean", "default": false, diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json index dd7d6b209f5..fa0230320ec 100644 --- a/extensions/typescript-language-features/package.nls.json +++ b/extensions/typescript-language-features/package.nls.json @@ -71,6 +71,8 @@ "configuration.tsserver.maxTsServerMemory": "The maximum amount of memory (in MB) to allocate to the TypeScript server process.", "configuration.tsserver.experimental.enableProjectDiagnostics": "(Experimental) Enables project wide error reporting.", "typescript.locale": "Sets the locale used to report JavaScript and TypeScript errors. Defaults to use VS Code's locale.", + "configuration.implicitProjectConfig.module": "Sets the module system for the program. See more: https://www.typescriptlang.org/tsconfig#module.", + "configuration.implicitProjectConfig.target": "Set target JavaScript language version for emitted JavaScript and include library declarations. See more: https://www.typescriptlang.org/tsconfig#target.", "configuration.implicitProjectConfig.checkJs": "Enable/disable semantic checking of JavaScript files. Existing `jsconfig.json` or `tsconfig.json` files override this setting.", "configuration.javascript.checkJs.checkJs.deprecation": "This setting has been deprecated in favor of `js/ts.implicitProjectConfig.checkJs`.", "configuration.implicitProjectConfig.experimentalDecorators": "Enable/disable `experimentalDecorators` in JavaScript files that are not part of a project. Existing `jsconfig.json` or `tsconfig.json` files override this setting.", diff --git a/extensions/typescript-language-features/src/utils/configuration.ts b/extensions/typescript-language-features/src/utils/configuration.ts index 1249cd5b6ba..c69b8fde758 100644 --- a/extensions/typescript-language-features/src/utils/configuration.ts +++ b/extensions/typescript-language-features/src/utils/configuration.ts @@ -52,12 +52,16 @@ export const enum SyntaxServerConfiguration { export class ImplicitProjectConfiguration { + public readonly target: string | undefined; + public readonly module: string | undefined; public readonly checkJs: boolean; public readonly experimentalDecorators: boolean; public readonly strictNullChecks: boolean; public readonly strictFunctionTypes: boolean; constructor(configuration: vscode.WorkspaceConfiguration) { + this.target = ImplicitProjectConfiguration.readTarget(configuration); + this.module = ImplicitProjectConfiguration.readModule(configuration); this.checkJs = ImplicitProjectConfiguration.readCheckJs(configuration); this.experimentalDecorators = ImplicitProjectConfiguration.readExperimentalDecorators(configuration); this.strictNullChecks = ImplicitProjectConfiguration.readImplicitStrictNullChecks(configuration); @@ -68,6 +72,14 @@ export class ImplicitProjectConfiguration { return objects.equals(this, other); } + private static readTarget(configuration: vscode.WorkspaceConfiguration): string | undefined { + return configuration.get('js/ts.implicitProjectConfig.target'); + } + + private static readModule(configuration: vscode.WorkspaceConfiguration): string | undefined { + return configuration.get('js/ts.implicitProjectConfig.module'); + } + private static readCheckJs(configuration: vscode.WorkspaceConfiguration): boolean { return configuration.get('js/ts.implicitProjectConfig.checkJs') ?? configuration.get('javascript.implicitProjectConfig.checkJs', false); diff --git a/extensions/typescript-language-features/src/utils/tsconfig.ts b/extensions/typescript-language-features/src/utils/tsconfig.ts index d72d7489e33..463f0f7114a 100644 --- a/extensions/typescript-language-features/src/utils/tsconfig.ts +++ b/extensions/typescript-language-features/src/utils/tsconfig.ts @@ -22,15 +22,18 @@ export function isImplicitProjectConfigFile(configFileName: string) { return configFileName.startsWith('/dev/null/'); } +const defaultProjectConfig = Object.freeze({ + module: 'ESNext' as Proto.ModuleKind, + moduleResolution: 'Node' as Proto.ModuleResolutionKind, + target: 'ES2020' as Proto.ScriptTarget, + jsx: 'Preserve' as Proto.JsxEmit, +}); + export function inferredProjectCompilerOptions( projectType: ProjectType, serviceConfig: TypeScriptServiceConfiguration, ): Proto.ExternalProjectCompilerOptions { - const projectConfig: Proto.ExternalProjectCompilerOptions = { - module: 'commonjs' as Proto.ModuleKind, - target: 'es2020' as Proto.ScriptTarget, - jsx: 'preserve' as Proto.JsxEmit, - }; + const projectConfig = { ...defaultProjectConfig }; if (serviceConfig.implicitProjectConfiguration.checkJs) { projectConfig.checkJs = true; @@ -51,6 +54,15 @@ export function inferredProjectCompilerOptions( projectConfig.strictFunctionTypes = true; } + + if (serviceConfig.implicitProjectConfiguration.module) { + projectConfig.module = serviceConfig.implicitProjectConfiguration.module as Proto.ModuleKind; + } + + if (serviceConfig.implicitProjectConfiguration.target) { + projectConfig.target = serviceConfig.implicitProjectConfiguration.target as Proto.ScriptTarget; + } + if (projectType === ProjectType.TypeScript) { projectConfig.sourceMap = true; } From 71c0686d04c76d9caf0cf70585459732c18101ff Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 9 Mar 2022 14:38:13 -0800 Subject: [PATCH 089/175] Use lowercase preserve for jsxemit This matches what the tsconfig schema expects --- extensions/typescript-language-features/src/utils/tsconfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/typescript-language-features/src/utils/tsconfig.ts b/extensions/typescript-language-features/src/utils/tsconfig.ts index 463f0f7114a..b92a26916d1 100644 --- a/extensions/typescript-language-features/src/utils/tsconfig.ts +++ b/extensions/typescript-language-features/src/utils/tsconfig.ts @@ -26,7 +26,7 @@ const defaultProjectConfig = Object.freeze module: 'ESNext' as Proto.ModuleKind, moduleResolution: 'Node' as Proto.ModuleResolutionKind, target: 'ES2020' as Proto.ScriptTarget, - jsx: 'Preserve' as Proto.JsxEmit, + jsx: 'preserve' as Proto.JsxEmit, }); export function inferredProjectCompilerOptions( From 5cf9d173cb8bd2f9a333609dd85819d4d3248cfd Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Wed, 9 Mar 2022 23:38:28 +0100 Subject: [PATCH 090/175] DAP 1.55.0-pre.1 --- package.json | 1 - .../contrib/debug/common/debugProtocol.d.ts | 391 +++++++++--------- yarn.lock | 5 - 3 files changed, 196 insertions(+), 201 deletions(-) diff --git a/package.json b/package.json index b46c5602a28..e82e3bfa8d3 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "dependencies": { "@microsoft/applicationinsights-web": "^2.6.4", "@parcel/watcher": "2.0.5", - "@vscode/debugprotocol": "1.54.0", "@vscode/iconv-lite-umd": "0.7.0", "@vscode/ripgrep": "^1.14.1", "@vscode/sqlite3": "4.0.12", diff --git a/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts b/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts index 540c79f99ea..242b3fd980c 100644 --- a/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts +++ b/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts @@ -3,14 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - /** Declaration module describing the VS Code debug protocol. Auto-generated from json schema. Do not edit manually. */ declare module DebugProtocol { /** Base class of requests, responses, and events. */ - export interface ProtocolMessage { + interface ProtocolMessage { /** Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. */ seq: number; /** Message type. @@ -20,7 +19,7 @@ declare module DebugProtocol { } /** A client or debug adapter initiated request. */ - export interface Request extends ProtocolMessage { + interface Request extends ProtocolMessage { // type: 'request'; /** The command to execute. */ command: string; @@ -29,7 +28,7 @@ declare module DebugProtocol { } /** A debug adapter initiated event. */ - export interface Event extends ProtocolMessage { + interface Event extends ProtocolMessage { // type: 'event'; /** Type of event. */ event: string; @@ -38,7 +37,7 @@ declare module DebugProtocol { } /** Response for a request. */ - export interface Response extends ProtocolMessage { + interface Response extends ProtocolMessage { // type: 'response'; /** Sequence number of the corresponding request. */ request_seq: number; @@ -62,7 +61,7 @@ declare module DebugProtocol { } /** On error (whenever 'success' is false), the body can provide more details. */ - export interface ErrorResponse extends Response { + interface ErrorResponse extends Response { body: { /** An optional, structured error message. */ error?: Message; @@ -82,13 +81,13 @@ declare module DebugProtocol { The progress that got cancelled still needs to send a 'progressEnd' event back. A client should not assume that progress just got cancelled after sending the 'cancel' request. */ - export interface CancelRequest extends Request { + interface CancelRequest extends Request { // command: 'cancel'; arguments?: CancelArguments; } /** Arguments for 'cancel' request. */ - export interface CancelArguments { + interface CancelArguments { /** The ID (attribute 'seq') of the request to cancel. If missing no request is cancelled. Both a 'requestId' and a 'progressId' can be specified in one request. */ @@ -100,7 +99,7 @@ declare module DebugProtocol { } /** Response to 'cancel' request. This is just an acknowledgement, so no body field is required. */ - export interface CancelResponse extends Response { + interface CancelResponse extends Response { } /** Event message for 'initialized' event type. @@ -114,7 +113,7 @@ declare module DebugProtocol { - frontend sends other future configuration requests - frontend sends one 'configurationDone' request to indicate the end of the configuration. */ - export interface InitializedEvent extends Event { + interface InitializedEvent extends Event { // event: 'initialized'; } @@ -122,7 +121,7 @@ declare module DebugProtocol { The event indicates that the execution of the debuggee has stopped due to some condition. This can be caused by a break point previously set, a stepping request has completed, by executing a debugger statement etc. */ - export interface StoppedEvent extends Event { + interface StoppedEvent extends Event { // event: 'stopped'; body: { /** The reason for the event. @@ -157,7 +156,7 @@ declare module DebugProtocol { Please note: a debug adapter is not expected to send this event in response to a request that implies that execution continues, e.g. 'launch' or 'continue'. It is only necessary to send a 'continued' event if there was no previous request that implied this. */ - export interface ContinuedEvent extends Event { + interface ContinuedEvent extends Event { // event: 'continued'; body: { /** The thread which was continued. */ @@ -170,7 +169,7 @@ declare module DebugProtocol { /** Event message for 'exited' event type. The event indicates that the debuggee has exited and returns its exit code. */ - export interface ExitedEvent extends Event { + interface ExitedEvent extends Event { // event: 'exited'; body: { /** The exit code returned from the debuggee. */ @@ -181,7 +180,7 @@ declare module DebugProtocol { /** Event message for 'terminated' event type. The event indicates that debugging of the debuggee has terminated. This does **not** mean that the debuggee itself has exited. */ - export interface TerminatedEvent extends Event { + interface TerminatedEvent extends Event { // event: 'terminated'; body?: { /** A debug adapter may set 'restart' to true (or to an arbitrary object) to request that the front end restarts the session. @@ -194,7 +193,7 @@ declare module DebugProtocol { /** Event message for 'thread' event type. The event indicates that a thread has started or exited. */ - export interface ThreadEvent extends Event { + interface ThreadEvent extends Event { // event: 'thread'; body: { /** The reason for the event. @@ -209,7 +208,7 @@ declare module DebugProtocol { /** Event message for 'output' event type. The event indicates that the target has produced some output. */ - export interface OutputEvent extends Event { + interface OutputEvent extends Event { // event: 'output'; body: { /** The output category. If not specified or if the category is not understand by the client, 'console' is assumed. @@ -249,7 +248,7 @@ declare module DebugProtocol { /** Event message for 'breakpoint' event type. The event indicates that some information about a breakpoint has changed. */ - export interface BreakpointEvent extends Event { + interface BreakpointEvent extends Event { // event: 'breakpoint'; body: { /** The reason for the event. @@ -264,7 +263,7 @@ declare module DebugProtocol { /** Event message for 'module' event type. The event indicates that some information about a module has changed. */ - export interface ModuleEvent extends Event { + interface ModuleEvent extends Event { // event: 'module'; body: { /** The reason for the event. */ @@ -277,7 +276,7 @@ declare module DebugProtocol { /** Event message for 'loadedSource' event type. The event indicates that some source has been added, changed, or removed from the set of all loaded sources. */ - export interface LoadedSourceEvent extends Event { + interface LoadedSourceEvent extends Event { // event: 'loadedSource'; body: { /** The reason for the event. */ @@ -290,7 +289,7 @@ declare module DebugProtocol { /** Event message for 'process' event type. The event indicates that the debugger has begun debugging a new process. Either one that it has launched, or one that it has attached to. */ - export interface ProcessEvent extends Event { + interface ProcessEvent extends Event { // event: 'process'; body: { /** The logical name of the process. This is usually the full path to process's executable file. Example: /home/example/myproj/program.js. */ @@ -316,7 +315,7 @@ declare module DebugProtocol { Consequently this event has a hint characteristic: a frontend can only be expected to make a 'best effort' in honouring individual capabilities but there are no guarantees. Only changed capabilities need to be included, all other capabilities keep their values. */ - export interface CapabilitiesEvent extends Event { + interface CapabilitiesEvent extends Event { // event: 'capabilities'; body: { /** The set of updated capabilities. */ @@ -330,7 +329,7 @@ declare module DebugProtocol { The client is free to delay the showing of the UI in order to reduce flicker. This event should only be sent if the client has passed the value true for the 'supportsProgressReporting' capability of the 'initialize' request. */ - export interface ProgressStartEvent extends Event { + interface ProgressStartEvent extends Event { // event: 'progressStart'; body: { /** An ID that must be used in subsequent 'progressUpdate' and 'progressEnd' events to make them refer to the same progress reporting. @@ -361,7 +360,7 @@ declare module DebugProtocol { The client does not have to update the UI immediately, but the clients needs to keep track of the message and/or percentage values. This event should only be sent if the client has passed the value true for the 'supportsProgressReporting' capability of the 'initialize' request. */ - export interface ProgressUpdateEvent extends Event { + interface ProgressUpdateEvent extends Event { // event: 'progressUpdate'; body: { /** The ID that was introduced in the initial 'progressStart' event. */ @@ -377,7 +376,7 @@ declare module DebugProtocol { The event signals the end of the progress reporting with an optional final message. This event should only be sent if the client has passed the value true for the 'supportsProgressReporting' capability of the 'initialize' request. */ - export interface ProgressEndEvent extends Event { + interface ProgressEndEvent extends Event { // event: 'progressEnd'; body: { /** The ID that was introduced in the initial 'ProgressStartEvent'. */ @@ -392,7 +391,7 @@ declare module DebugProtocol { Debug adapters do not have to emit this event for runtime changes like stopped or thread events because in that case the client refetches the new state anyway. But the event can be used for example to refresh the UI after rendering formatting has changed in the debug adapter. This event should only be sent if the debug adapter has received a value true for the 'supportsInvalidatedEvent' capability of the 'initialize' request. */ - export interface InvalidatedEvent extends Event { + interface InvalidatedEvent extends Event { // event: 'invalidated'; body: { /** Optional set of logical areas that got invalidated. This property has a hint characteristic: a client can only be expected to make a 'best effort' in honouring the areas but there are no guarantees. If this property is missing, empty, or if values are not understand the client should assume a single value 'all'. */ @@ -409,7 +408,7 @@ declare module DebugProtocol { Clients typically react to the event by re-issuing a `readMemory` request if they show the memory identified by the `memoryReference` and if the updated memory range overlaps the displayed range. Clients should not make assumptions how individual memory references relate to each other, so they should not assume that they are part of a single continuous address range and might overlap. Debug adapters can use this event to indicate that the contents of a memory range has changed due to some other DAP request like `setVariable` or `setExpression`. Debug adapters are not expected to emit this event for each and every memory change of a running program, because that information is typically not available from debuggers and it would flood clients with too many events. */ - export interface MemoryEvent extends Event { + interface MemoryEvent extends Event { // event: 'memory'; body: { /** Memory reference of a memory range that has been updated. */ @@ -426,13 +425,13 @@ declare module DebugProtocol { This is typically used to launch the debuggee in a terminal provided by the client. This request should only be called if the client has passed the value true for the 'supportsRunInTerminalRequest' capability of the 'initialize' request. */ - export interface RunInTerminalRequest extends Request { + interface RunInTerminalRequest extends Request { // command: 'runInTerminal'; arguments: RunInTerminalRequestArguments; } /** Arguments for 'runInTerminal' request. */ - export interface RunInTerminalRequestArguments { + interface RunInTerminalRequestArguments { /** What kind of terminal to launch. */ kind?: 'integrated' | 'external'; /** Optional title of the terminal. */ @@ -446,7 +445,7 @@ declare module DebugProtocol { } /** Response to 'runInTerminal' request. */ - export interface RunInTerminalResponse extends Response { + interface RunInTerminalResponse extends Response { body: { /** The process ID. The value should be less than or equal to 2147483647 (2^31-1). */ processId?: number; @@ -462,13 +461,13 @@ declare module DebugProtocol { In addition the debug adapter is not allowed to send any requests or events to the client until it has responded with an 'initialize' response. The 'initialize' request may only be sent once. */ - export interface InitializeRequest extends Request { + interface InitializeRequest extends Request { // command: 'initialize'; arguments: InitializeRequestArguments; } /** Arguments for 'initialize' request. */ - export interface InitializeRequestArguments { + interface InitializeRequestArguments { /** The ID of the (frontend) client using this adapter. */ clientID?: string; /** The human readable name of the (frontend) client using this adapter. */ @@ -502,7 +501,7 @@ declare module DebugProtocol { } /** Response to 'initialize' request. */ - export interface InitializeResponse extends Response { + interface InitializeResponse extends Response { /** The capabilities of this debug adapter. */ body?: Capabilities; } @@ -512,30 +511,30 @@ declare module DebugProtocol { So it is the last request in the sequence of configuration requests (which was started by the 'initialized' event). Clients should only call this request if the capability 'supportsConfigurationDoneRequest' is true. */ - export interface ConfigurationDoneRequest extends Request { + interface ConfigurationDoneRequest extends Request { // command: 'configurationDone'; arguments?: ConfigurationDoneArguments; } /** Arguments for 'configurationDone' request. */ - export interface ConfigurationDoneArguments { + interface ConfigurationDoneArguments { } /** Response to 'configurationDone' request. This is just an acknowledgement, so no body field is required. */ - export interface ConfigurationDoneResponse extends Response { + interface ConfigurationDoneResponse extends Response { } /** Launch request; value of command field is 'launch'. This launch request is sent from the client to the debug adapter to start the debuggee with or without debugging (if 'noDebug' is true). Since launching is debugger/runtime specific, the arguments for this request are not part of this specification. */ - export interface LaunchRequest extends Request { + interface LaunchRequest extends Request { // command: 'launch'; arguments: LaunchRequestArguments; } /** Arguments for 'launch' request. Additional attributes are implementation specific. */ - export interface LaunchRequestArguments { + interface LaunchRequestArguments { /** If noDebug is true the launch request should launch the program without enabling debugging. */ noDebug?: boolean; /** Optional data from the previous, restarted session. @@ -546,20 +545,20 @@ declare module DebugProtocol { } /** Response to 'launch' request. This is just an acknowledgement, so no body field is required. */ - export interface LaunchResponse extends Response { + interface LaunchResponse extends Response { } /** Attach request; value of command field is 'attach'. The attach request is sent from the client to the debug adapter to attach to a debuggee that is already running. Since attaching is debugger/runtime specific, the arguments for this request are not part of this specification. */ - export interface AttachRequest extends Request { + interface AttachRequest extends Request { // command: 'attach'; arguments: AttachRequestArguments; } /** Arguments for 'attach' request. Additional attributes are implementation specific. */ - export interface AttachRequestArguments { + interface AttachRequestArguments { /** Optional data from the previous, restarted session. The data is sent as the 'restart' attribute of the 'terminated' event. The client should leave the data intact. @@ -568,26 +567,26 @@ declare module DebugProtocol { } /** Response to 'attach' request. This is just an acknowledgement, so no body field is required. */ - export interface AttachResponse extends Response { + interface AttachResponse extends Response { } /** Restart request; value of command field is 'restart'. Restarts a debug session. Clients should only call this request if the capability 'supportsRestartRequest' is true. If the capability is missing or has the value false, a typical client will emulate 'restart' by terminating the debug adapter first and then launching it anew. */ - export interface RestartRequest extends Request { + interface RestartRequest extends Request { // command: 'restart'; arguments?: RestartArguments; } /** Arguments for 'restart' request. */ - export interface RestartArguments { + interface RestartArguments { /** The latest version of the 'launch' or 'attach' configuration. */ arguments?: LaunchRequestArguments | AttachRequestArguments; } /** Response to 'restart' request. This is just an acknowledgement, so no body field is required. */ - export interface RestartResponse extends Response { + interface RestartResponse extends Response { } /** Disconnect request; value of command field is 'disconnect'. @@ -597,13 +596,13 @@ declare module DebugProtocol { If the 'attach' request was used to connect to the debuggee, 'disconnect' does not terminate the debuggee. This behavior can be controlled with the 'terminateDebuggee' argument (if supported by the debug adapter). */ - export interface DisconnectRequest extends Request { + interface DisconnectRequest extends Request { // command: 'disconnect'; arguments?: DisconnectArguments; } /** Arguments for 'disconnect' request. */ - export interface DisconnectArguments { + interface DisconnectArguments { /** A value of true indicates that this 'disconnect' request is part of a restart sequence. */ restart?: boolean; /** Indicates whether the debuggee should be terminated when the debugger is disconnected. @@ -619,39 +618,39 @@ declare module DebugProtocol { } /** Response to 'disconnect' request. This is just an acknowledgement, so no body field is required. */ - export interface DisconnectResponse extends Response { + interface DisconnectResponse extends Response { } /** Terminate request; value of command field is 'terminate'. The 'terminate' request is sent from the client to the debug adapter in order to give the debuggee a chance for terminating itself. Clients should only call this request if the capability 'supportsTerminateRequest' is true. */ - export interface TerminateRequest extends Request { + interface TerminateRequest extends Request { // command: 'terminate'; arguments?: TerminateArguments; } /** Arguments for 'terminate' request. */ - export interface TerminateArguments { + interface TerminateArguments { /** A value of true indicates that this 'terminate' request is part of a restart sequence. */ restart?: boolean; } /** Response to 'terminate' request. This is just an acknowledgement, so no body field is required. */ - export interface TerminateResponse extends Response { + interface TerminateResponse extends Response { } /** BreakpointLocations request; value of command field is 'breakpointLocations'. The 'breakpointLocations' request returns all possible locations for source breakpoints in a given range. Clients should only call this request if the capability 'supportsBreakpointLocationsRequest' is true. */ - export interface BreakpointLocationsRequest extends Request { + interface BreakpointLocationsRequest extends Request { // command: 'breakpointLocations'; arguments?: BreakpointLocationsArguments; } /** Arguments for 'breakpointLocations' request. */ - export interface BreakpointLocationsArguments { + interface BreakpointLocationsArguments { /** The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified. */ source: Source; /** Start line of range to search possible breakpoint locations in. If only the line is specified, the request returns all possible locations in that line. */ @@ -667,7 +666,7 @@ declare module DebugProtocol { /** Response to 'breakpointLocations' request. Contains possible locations for source breakpoints. */ - export interface BreakpointLocationsResponse extends Response { + interface BreakpointLocationsResponse extends Response { body: { /** Sorted set of possible breakpoint locations. */ breakpoints: BreakpointLocation[]; @@ -679,13 +678,13 @@ declare module DebugProtocol { To clear all breakpoint for a source, specify an empty array. When a breakpoint is hit, a 'stopped' event (with reason 'breakpoint') is generated. */ - export interface SetBreakpointsRequest extends Request { + interface SetBreakpointsRequest extends Request { // command: 'setBreakpoints'; arguments: SetBreakpointsArguments; } /** Arguments for 'setBreakpoints' request. */ - export interface SetBreakpointsArguments { + interface SetBreakpointsArguments { /** The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified. */ source: Source; /** The code locations of the breakpoints. */ @@ -702,7 +701,7 @@ declare module DebugProtocol { The breakpoints returned are in the same order as the elements of the 'breakpoints' (or the deprecated 'lines') array in the arguments. */ - export interface SetBreakpointsResponse extends Response { + interface SetBreakpointsResponse extends Response { body: { /** Information about the breakpoints. The array elements are in the same order as the elements of the 'breakpoints' (or the deprecated 'lines') array in the arguments. @@ -717,13 +716,13 @@ declare module DebugProtocol { When a function breakpoint is hit, a 'stopped' event (with reason 'function breakpoint') is generated. Clients should only call this request if the capability 'supportsFunctionBreakpoints' is true. */ - export interface SetFunctionBreakpointsRequest extends Request { + interface SetFunctionBreakpointsRequest extends Request { // command: 'setFunctionBreakpoints'; arguments: SetFunctionBreakpointsArguments; } /** Arguments for 'setFunctionBreakpoints' request. */ - export interface SetFunctionBreakpointsArguments { + interface SetFunctionBreakpointsArguments { /** The function names of the breakpoints. */ breakpoints: FunctionBreakpoint[]; } @@ -731,7 +730,7 @@ declare module DebugProtocol { /** Response to 'setFunctionBreakpoints' request. Returned is information about each breakpoint created by this request. */ - export interface SetFunctionBreakpointsResponse extends Response { + interface SetFunctionBreakpointsResponse extends Response { body: { /** Information about the breakpoints. The array elements correspond to the elements of the 'breakpoints' array. */ breakpoints: Breakpoint[]; @@ -743,13 +742,13 @@ declare module DebugProtocol { If an exception is configured to break, a 'stopped' event is fired (with reason 'exception'). Clients should only call this request if the capability 'exceptionBreakpointFilters' returns one or more filters. */ - export interface SetExceptionBreakpointsRequest extends Request { + interface SetExceptionBreakpointsRequest extends Request { // command: 'setExceptionBreakpoints'; arguments: SetExceptionBreakpointsArguments; } /** Arguments for 'setExceptionBreakpoints' request. */ - export interface SetExceptionBreakpointsArguments { + interface SetExceptionBreakpointsArguments { /** Set of exception filters specified by their ID. The set of all possible exception filters is defined by the 'exceptionBreakpointFilters' capability. The 'filter' and 'filterOptions' sets are additive. */ filters: string[]; /** Set of exception filters and their options. The set of all possible exception filters is defined by the 'exceptionBreakpointFilters' capability. This attribute is only honored by a debug adapter if the capability 'supportsExceptionFilterOptions' is true. The 'filter' and 'filterOptions' sets are additive. */ @@ -765,7 +764,7 @@ declare module DebugProtocol { The mandatory 'verified' property of a Breakpoint object signals whether the exception breakpoint or filter could be successfully created and whether the optional condition or hit count expressions are valid. In case of an error the 'message' property explains the problem. An optional 'id' property can be used to introduce a unique ID for the exception breakpoint or filter so that it can be updated subsequently by sending breakpoint events. For backward compatibility both the 'breakpoints' array and the enclosing 'body' are optional. If these elements are missing a client will not be able to show problems for individual exception breakpoints or filters. */ - export interface SetExceptionBreakpointsResponse extends Response { + interface SetExceptionBreakpointsResponse extends Response { body?: { /** Information about the exception breakpoints or filters. The breakpoints returned are in the same order as the elements of the 'filters', 'filterOptions', 'exceptionOptions' arrays in the arguments. If both 'filters' and 'filterOptions' are given, the returned array must start with 'filters' information first, followed by 'filterOptions' information. @@ -778,13 +777,13 @@ declare module DebugProtocol { Obtains information on a possible data breakpoint that could be set on an expression or variable. Clients should only call this request if the capability 'supportsDataBreakpoints' is true. */ - export interface DataBreakpointInfoRequest extends Request { + interface DataBreakpointInfoRequest extends Request { // command: 'dataBreakpointInfo'; arguments: DataBreakpointInfoArguments; } /** Arguments for 'dataBreakpointInfo' request. */ - export interface DataBreakpointInfoArguments { + interface DataBreakpointInfoArguments { /** Reference to the Variable container if the data breakpoint is requested for a child of the container. */ variablesReference?: number; /** The name of the Variable's child to obtain data breakpoint information for. @@ -794,7 +793,7 @@ declare module DebugProtocol { } /** Response to 'dataBreakpointInfo' request. */ - export interface DataBreakpointInfoResponse extends Response { + interface DataBreakpointInfoResponse extends Response { body: { /** An identifier for the data on which a data breakpoint can be registered with the setDataBreakpoints request or null if no data breakpoint is available. */ dataId: string | null; @@ -813,13 +812,13 @@ declare module DebugProtocol { When a data breakpoint is hit, a 'stopped' event (with reason 'data breakpoint') is generated. Clients should only call this request if the capability 'supportsDataBreakpoints' is true. */ - export interface SetDataBreakpointsRequest extends Request { + interface SetDataBreakpointsRequest extends Request { // command: 'setDataBreakpoints'; arguments: SetDataBreakpointsArguments; } /** Arguments for 'setDataBreakpoints' request. */ - export interface SetDataBreakpointsArguments { + interface SetDataBreakpointsArguments { /** The contents of this array replaces all existing data breakpoints. An empty array clears all data breakpoints. */ breakpoints: DataBreakpoint[]; } @@ -827,7 +826,7 @@ declare module DebugProtocol { /** Response to 'setDataBreakpoints' request. Returned is information about each breakpoint created by this request. */ - export interface SetDataBreakpointsResponse extends Response { + interface SetDataBreakpointsResponse extends Response { body: { /** Information about the data breakpoints. The array elements correspond to the elements of the input argument 'breakpoints' array. */ breakpoints: Breakpoint[]; @@ -840,19 +839,19 @@ declare module DebugProtocol { When an instruction breakpoint is hit, a 'stopped' event (with reason 'instruction breakpoint') is generated. Clients should only call this request if the capability 'supportsInstructionBreakpoints' is true. */ - export interface SetInstructionBreakpointsRequest extends Request { + interface SetInstructionBreakpointsRequest extends Request { // command: 'setInstructionBreakpoints'; arguments: SetInstructionBreakpointsArguments; } /** Arguments for 'setInstructionBreakpoints' request */ - export interface SetInstructionBreakpointsArguments { + interface SetInstructionBreakpointsArguments { /** The instruction references of the breakpoints */ breakpoints: InstructionBreakpoint[]; } /** Response to 'setInstructionBreakpoints' request */ - export interface SetInstructionBreakpointsResponse extends Response { + interface SetInstructionBreakpointsResponse extends Response { body: { /** Information about the breakpoints. The array elements correspond to the elements of the 'breakpoints' array. */ breakpoints: Breakpoint[]; @@ -862,13 +861,13 @@ declare module DebugProtocol { /** Continue request; value of command field is 'continue'. The request resumes execution of all threads. If the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true resumes only the specified thread. If not all threads were resumed, the 'allThreadsContinued' attribute of the response must be set to false. */ - export interface ContinueRequest extends Request { + interface ContinueRequest extends Request { // command: 'continue'; arguments: ContinueArguments; } /** Arguments for 'continue' request. */ - export interface ContinueArguments { + interface ContinueArguments { /** Specifies the active thread. If the debug adapter supports single thread execution (see 'supportsSingleThreadExecutionRequests') and the optional argument 'singleThread' is true, only the thread with this ID is resumed. */ threadId: number; /** If this optional flag is true, execution is resumed only for the thread with given 'threadId'. */ @@ -876,7 +875,7 @@ declare module DebugProtocol { } /** Response to 'continue' request. */ - export interface ContinueResponse extends Response { + interface ContinueResponse extends Response { body: { /** The value true (or a missing property) signals to the client that all threads have been resumed. The value false must be returned if not all threads were resumed. */ allThreadsContinued?: boolean; @@ -888,13 +887,13 @@ declare module DebugProtocol { If the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other suspended threads from resuming. The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed. */ - export interface NextRequest extends Request { + interface NextRequest extends Request { // command: 'next'; arguments: NextArguments; } /** Arguments for 'next' request. */ - export interface NextArguments { + interface NextArguments { /** Specifies the thread for which to resume execution for one step (of the given granularity). */ threadId: number; /** If this optional flag is true, all other suspended threads are not resumed. */ @@ -904,7 +903,7 @@ declare module DebugProtocol { } /** Response to 'next' request. This is just an acknowledgement, so no body field is required. */ - export interface NextResponse extends Response { + interface NextResponse extends Response { } /** StepIn request; value of command field is 'stepIn'. @@ -916,13 +915,13 @@ declare module DebugProtocol { the optional argument 'targetId' can be used to control into which target the 'stepIn' should occur. The list of possible targets for a given source line can be retrieved via the 'stepInTargets' request. */ - export interface StepInRequest extends Request { + interface StepInRequest extends Request { // command: 'stepIn'; arguments: StepInArguments; } /** Arguments for 'stepIn' request. */ - export interface StepInArguments { + interface StepInArguments { /** Specifies the thread for which to resume execution for one step-into (of the given granularity). */ threadId: number; /** If this optional flag is true, all other suspended threads are not resumed. */ @@ -934,7 +933,7 @@ declare module DebugProtocol { } /** Response to 'stepIn' request. This is just an acknowledgement, so no body field is required. */ - export interface StepInResponse extends Response { + interface StepInResponse extends Response { } /** StepOut request; value of command field is 'stepOut'. @@ -942,13 +941,13 @@ declare module DebugProtocol { If the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other suspended threads from resuming. The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed. */ - export interface StepOutRequest extends Request { + interface StepOutRequest extends Request { // command: 'stepOut'; arguments: StepOutArguments; } /** Arguments for 'stepOut' request. */ - export interface StepOutArguments { + interface StepOutArguments { /** Specifies the thread for which to resume execution for one step-out (of the given granularity). */ threadId: number; /** If this optional flag is true, all other suspended threads are not resumed. */ @@ -958,7 +957,7 @@ declare module DebugProtocol { } /** Response to 'stepOut' request. This is just an acknowledgement, so no body field is required. */ - export interface StepOutResponse extends Response { + interface StepOutResponse extends Response { } /** StepBack request; value of command field is 'stepBack'. @@ -967,13 +966,13 @@ declare module DebugProtocol { The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed. Clients should only call this request if the capability 'supportsStepBack' is true. */ - export interface StepBackRequest extends Request { + interface StepBackRequest extends Request { // command: 'stepBack'; arguments: StepBackArguments; } /** Arguments for 'stepBack' request. */ - export interface StepBackArguments { + interface StepBackArguments { /** Specifies the thread for which to resume execution for one step backwards (of the given granularity). */ threadId: number; /** If this optional flag is true, all other suspended threads are not resumed. */ @@ -983,20 +982,20 @@ declare module DebugProtocol { } /** Response to 'stepBack' request. This is just an acknowledgement, so no body field is required. */ - export interface StepBackResponse extends Response { + interface StepBackResponse extends Response { } /** ReverseContinue request; value of command field is 'reverseContinue'. The request resumes backward execution of all threads. If the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true resumes only the specified thread. If not all threads were resumed, the 'allThreadsContinued' attribute of the response must be set to false. Clients should only call this request if the capability 'supportsStepBack' is true. */ - export interface ReverseContinueRequest extends Request { + interface ReverseContinueRequest extends Request { // command: 'reverseContinue'; arguments: ReverseContinueArguments; } /** Arguments for 'reverseContinue' request. */ - export interface ReverseContinueArguments { + interface ReverseContinueArguments { /** Specifies the active thread. If the debug adapter supports single thread execution (see 'supportsSingleThreadExecutionRequests') and the optional argument 'singleThread' is true, only the thread with this ID is resumed. */ threadId: number; /** If this optional flag is true, backward execution is resumed only for the thread with given 'threadId'. */ @@ -1004,7 +1003,7 @@ declare module DebugProtocol { } /** Response to 'reverseContinue' request. This is just an acknowledgement, so no body field is required. */ - export interface ReverseContinueResponse extends Response { + interface ReverseContinueResponse extends Response { } /** RestartFrame request; value of command field is 'restartFrame'. @@ -1012,19 +1011,19 @@ declare module DebugProtocol { The debug adapter first sends the response and then a 'stopped' event (with reason 'restart') after the restart has completed. Clients should only call this request if the capability 'supportsRestartFrame' is true. */ - export interface RestartFrameRequest extends Request { + interface RestartFrameRequest extends Request { // command: 'restartFrame'; arguments: RestartFrameArguments; } /** Arguments for 'restartFrame' request. */ - export interface RestartFrameArguments { + interface RestartFrameArguments { /** Restart this stackframe. */ frameId: number; } /** Response to 'restartFrame' request. This is just an acknowledgement, so no body field is required. */ - export interface RestartFrameResponse extends Response { + interface RestartFrameResponse extends Response { } /** Goto request; value of command field is 'goto'. @@ -1034,13 +1033,13 @@ declare module DebugProtocol { The debug adapter first sends the response and then a 'stopped' event with reason 'goto'. Clients should only call this request if the capability 'supportsGotoTargetsRequest' is true (because only then goto targets exist that can be passed as arguments). */ - export interface GotoRequest extends Request { + interface GotoRequest extends Request { // command: 'goto'; arguments: GotoArguments; } /** Arguments for 'goto' request. */ - export interface GotoArguments { + interface GotoArguments { /** Set the goto target for this thread. */ threadId: number; /** The location where the debuggee will continue to run. */ @@ -1048,39 +1047,39 @@ declare module DebugProtocol { } /** Response to 'goto' request. This is just an acknowledgement, so no body field is required. */ - export interface GotoResponse extends Response { + interface GotoResponse extends Response { } /** Pause request; value of command field is 'pause'. The request suspends the debuggee. The debug adapter first sends the response and then a 'stopped' event (with reason 'pause') after the thread has been paused successfully. */ - export interface PauseRequest extends Request { + interface PauseRequest extends Request { // command: 'pause'; arguments: PauseArguments; } /** Arguments for 'pause' request. */ - export interface PauseArguments { + interface PauseArguments { /** Pause execution for this thread. */ threadId: number; } /** Response to 'pause' request. This is just an acknowledgement, so no body field is required. */ - export interface PauseResponse extends Response { + interface PauseResponse extends Response { } /** StackTrace request; value of command field is 'stackTrace'. The request returns a stacktrace from the current execution state of a given thread. A client can request all stack frames by omitting the startFrame and levels arguments. For performance conscious clients and if the debug adapter's 'supportsDelayedStackTraceLoading' capability is true, stack frames can be retrieved in a piecemeal way with the startFrame and levels arguments. The response of the stackTrace request may contain a totalFrames property that hints at the total number of frames in the stack. If a client needs this total number upfront, it can issue a request for a single (first) frame and depending on the value of totalFrames decide how to proceed. In any case a client should be prepared to receive less frames than requested, which is an indication that the end of the stack has been reached. */ - export interface StackTraceRequest extends Request { + interface StackTraceRequest extends Request { // command: 'stackTrace'; arguments: StackTraceArguments; } /** Arguments for 'stackTrace' request. */ - export interface StackTraceArguments { + interface StackTraceArguments { /** Retrieve the stacktrace for this thread. */ threadId: number; /** The index of the first frame to return; if omitted frames start at 0. */ @@ -1094,7 +1093,7 @@ declare module DebugProtocol { } /** Response to 'stackTrace' request. */ - export interface StackTraceResponse extends Response { + interface StackTraceResponse extends Response { body: { /** The frames of the stackframe. If the array has length zero, there are no stackframes available. This means that there is no location information available. @@ -1108,19 +1107,19 @@ declare module DebugProtocol { /** Scopes request; value of command field is 'scopes'. The request returns the variable scopes for a given stackframe ID. */ - export interface ScopesRequest extends Request { + interface ScopesRequest extends Request { // command: 'scopes'; arguments: ScopesArguments; } /** Arguments for 'scopes' request. */ - export interface ScopesArguments { + interface ScopesArguments { /** Retrieve the scopes for this stackframe. */ frameId: number; } /** Response to 'scopes' request. */ - export interface ScopesResponse extends Response { + interface ScopesResponse extends Response { body: { /** The scopes of the stackframe. If the array has length zero, there are no scopes available. */ scopes: Scope[]; @@ -1131,13 +1130,13 @@ declare module DebugProtocol { Retrieves all child variables for the given variable reference. An optional filter can be used to limit the fetched children to either named or indexed children. */ - export interface VariablesRequest extends Request { + interface VariablesRequest extends Request { // command: 'variables'; arguments: VariablesArguments; } /** Arguments for 'variables' request. */ - export interface VariablesArguments { + interface VariablesArguments { /** The Variable reference. */ variablesReference: number; /** Optional filter to limit the child variables to either named or indexed. If omitted, both types are fetched. */ @@ -1153,7 +1152,7 @@ declare module DebugProtocol { } /** Response to 'variables' request. */ - export interface VariablesResponse extends Response { + interface VariablesResponse extends Response { body: { /** All (or a range) of variables for the given variable reference. */ variables: Variable[]; @@ -1164,13 +1163,13 @@ declare module DebugProtocol { Set the variable with the given name in the variable container to a new value. Clients should only call this request if the capability 'supportsSetVariable' is true. If a debug adapter implements both setVariable and setExpression, a client will only use setExpression if the variable has an evaluateName property. */ - export interface SetVariableRequest extends Request { + interface SetVariableRequest extends Request { // command: 'setVariable'; arguments: SetVariableArguments; } /** Arguments for 'setVariable' request. */ - export interface SetVariableArguments { + interface SetVariableArguments { /** The reference of the variable container. */ variablesReference: number; /** The name of the variable in the container. */ @@ -1182,7 +1181,7 @@ declare module DebugProtocol { } /** Response to 'setVariable' request. */ - export interface SetVariableResponse extends Response { + interface SetVariableResponse extends Response { body: { /** The new value of the variable. */ value: string; @@ -1208,13 +1207,13 @@ declare module DebugProtocol { /** Source request; value of command field is 'source'. The request retrieves the source code for a given source reference. */ - export interface SourceRequest extends Request { + interface SourceRequest extends Request { // command: 'source'; arguments: SourceArguments; } /** Arguments for 'source' request. */ - export interface SourceArguments { + interface SourceArguments { /** Specifies the source content to load. Either source.path or source.sourceReference must be specified. */ source?: Source; /** The reference to the source. This is the same as source.sourceReference. @@ -1224,7 +1223,7 @@ declare module DebugProtocol { } /** Response to 'source' request. */ - export interface SourceResponse extends Response { + interface SourceResponse extends Response { body: { /** Content of the source reference. */ content: string; @@ -1236,12 +1235,12 @@ declare module DebugProtocol { /** Threads request; value of command field is 'threads'. The request retrieves a list of all threads. */ - export interface ThreadsRequest extends Request { + interface ThreadsRequest extends Request { // command: 'threads'; } /** Response to 'threads' request. */ - export interface ThreadsResponse extends Response { + interface ThreadsResponse extends Response { body: { /** All threads. */ threads: Thread[]; @@ -1252,32 +1251,32 @@ declare module DebugProtocol { The request terminates the threads with the given ids. Clients should only call this request if the capability 'supportsTerminateThreadsRequest' is true. */ - export interface TerminateThreadsRequest extends Request { + interface TerminateThreadsRequest extends Request { // command: 'terminateThreads'; arguments: TerminateThreadsArguments; } /** Arguments for 'terminateThreads' request. */ - export interface TerminateThreadsArguments { + interface TerminateThreadsArguments { /** Ids of threads to be terminated. */ threadIds?: number[]; } /** Response to 'terminateThreads' request. This is just an acknowledgement, so no body field is required. */ - export interface TerminateThreadsResponse extends Response { + interface TerminateThreadsResponse extends Response { } /** Modules request; value of command field is 'modules'. Modules can be retrieved from the debug adapter with this request which can either return all modules or a range of modules to support paging. Clients should only call this request if the capability 'supportsModulesRequest' is true. */ - export interface ModulesRequest extends Request { + interface ModulesRequest extends Request { // command: 'modules'; arguments: ModulesArguments; } /** Arguments for 'modules' request. */ - export interface ModulesArguments { + interface ModulesArguments { /** The index of the first module to return; if omitted modules start at 0. */ startModule?: number; /** The number of modules to return. If moduleCount is not specified or 0, all modules are returned. */ @@ -1285,7 +1284,7 @@ declare module DebugProtocol { } /** Response to 'modules' request. */ - export interface ModulesResponse extends Response { + interface ModulesResponse extends Response { body: { /** All modules or range of modules. */ modules: Module[]; @@ -1298,17 +1297,17 @@ declare module DebugProtocol { Retrieves the set of all sources currently loaded by the debugged process. Clients should only call this request if the capability 'supportsLoadedSourcesRequest' is true. */ - export interface LoadedSourcesRequest extends Request { + interface LoadedSourcesRequest extends Request { // command: 'loadedSources'; arguments?: LoadedSourcesArguments; } /** Arguments for 'loadedSources' request. */ - export interface LoadedSourcesArguments { + interface LoadedSourcesArguments { } /** Response to 'loadedSources' request. */ - export interface LoadedSourcesResponse extends Response { + interface LoadedSourcesResponse extends Response { body: { /** Set of loaded sources. */ sources: Source[]; @@ -1319,35 +1318,37 @@ declare module DebugProtocol { Evaluates the given expression in the context of the top most stack frame. The expression has access to any variables and arguments that are in scope. */ - export interface EvaluateRequest extends Request { + interface EvaluateRequest extends Request { // command: 'evaluate'; arguments: EvaluateArguments; } /** Arguments for 'evaluate' request. */ - export interface EvaluateArguments { + interface EvaluateArguments { /** The expression to evaluate. */ expression: string; /** Evaluate the expression in the scope of this stack frame. If not specified, the expression is evaluated in the global scope. */ frameId?: number; - /** The context in which the evaluate request is run. + /** The context in which the evaluate request is used. Values: - 'watch': evaluate is run in a watch. - 'repl': evaluate is run from REPL console. - 'hover': evaluate is run from a data hover. - 'clipboard': evaluate is run to generate the value that will be stored in the clipboard. - The attribute is only honored by a debug adapter if the capability 'supportsClipboardContext' is true. + 'variables': evaluate is called from a variables view context. + 'watch': evaluate is called from a watch view context. + 'repl': evaluate is called from a REPL context. + 'hover': evaluate is called to generate the debug hover contents. + This value should only be used if the capability 'supportsEvaluateForHovers' is true. + 'clipboard': evaluate is called to generate clipboard contents. + This value should only be used if the capability 'supportsClipboardContext' is true. etc. */ - context?: 'watch' | 'repl' | 'hover' | 'clipboard' | string; - /** Specifies details on how to format the Evaluate result. + context?: 'variables' | 'watch' | 'repl' | 'hover' | 'clipboard' | string; + /** Specifies details on how to format the result. The attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true. */ format?: ValueFormat; } /** Response to 'evaluate' request. */ - export interface EvaluateResponse extends Response { + interface EvaluateResponse extends Response { body: { /** The result of the evaluate request. */ result: string; @@ -1385,13 +1386,13 @@ declare module DebugProtocol { Clients should only call this request if the capability 'supportsSetExpression' is true. If a debug adapter implements both setExpression and setVariable, a client will only use setExpression if the variable has an evaluateName property. */ - export interface SetExpressionRequest extends Request { + interface SetExpressionRequest extends Request { // command: 'setExpression'; arguments: SetExpressionArguments; } /** Arguments for 'setExpression' request. */ - export interface SetExpressionArguments { + interface SetExpressionArguments { /** The l-value expression to assign to. */ expression: string; /** The value expression to assign to the l-value expression. */ @@ -1403,7 +1404,7 @@ declare module DebugProtocol { } /** Response to 'setExpression' request. */ - export interface SetExpressionResponse extends Response { + interface SetExpressionResponse extends Response { body: { /** The new value of the expression. */ value: string; @@ -1436,19 +1437,19 @@ declare module DebugProtocol { The StepInTargets may only be called if the 'supportsStepInTargetsRequest' capability exists and is true. Clients should only call this request if the capability 'supportsStepInTargetsRequest' is true. */ - export interface StepInTargetsRequest extends Request { + interface StepInTargetsRequest extends Request { // command: 'stepInTargets'; arguments: StepInTargetsArguments; } /** Arguments for 'stepInTargets' request. */ - export interface StepInTargetsArguments { + interface StepInTargetsArguments { /** The stack frame for which to retrieve the possible stepIn targets. */ frameId: number; } /** Response to 'stepInTargets' request. */ - export interface StepInTargetsResponse extends Response { + interface StepInTargetsResponse extends Response { body: { /** The possible stepIn targets of the specified source location. */ targets: StepInTarget[]; @@ -1460,13 +1461,13 @@ declare module DebugProtocol { These targets can be used in the 'goto' request. Clients should only call this request if the capability 'supportsGotoTargetsRequest' is true. */ - export interface GotoTargetsRequest extends Request { + interface GotoTargetsRequest extends Request { // command: 'gotoTargets'; arguments: GotoTargetsArguments; } /** Arguments for 'gotoTargets' request. */ - export interface GotoTargetsArguments { + interface GotoTargetsArguments { /** The source location for which the goto targets are determined. */ source: Source; /** The line location for which the goto targets are determined. */ @@ -1476,7 +1477,7 @@ declare module DebugProtocol { } /** Response to 'gotoTargets' request. */ - export interface GotoTargetsResponse extends Response { + interface GotoTargetsResponse extends Response { body: { /** The possible goto targets of the specified location. */ targets: GotoTarget[]; @@ -1487,13 +1488,13 @@ declare module DebugProtocol { Returns a list of possible completions for a given caret position and text. Clients should only call this request if the capability 'supportsCompletionsRequest' is true. */ - export interface CompletionsRequest extends Request { + interface CompletionsRequest extends Request { // command: 'completions'; arguments: CompletionsArguments; } /** Arguments for 'completions' request. */ - export interface CompletionsArguments { + interface CompletionsArguments { /** Returns completions in the scope of this stack frame. If not specified, the completions are returned for the global scope. */ frameId?: number; /** One or more source lines. Typically this is the text a user has typed into the debug console before he asked for completion. */ @@ -1505,7 +1506,7 @@ declare module DebugProtocol { } /** Response to 'completions' request. */ - export interface CompletionsResponse extends Response { + interface CompletionsResponse extends Response { body: { /** The possible completions for . */ targets: CompletionItem[]; @@ -1516,19 +1517,19 @@ declare module DebugProtocol { Retrieves the details of the exception that caused this event to be raised. Clients should only call this request if the capability 'supportsExceptionInfoRequest' is true. */ - export interface ExceptionInfoRequest extends Request { + interface ExceptionInfoRequest extends Request { // command: 'exceptionInfo'; arguments: ExceptionInfoArguments; } /** Arguments for 'exceptionInfo' request. */ - export interface ExceptionInfoArguments { + interface ExceptionInfoArguments { /** Thread for which exception information should be retrieved. */ threadId: number; } /** Response to 'exceptionInfo' request. */ - export interface ExceptionInfoResponse extends Response { + interface ExceptionInfoResponse extends Response { body: { /** ID of the exception that was thrown. */ exceptionId: string; @@ -1545,13 +1546,13 @@ declare module DebugProtocol { Reads bytes from memory at the provided location. Clients should only call this request if the capability 'supportsReadMemoryRequest' is true. */ - export interface ReadMemoryRequest extends Request { + interface ReadMemoryRequest extends Request { // command: 'readMemory'; arguments: ReadMemoryArguments; } /** Arguments for 'readMemory' request. */ - export interface ReadMemoryArguments { + interface ReadMemoryArguments { /** Memory reference to the base location from which data should be read. */ memoryReference: string; /** Optional offset (in bytes) to be applied to the reference location before reading data. Can be negative. */ @@ -1561,7 +1562,7 @@ declare module DebugProtocol { } /** Response to 'readMemory' request. */ - export interface ReadMemoryResponse extends Response { + interface ReadMemoryResponse extends Response { body?: { /** The address of the first byte of data returned. Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. @@ -1580,13 +1581,13 @@ declare module DebugProtocol { Writes bytes to memory at the provided location. Clients should only call this request if the capability 'supportsWriteMemoryRequest' is true. */ - export interface WriteMemoryRequest extends Request { + interface WriteMemoryRequest extends Request { // command: 'writeMemory'; arguments: WriteMemoryArguments; } /** Arguments for 'writeMemory' request. */ - export interface WriteMemoryArguments { + interface WriteMemoryArguments { /** Memory reference to the base location to which data should be written. */ memoryReference: string; /** Optional offset (in bytes) to be applied to the reference location before writing data. Can be negative. */ @@ -1600,7 +1601,7 @@ declare module DebugProtocol { } /** Response to 'writeMemory' request. */ - export interface WriteMemoryResponse extends Response { + interface WriteMemoryResponse extends Response { body?: { /** Optional property that should be returned when 'allowPartial' is true to indicate the offset of the first byte of data successfully written. Can be negative. */ offset?: number; @@ -1613,13 +1614,13 @@ declare module DebugProtocol { Disassembles code stored at the provided location. Clients should only call this request if the capability 'supportsDisassembleRequest' is true. */ - export interface DisassembleRequest extends Request { + interface DisassembleRequest extends Request { // command: 'disassemble'; arguments: DisassembleArguments; } /** Arguments for 'disassemble' request. */ - export interface DisassembleArguments { + interface DisassembleArguments { /** Memory reference to the base location containing the instructions to disassemble. */ memoryReference: string; /** Optional offset (in bytes) to be applied to the reference location before disassembling. Can be negative. */ @@ -1635,7 +1636,7 @@ declare module DebugProtocol { } /** Response to 'disassemble' request. */ - export interface DisassembleResponse extends Response { + interface DisassembleResponse extends Response { body?: { /** The list of disassembled instructions. */ instructions: DisassembledInstruction[]; @@ -1643,7 +1644,7 @@ declare module DebugProtocol { } /** Information about the capabilities of a debug adapter. */ - export interface Capabilities { + interface Capabilities { /** The debug adapter supports the 'configurationDone' request. */ supportsConfigurationDoneRequest?: boolean; /** The debug adapter supports function breakpoints. */ @@ -1725,7 +1726,7 @@ declare module DebugProtocol { } /** An ExceptionBreakpointsFilter is shown in the UI as an filter option for configuring how exceptions are dealt with. */ - export interface ExceptionBreakpointsFilter { + interface ExceptionBreakpointsFilter { /** The internal ID of the filter option. This value is passed to the 'setExceptionBreakpoints' request. */ filter: string; /** The name of the filter option. This will be shown in the UI. */ @@ -1741,7 +1742,7 @@ declare module DebugProtocol { } /** A structured message object. Used to return errors from requests. */ - export interface Message { + interface Message { /** Unique identifier for the message. */ id: number; /** A format string for the message. Embedded variables have the form '{name}'. @@ -1769,7 +1770,7 @@ declare module DebugProtocol { To avoid an unnecessary proliferation of additional attributes with similar semantics but different names we recommend to re-use attributes from the 'recommended' list below first, and only introduce new attributes if nothing appropriate could be found. */ - export interface Module { + interface Module { /** Unique identifier for the module. */ id: number | string; /** A name of the module. */ @@ -1800,7 +1801,7 @@ declare module DebugProtocol { and what the column's label should be. It is only used if the underlying UI actually supports this level of customization. */ - export interface ColumnDescriptor { + interface ColumnDescriptor { /** Name of the attribute rendered in this column. */ attributeName: string; /** Header UI label of column. */ @@ -1816,12 +1817,12 @@ declare module DebugProtocol { /** The ModulesViewDescriptor is the container for all declarative configuration options of a ModuleView. For now it only specifies the columns to be shown in the modules view. */ - export interface ModulesViewDescriptor { + interface ModulesViewDescriptor { columns: ColumnDescriptor[]; } /** A Thread */ - export interface Thread { + interface Thread { /** Unique identifier for the thread. */ id: number; /** A name of the thread. */ @@ -1831,7 +1832,7 @@ declare module DebugProtocol { /** A Source is a descriptor for source code. It is returned from the debug adapter as part of a StackFrame and it is used by clients when specifying breakpoints. */ - export interface Source { + interface Source { /** The short name of the source. Every source returned from the debug adapter has a name. When sending a source to the debug adapter this name is optional. */ @@ -1862,7 +1863,7 @@ declare module DebugProtocol { } /** A Stackframe contains the source location. */ - export interface StackFrame { + interface StackFrame { /** An identifier for the stack frame. It must be unique across all threads. This id can be used to retrieve the scopes of the frame with the 'scopesRequest' or to restart the execution of a stackframe. */ @@ -1892,7 +1893,7 @@ declare module DebugProtocol { } /** A Scope is a named container for variables. Optionally a scope can map to a source or a range within a source. */ - export interface Scope { + interface Scope { /** Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This string is shown in the UI as is and can be translated. */ name: string; /** An optional hint for how to present this scope in the UI. If this attribute is missing, the scope is shown with a generic UI. @@ -1934,7 +1935,7 @@ declare module DebugProtocol { If the number of named or indexed children is large, the numbers should be returned via the optional 'namedVariables' and 'indexedVariables' attributes. The client can use this optional information to present the children in a paged UI and fetch them in chunks. */ - export interface Variable { + interface Variable { /** The variable's name. */ name: string; /** The variable's value. @@ -1968,7 +1969,7 @@ declare module DebugProtocol { } /** Optional properties of a variable that can be used to determine how to render the variable in the UI. */ - export interface VariablePresentationHint { + interface VariablePresentationHint { /** The kind of variable. Before introducing additional values, try to use the listed values. Values: 'property': Indicates that the object is a property. @@ -2011,7 +2012,7 @@ declare module DebugProtocol { } /** Properties of a breakpoint location returned from the 'breakpointLocations' request. */ - export interface BreakpointLocation { + interface BreakpointLocation { /** Start line of breakpoint location. */ line: number; /** Optional start column of breakpoint location. */ @@ -2023,7 +2024,7 @@ declare module DebugProtocol { } /** Properties of a breakpoint or logpoint passed to the setBreakpoints request. */ - export interface SourceBreakpoint { + interface SourceBreakpoint { /** The source line of the breakpoint or logpoint. */ line: number; /** An optional source column of the breakpoint. */ @@ -2045,7 +2046,7 @@ declare module DebugProtocol { } /** Properties of a breakpoint passed to the setFunctionBreakpoints request. */ - export interface FunctionBreakpoint { + interface FunctionBreakpoint { /** The name of the function. */ name: string; /** An optional expression for conditional breakpoints. @@ -2060,10 +2061,10 @@ declare module DebugProtocol { } /** This enumeration defines all possible access types for data breakpoints. */ - export type DataBreakpointAccessType = 'read' | 'write' | 'readWrite'; + type DataBreakpointAccessType = 'read' | 'write' | 'readWrite'; /** Properties of a data breakpoint passed to the setDataBreakpoints request. */ - export interface DataBreakpoint { + interface DataBreakpoint { /** An id representing the data. This id is returned from the dataBreakpointInfo request. */ dataId: string; /** The access type of the data. */ @@ -2077,7 +2078,7 @@ declare module DebugProtocol { } /** Properties of a breakpoint passed to the setInstructionBreakpoints request */ - export interface InstructionBreakpoint { + interface InstructionBreakpoint { /** The instruction reference of the breakpoint. This should be a memory or instruction pointer reference from an EvaluateResponse, Variable, StackFrame, GotoTarget, or Breakpoint. */ @@ -2098,7 +2099,7 @@ declare module DebugProtocol { } /** Information about a Breakpoint created in setBreakpoints, setFunctionBreakpoints, setInstructionBreakpoints, or setDataBreakpoints. */ - export interface Breakpoint { + interface Breakpoint { /** An optional identifier for the breakpoint. It is needed if breakpoint events are used to update or remove breakpoints. */ id?: number; /** If true breakpoint could be set (but not necessarily at the desired location). */ @@ -2134,10 +2135,10 @@ declare module DebugProtocol { 'line': The step should allow the program to run until the current source line has executed. 'instruction': The step should allow one instruction to execute (e.g. one x86 instruction). */ - export type SteppingGranularity = 'statement' | 'line' | 'instruction'; + type SteppingGranularity = 'statement' | 'line' | 'instruction'; /** A StepInTarget can be used in the 'stepIn' request and determines into which single target the stepIn request should step. */ - export interface StepInTarget { + interface StepInTarget { /** Unique identifier for a stepIn target. */ id: number; /** The name of the stepIn target (shown in the UI). */ @@ -2147,7 +2148,7 @@ declare module DebugProtocol { /** A GotoTarget describes a code location that can be used as a target in the 'goto' request. The possible goto targets can be determined via the 'gotoTargets' request. */ - export interface GotoTarget { + interface GotoTarget { /** Unique identifier for a goto target. This is used in the goto request. */ id: number; /** The name of the goto target (shown in the UI). */ @@ -2165,7 +2166,7 @@ declare module DebugProtocol { } /** CompletionItems are the suggestions returned from the CompletionsRequest. */ - export interface CompletionItem { + interface CompletionItem { /** The label of this completion item. By default this is also the text that is inserted when selecting this completion. */ label: string; /** If text is not falsy then it is inserted instead of the label. */ @@ -2197,13 +2198,13 @@ declare module DebugProtocol { } /** Some predefined types for the CompletionItem. Please note that not all clients have specific icons for all of them. */ - export type CompletionItemType = 'method' | 'function' | 'constructor' | 'field' | 'variable' | 'class' | 'interface' | 'module' | 'property' | 'unit' | 'value' | 'enum' | 'keyword' | 'snippet' | 'text' | 'color' | 'file' | 'reference' | 'customcolor'; + type CompletionItemType = 'method' | 'function' | 'constructor' | 'field' | 'variable' | 'class' | 'interface' | 'module' | 'property' | 'unit' | 'value' | 'enum' | 'keyword' | 'snippet' | 'text' | 'color' | 'file' | 'reference' | 'customcolor'; /** Names of checksum algorithms that may be supported by a debug adapter. */ - export type ChecksumAlgorithm = 'MD5' | 'SHA1' | 'SHA256' | 'timestamp'; + type ChecksumAlgorithm = 'MD5' | 'SHA1' | 'SHA256' | 'timestamp'; /** The checksum of an item calculated by the specified algorithm. */ - export interface Checksum { + interface Checksum { /** The algorithm used to calculate this checksum. */ algorithm: ChecksumAlgorithm; /** Value of the checksum. */ @@ -2211,13 +2212,13 @@ declare module DebugProtocol { } /** Provides formatting information for a value. */ - export interface ValueFormat { + interface ValueFormat { /** Display the value in hex. */ hex?: boolean; } /** Provides formatting information for a stack frame. */ - export interface StackFrameFormat extends ValueFormat { + interface StackFrameFormat extends ValueFormat { /** Displays parameters for the stack frame. */ parameters?: boolean; /** Displays the types of parameters for the stack frame. */ @@ -2234,8 +2235,8 @@ declare module DebugProtocol { includeAll?: boolean; } - /** An ExceptionFilterOptions is used to specify an exception filter together with a condition for the setExceptionsFilter request. */ - export interface ExceptionFilterOptions { + /** An ExceptionFilterOptions is used to specify an exception filter together with a condition for the 'setExceptionBreakpoints' request. */ + interface ExceptionFilterOptions { /** ID of an exception filter returned by the 'exceptionBreakpointFilters' capability. */ filterId: string; /** An optional expression for conditional exceptions. @@ -2245,7 +2246,7 @@ declare module DebugProtocol { } /** An ExceptionOptions assigns configuration options to a set of exceptions. */ - export interface ExceptionOptions { + interface ExceptionOptions { /** A path that selects a single or multiple exceptions in a tree. If 'path' is missing, the whole tree is selected. By convention the first segment of the path is a category that is used to group exceptions in the UI. */ @@ -2260,13 +2261,13 @@ declare module DebugProtocol { unhandled: breaks when exception unhandled, userUnhandled: breaks if the exception is not handled by user code. */ - export type ExceptionBreakMode = 'never' | 'always' | 'unhandled' | 'userUnhandled'; + type ExceptionBreakMode = 'never' | 'always' | 'unhandled' | 'userUnhandled'; /** An ExceptionPathSegment represents a segment in a path that is used to match leafs or nodes in a tree of exceptions. If a segment consists of more than one name, it matches the names provided if 'negate' is false or missing or it matches anything except the names provided if 'negate' is true. */ - export interface ExceptionPathSegment { + interface ExceptionPathSegment { /** If false or missing this segment matches the names provided, otherwise it matches anything except the names provided. */ negate?: boolean; /** Depending on the value of 'negate' the names that should match or not match. */ @@ -2274,7 +2275,7 @@ declare module DebugProtocol { } /** Detailed information about an exception that has occurred. */ - export interface ExceptionDetails { + interface ExceptionDetails { /** Message contained in the exception. */ message?: string; /** Short type name of the exception object. */ @@ -2290,7 +2291,7 @@ declare module DebugProtocol { } /** Represents a single disassembled instruction. */ - export interface DisassembledInstruction { + interface DisassembledInstruction { /** The address of the instruction. Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. */ address: string; /** Optional raw bytes representing the instruction and its operands, in an implementation-defined format. */ @@ -2322,6 +2323,6 @@ declare module DebugProtocol { 'variables': Previously fetched variable data has become invalid and needs to be refetched. etc. */ - export type InvalidatedAreas = 'all' | 'stacks' | 'threads' | 'variables' | string; + type InvalidatedAreas = 'all' | 'stacks' | 'threads' | 'variables' | string; } diff --git a/yarn.lock b/yarn.lock index 8b7937639c5..d43245dd02f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1556,11 +1556,6 @@ resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== -"@vscode/debugprotocol@1.54.0": - version "1.54.0" - resolved "https://registry.yarnpkg.com/@vscode/debugprotocol/-/debugprotocol-1.54.0.tgz#d0e687e4963e8535b94a8d549486ce25438d1a7c" - integrity sha512-/Qt6ICgqj2OzIsTJ9JJ4JTsvNz1ql+tfdbvtTWZCLJbDgkHwPNUSr6iKwCjgcZ7Hz8SbzVK8e9vIV/L7R21FCQ== - "@vscode/iconv-lite-umd@0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz#d2f1e0664ee6036408f9743fee264ea0699b0e48" From 12f0c7bfdca157976e41f54842e43e229b259026 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 9 Mar 2022 16:02:55 -0800 Subject: [PATCH 091/175] Bump @vscode/ripgrep --- package.json | 2 +- remote/package.json | 2 +- remote/yarn.lock | 23 +++++------------------ yarn.lock | 10 +++++----- 4 files changed, 12 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index e82e3bfa8d3..183eb42597b 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "@microsoft/applicationinsights-web": "^2.6.4", "@parcel/watcher": "2.0.5", "@vscode/iconv-lite-umd": "0.7.0", - "@vscode/ripgrep": "^1.14.1", + "@vscode/ripgrep": "^1.14.2", "@vscode/sqlite3": "4.0.12", "@vscode/sudo-prompt": "9.3.1", "@vscode/vscode-languagedetection": "1.0.21", diff --git a/remote/package.json b/remote/package.json index f353b702051..896b5292e41 100644 --- a/remote/package.json +++ b/remote/package.json @@ -6,7 +6,7 @@ "@microsoft/applicationinsights-web": "^2.6.4", "@parcel/watcher": "2.0.5", "@vscode/iconv-lite-umd": "0.7.0", - "@vscode/ripgrep": "^1.14.1", + "@vscode/ripgrep": "^1.14.2", "@vscode/vscode-languagedetection": "1.0.21", "applicationinsights": "1.4.2", "cookie": "^0.4.0", diff --git a/remote/yarn.lock b/remote/yarn.lock index cf092242bda..48a2ef7b2d6 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -101,12 +101,12 @@ resolved "https://registry.yarnpkg.com/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz#d2f1e0664ee6036408f9743fee264ea0699b0e48" integrity sha512-bRRFxLfg5dtAyl5XyiVWz/ZBPahpOpPrNYnnHpOpUZvam4tKH35wdhP4Kj6PbM0+KdliOsPzbGWpkxcdpNB/sg== -"@vscode/ripgrep@^1.14.1": - version "1.14.1" - resolved "https://registry.yarnpkg.com/@vscode/ripgrep/-/ripgrep-1.14.1.tgz#66b104a6c7283d17672eb01c02b1c1294d4bb2ae" - integrity sha512-f2N/iPZhxP9bho7iK0DibJDprU+spE8hTIvQg1fi8v82oWIWU9IB4a92444GyxSaFgb+hWpQe46QkFDh5W1VpQ== +"@vscode/ripgrep@^1.14.2": + version "1.14.2" + resolved "https://registry.yarnpkg.com/@vscode/ripgrep/-/ripgrep-1.14.2.tgz#47c0eec2b64f53d8f7e1b5ffd22a62e229191c34" + integrity sha512-KDaehS8Jfdg1dqStaIPDKYh66jzKd5jy5aYEPzIv0JYFLADPsCSQPBUdsJVXnr0t72OlDcj96W05xt/rSnNFFQ== dependencies: - https-proxy-agent "^4.0.0" + https-proxy-agent "^5.0.0" proxy-from-env "^1.1.0" "@vscode/vscode-languagedetection@1.0.21": @@ -126,11 +126,6 @@ agent-base@4: dependencies: es6-promisify "^5.0.0" -agent-base@5: - version "5.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c" - integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== - agent-base@6, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -431,14 +426,6 @@ https-proxy-agent@^2.2.3: agent-base "^4.3.0" debug "^3.1.0" -https-proxy-agent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b" - integrity sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg== - dependencies: - agent-base "5" - debug "4" - https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" diff --git a/yarn.lock b/yarn.lock index d43245dd02f..2b99fa1349d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1561,12 +1561,12 @@ resolved "https://registry.yarnpkg.com/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz#d2f1e0664ee6036408f9743fee264ea0699b0e48" integrity sha512-bRRFxLfg5dtAyl5XyiVWz/ZBPahpOpPrNYnnHpOpUZvam4tKH35wdhP4Kj6PbM0+KdliOsPzbGWpkxcdpNB/sg== -"@vscode/ripgrep@^1.14.1": - version "1.14.1" - resolved "https://registry.yarnpkg.com/@vscode/ripgrep/-/ripgrep-1.14.1.tgz#66b104a6c7283d17672eb01c02b1c1294d4bb2ae" - integrity sha512-f2N/iPZhxP9bho7iK0DibJDprU+spE8hTIvQg1fi8v82oWIWU9IB4a92444GyxSaFgb+hWpQe46QkFDh5W1VpQ== +"@vscode/ripgrep@^1.14.2": + version "1.14.2" + resolved "https://registry.yarnpkg.com/@vscode/ripgrep/-/ripgrep-1.14.2.tgz#47c0eec2b64f53d8f7e1b5ffd22a62e229191c34" + integrity sha512-KDaehS8Jfdg1dqStaIPDKYh66jzKd5jy5aYEPzIv0JYFLADPsCSQPBUdsJVXnr0t72OlDcj96W05xt/rSnNFFQ== dependencies: - https-proxy-agent "^4.0.0" + https-proxy-agent "^5.0.0" proxy-from-env "^1.1.0" "@vscode/sqlite3@4.0.12": From 44223839d014b62e21942d0bbb98384b50e91cbc Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 9 Mar 2022 16:33:59 -0800 Subject: [PATCH 092/175] Fix #144112 --- .../contrib/cellCommands/cellCommands.ts | 24 ------------------- .../browser/controller/coreActions.ts | 3 +-- .../browser/controller/editActions.ts | 4 ---- 3 files changed, 1 insertion(+), 30 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/cellCommands/cellCommands.ts b/src/vs/workbench/contrib/notebook/browser/contrib/cellCommands/cellCommands.ts index 6eae7cd10c9..2adc303d4e1 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/cellCommands/cellCommands.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/cellCommands/cellCommands.ts @@ -335,12 +335,6 @@ registerAction2(class CollapseCellInputAction extends NotebookMultiCellAction { when: ContextKeyExpr.and(NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_INPUT_COLLAPSED.toNegated(), InputFocusedContext.toNegated()), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyC), weight: KeybindingWeight.WorkbenchContrib - }, - menu: { - id: MenuId.NotebookCellTitle, - when: ContextKeyExpr.and(NOTEBOOK_CELL_INPUT_COLLAPSED.toNegated()), - group: CellOverflowToolbarGroups.Collapse, - order: 0 } }); } @@ -367,12 +361,6 @@ registerAction2(class ExpandCellInputAction extends NotebookMultiCellAction { when: ContextKeyExpr.and(NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_INPUT_COLLAPSED), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyC), weight: KeybindingWeight.WorkbenchContrib - }, - menu: { - id: MenuId.NotebookCellTitle, - when: ContextKeyExpr.and(NOTEBOOK_CELL_INPUT_COLLAPSED), - group: CellOverflowToolbarGroups.Collapse, - order: 1 } }); } @@ -399,12 +387,6 @@ registerAction2(class CollapseCellOutputAction extends NotebookMultiCellAction { when: ContextKeyExpr.and(NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_OUTPUT_COLLAPSED.toNegated(), InputFocusedContext.toNegated(), NOTEBOOK_CELL_HAS_OUTPUTS), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyT), weight: KeybindingWeight.WorkbenchContrib - }, - menu: { - id: MenuId.NotebookCellTitle, - when: ContextKeyExpr.and(NOTEBOOK_CELL_OUTPUT_COLLAPSED.toNegated(), NOTEBOOK_CELL_HAS_OUTPUTS), - group: CellOverflowToolbarGroups.Collapse, - order: 2 } }); } @@ -427,12 +409,6 @@ registerAction2(class ExpandCellOuputAction extends NotebookMultiCellAction { when: ContextKeyExpr.and(NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_OUTPUT_COLLAPSED), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyT), weight: KeybindingWeight.WorkbenchContrib - }, - menu: { - id: MenuId.NotebookCellTitle, - when: ContextKeyExpr.and(NOTEBOOK_CELL_OUTPUT_COLLAPSED), - group: CellOverflowToolbarGroups.Collapse, - order: 3 } }); } diff --git a/src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts index 431ea8a4d66..1c601fbf36f 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts @@ -42,8 +42,7 @@ export const enum CellToolbarOrder { export const enum CellOverflowToolbarGroups { Copy = '1_copy', Insert = '2_insert', - Edit = '3_edit', - Collapse = '4_collapse', + Edit = '3_edit' } export interface INotebookActionContext { diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts index dec1acd7471..602e14a3940 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts @@ -147,10 +147,6 @@ registerAction2(class DeleteCellAction extends NotebookCellAction { { id: DELETE_CELL_COMMAND_ID, title: localize('notebookActions.deleteCell', "Delete Cell"), - menu: { - id: MenuId.NotebookCellTitle, - when: NOTEBOOK_EDITOR_EDITABLE - }, keybinding: { primary: KeyCode.Delete, mac: { From f407da25ec62fc82d8f038eb4ae0df1fe8ff246a Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Wed, 9 Mar 2022 16:41:28 -0800 Subject: [PATCH 093/175] Consider order fields when doing searches in the Settings editor (#144213) --- .../preferences/common/preferences.ts | 2 + .../preferences/common/preferencesModels.ts | 53 ++++++++++++++++--- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts index 637c82f3e47..a60de6ae3c1 100644 --- a/src/vs/workbench/services/preferences/common/preferences.ts +++ b/src/vs/workbench/services/preferences/common/preferences.ts @@ -89,6 +89,8 @@ export interface ISetting { editPresentation?: EditPresentationTypes; defaultValueSource?: string | IExtensionInfo; isLanguageTagSetting?: boolean; + categoryOrder?: number; + categoryLabel?: string; } export interface IExtensionSetting extends ISetting { diff --git a/src/vs/workbench/services/preferences/common/preferencesModels.ts b/src/vs/workbench/services/preferences/common/preferencesModels.ts index 979d4e0e660..df0250c0d61 100644 --- a/src/vs/workbench/services/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/services/preferences/common/preferencesModels.ts @@ -16,7 +16,7 @@ import { ISingleEditOperation } from 'vs/editor/common/core/editOperation'; import { ITextEditorModel } from 'vs/editor/common/services/resolverService'; import * as nls from 'vs/nls'; import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ConfigurationScope, Extensions, IConfigurationNode, IConfigurationPropertySchema, IConfigurationRegistry, IExtensionInfo, IRegisteredConfigurationPropertySchema, OVERRIDE_PROPERTY_REGEX } from 'vs/platform/configuration/common/configurationRegistry'; +import { ConfigurationScope, Extensions, IConfigurationNode, IConfigurationRegistry, IExtensionInfo, IRegisteredConfigurationPropertySchema, OVERRIDE_PROPERTY_REGEX } from 'vs/platform/configuration/common/configurationRegistry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { Registry } from 'vs/platform/registry/common/platform'; import { EditorModel } from 'vs/workbench/common/editor/editorModel'; @@ -57,6 +57,18 @@ export abstract class AbstractSettingsModel extends EditorModel { }); } + private compareTwoNullableNumbers(a: number | undefined, b: number | undefined): number { + const aOrMax = a ?? Number.MAX_SAFE_INTEGER; + const bOrMax = b ?? Number.MAX_SAFE_INTEGER; + if (aOrMax < bOrMax) { + return -1; + } else if (aOrMax > bOrMax) { + return 1; + } else { + return 0; + } + } + filterSettings(filter: string, groupFilter: IGroupFilter, settingMatcher: ISettingMatcher): ISettingMatch[] { const allGroups = this.filterGroups; @@ -80,12 +92,28 @@ export abstract class AbstractSettingsModel extends EditorModel { } filterMatches.sort((a, b) => { - // Sort by match type if the match types are not equal. - // The priority of the match type is given by the SettingMatchType enum. - // If they're equal, fall back to the "stable sort" counter score. if (a.matchType !== b.matchType) { + // Sort by match type if the match types are not the same. + // The priority of the match type is given by the SettingMatchType enum. return b.matchType - a.matchType; } else { + // The match types are the same. + if (a.setting.extensionInfo && b.setting.extensionInfo + && a.setting.extensionInfo.id === b.setting.extensionInfo.id) { + // These settings belong to the same extension. + if (a.setting.categoryLabel !== b.setting.categoryLabel + && (a.setting.categoryOrder !== undefined || b.setting.categoryOrder !== undefined) + && a.setting.categoryOrder !== b.setting.categoryOrder) { + // These two settings don't belong to the same category and have different category orders. + return this.compareTwoNullableNumbers(a.setting.categoryOrder, b.setting.categoryOrder); + } else if (a.setting.categoryLabel === b.setting.categoryLabel + && (a.setting.order !== undefined || b.setting.order !== undefined) + && a.setting.order !== b.setting.order) { + // These two settings belong to the same category, but have different orders. + return this.compareTwoNullableNumbers(a.setting.order, b.setting.order); + } + } + // In the worst case, go back to lexicographical order. return b.score - a.score; } }); @@ -602,7 +630,7 @@ export class DefaultSettings extends Disposable { result.push(settingsGroup); } const configurationSettings: ISetting[] = []; - for (const setting of [...settingsGroup.sections[settingsGroup.sections.length - 1].settings, ...this.parseSettings(config.properties, config.extensionInfo)]) { + for (const setting of [...settingsGroup.sections[settingsGroup.sections.length - 1].settings, ...this.parseSettings(config)]) { if (!seenSettings[setting.key]) { configurationSettings.push(setting); seenSettings[setting.key] = true; @@ -629,8 +657,17 @@ export class DefaultSettings extends Disposable { return result; } - private parseSettings(settingsObject: { [path: string]: IConfigurationPropertySchema }, extensionInfo?: IExtensionInfo): ISetting[] { + private parseSettings(config: IConfigurationNode): ISetting[] { const result: ISetting[] = []; + + const settingsObject = config.properties; + const extensionInfo = config.extensionInfo; + + // Try using the title if the category id wasn't given + // (in which case the category id is the same as the extension id) + const categoryLabel = config.extensionInfo?.id === config.id ? config.title : config.id; + const categoryOrder = config.order; + for (const key in settingsObject) { const prop = settingsObject[key]; if (this.matchesScope(prop)) { @@ -713,7 +750,9 @@ export class DefaultSettings extends Disposable { editPresentation: prop.editPresentation, order: prop.order, defaultValueSource, - isLanguageTagSetting + isLanguageTagSetting, + categoryLabel, + categoryOrder }); } } From faf8c71e8ddd3f29cc18740ba80e93e90f768128 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 10 Mar 2022 09:49:05 +0100 Subject: [PATCH 094/175] add tests --- .../common/extensionManagementUtil.ts | 2 +- .../test/common/extensionManagement.test.ts | 16 ++- .../browser/extensionsWorkbenchService.ts | 2 +- .../test/electron-browser/extension.test.ts | 104 ++++++++++++++++++ 4 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts diff --git a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts index 66c2b407a10..aec656f287b 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts @@ -29,7 +29,7 @@ export class ExtensionKey { static parse(key: string): ExtensionKey | null { const matches = ExtensionKeyRegex.exec(key); - return matches && matches[1] && matches[2] ? new ExtensionKey({ id: matches[1] }, matches[2], matches[3] as TargetPlatform || undefined) : null; + return matches && matches[1] && matches[2] ? new ExtensionKey({ id: matches[1] }, matches[2], matches[4] as TargetPlatform || undefined) : null; } readonly id: string; diff --git a/src/vs/platform/extensionManagement/test/common/extensionManagement.test.ts b/src/vs/platform/extensionManagement/test/common/extensionManagement.test.ts index 82ae6dd9031..adb910b63d3 100644 --- a/src/vs/platform/extensionManagement/test/common/extensionManagement.test.ts +++ b/src/vs/platform/extensionManagement/test/common/extensionManagement.test.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EXTENSION_IDENTIFIER_PATTERN } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { EXTENSION_IDENTIFIER_PATTERN, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionKey } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; suite('Extension Identifier Pattern', () => { @@ -26,4 +27,17 @@ suite('Extension Identifier Pattern', () => { assert.strictEqual(false, regEx.test('publ_isher.name')); assert.strictEqual(false, regEx.test('publisher._name')); }); + + test('extension key', () => { + assert.strictEqual(new ExtensionKey({ id: 'pub.extension-name' }, '1.0.1').toString(), 'pub.extension-name-1.0.1'); + assert.strictEqual(new ExtensionKey({ id: 'pub.extension-name' }, '1.0.1', TargetPlatform.UNDEFINED).toString(), 'pub.extension-name-1.0.1'); + assert.strictEqual(new ExtensionKey({ id: 'pub.extension-name' }, '1.0.1', TargetPlatform.WIN32_IA32).toString(), `pub.extension-name-1.0.1-${TargetPlatform.WIN32_IA32}`); + }); + + test('extension key parsing', () => { + assert.strictEqual(ExtensionKey.parse('pub.extension-name'), null); + assert.strictEqual(ExtensionKey.parse('pub.extension-name@1.2.3'), null); + assert.strictEqual(ExtensionKey.parse('pub.extension-name-1.0.1')?.toString(), 'pub.extension-name-1.0.1'); + assert.strictEqual(ExtensionKey.parse('pub.extension-name-1.0.1-win32-ia32')?.toString(), 'pub.extension-name-1.0.1-win32-ia32'); + }); }); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 1f50eb92db9..ec4a1287475 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -50,7 +50,7 @@ interface IExtensionStateProvider { (extension: Extension): T; } -class Extension implements IExtension { +export class Extension implements IExtension { public enablementState: EnablementState = EnablementState.EnabledGlobally; diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts new file mode 100644 index 00000000000..28ed773f20f --- /dev/null +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts @@ -0,0 +1,104 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { ExtensionState } from 'vs/workbench/contrib/extensions/common/extensions'; +import { Extension } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService'; +import { ITestInstantiationService, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices'; +import { IGalleryExtension, IGalleryExtensionProperties, ILocalExtension, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; +import { URI } from 'vs/base/common/uri'; +import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { generateUuid } from 'vs/base/common/uuid'; + +suite('Extension Test', () => { + + let instantiationService: ITestInstantiationService; + + setup(() => { + instantiationService = workbenchInstantiationService(); + }); + + test('extension is not outdated when there is no local and gallery', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, undefined, undefined); + assert.strictEqual(extension.outdated, false); + }); + + test('extension is not outdated when there is local and no gallery', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension(), undefined); + assert.strictEqual(extension.outdated, false); + }); + + test('extension is not outdated when there is no local and has gallery', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, undefined, aGalleryExtension()); + assert.strictEqual(extension.outdated, false); + }); + + test('extension is not outdated when local and gallery are on same version', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension(), aGalleryExtension()); + assert.strictEqual(extension.outdated, false); + }); + + test('extension is outdated when local is older than gallery', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', { version: '1.0.0' }), aGalleryExtension('somext', { version: '1.0.1' })); + assert.strictEqual(extension.outdated, true); + }); + + test('extension is not outdated when local is built in and older than gallery', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', { version: '1.0.0' }, { type: ExtensionType.System }), aGalleryExtension('somext', { version: '1.0.1' })); + assert.strictEqual(extension.outdated, false); + }); + + test('extension is outdated when local and gallery are on same version but on different target platforms', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', {}, { targetPlatform: TargetPlatform.WIN32_IA32 }), aGalleryExtension('somext', {}, { targetPlatform: TargetPlatform.WIN32_X64 })); + assert.strictEqual(extension.outdated, true); + }); + + test('extension is not outdated when local is not pre-release but gallery is pre-release', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', { version: '1.0.0' }), aGalleryExtension('somext', { version: '1.0.1' }, { isPreReleaseVersion: true })); + assert.strictEqual(extension.outdated, false); + }); + + test('extension is outdated when local and gallery are pre-releases', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', { version: '1.0.0' }, { preRelease: true, isPreReleaseVersion: true }), aGalleryExtension('somext', { version: '1.0.1' }, { isPreReleaseVersion: true })); + assert.strictEqual(extension.outdated, true); + }); + + test('extension is outdated when local was opted to pre-release but current version is not pre-release', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', { version: '1.0.0' }, { preRelease: true, isPreReleaseVersion: false }), aGalleryExtension('somext', { version: '1.0.1' }, { isPreReleaseVersion: true })); + assert.strictEqual(extension.outdated, true); + }); + + test('extension is outdated when local is pre-release but gallery is not', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', { version: '1.0.0' }, { preRelease: true, isPreReleaseVersion: true }), aGalleryExtension('somext', { version: '1.0.1' })); + assert.strictEqual(extension.outdated, true); + }); + + test('extension is outdated when local was opted pre-release but current version is not and gallery is not', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', { version: '1.0.0' }, { preRelease: true, isPreReleaseVersion: false }), aGalleryExtension('somext', { version: '1.0.1' })); + assert.strictEqual(extension.outdated, true); + }); + + function aLocalExtension(name: string = 'someext', manifest: Partial = {}, properties: Partial = {}): ILocalExtension { + manifest = { name, publisher: 'pub', version: '1.0.0', ...manifest }; + properties = { + type: ExtensionType.User, + location: URI.file(`pub.${name}`), + identifier: { id: getGalleryExtensionId(manifest.publisher!, manifest.name!) }, + targetPlatform: TargetPlatform.UNDEFINED, + ...properties + }; + return Object.create({ manifest, ...properties }); + } + + function aGalleryExtension(name: string = 'somext', properties: Partial = {}, galleryExtensionProperties: Partial = {}): IGalleryExtension { + const targetPlatform = galleryExtensionProperties.targetPlatform ?? TargetPlatform.UNDEFINED; + const galleryExtension = Object.create({ name, publisher: 'pub', version: '1.0.0', allTargetPlatforms: [targetPlatform], properties: {}, assets: {}, ...properties }); + galleryExtension.properties = { ...galleryExtension.properties, dependencies: [], targetPlatform, ...galleryExtensionProperties }; + galleryExtension.identifier = { id: getGalleryExtensionId(galleryExtension.publisher, galleryExtension.name), uuid: generateUuid() }; + return galleryExtension; + } + +}); From 68fe6ea43359c7b8f40c9d232df39df3503dc74f Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 10 Mar 2022 09:55:53 +0100 Subject: [PATCH 095/175] Enables bracket pair colorization by default. Fixes #144820. --- src/vs/editor/common/core/textModelDefaults.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/core/textModelDefaults.ts b/src/vs/editor/common/core/textModelDefaults.ts index 17965019ec7..6f549c74411 100644 --- a/src/vs/editor/common/core/textModelDefaults.ts +++ b/src/vs/editor/common/core/textModelDefaults.ts @@ -11,7 +11,7 @@ export const EDITOR_MODEL_DEFAULTS = { trimAutoWhitespace: true, largeFileOptimizations: true, bracketPairColorizationOptions: { - enabled: false, + enabled: true, useIndependentColorPoolPerBracketType: false, }, }; From 4ce5585b4ce4ef3ffa59d617336eaec2fc31d160 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 10 Mar 2022 10:35:56 +0100 Subject: [PATCH 096/175] Use ext host comment value in commands (#144743) Part of #130107 --- src/vs/workbench/api/common/extHostComments.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/api/common/extHostComments.ts b/src/vs/workbench/api/common/extHostComments.ts index 1f1049f8b4f..efbb27c0db9 100644 --- a/src/vs/workbench/api/common/extHostComments.ts +++ b/src/vs/workbench/api/common/extHostComments.ts @@ -50,7 +50,7 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo return arg; } - return commentController; + return commentController.value; } else if (arg && arg.$mid === MarshalledId.CommentThread) { const commentController = this._commentControllers.get(arg.commentControlHandle); @@ -64,7 +64,7 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo return arg; } - return commentThread; + return commentThread.value; } else if (arg && arg.$mid === MarshalledId.CommentThreadReply) { const commentController = this._commentControllers.get(arg.thread.commentControlHandle); @@ -79,7 +79,7 @@ export function createExtHostComments(mainContext: IMainContext, commands: ExtHo } return { - thread: commentThread, + thread: commentThread.value, text: arg.text }; } else if (arg && arg.$mid === MarshalledId.CommentNode) { From 06b2dd2130a18f7d8de3a46517fc0966b9320a48 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 10 Mar 2022 10:36:37 +0100 Subject: [PATCH 097/175] fix tests --- .../extensions/test/electron-browser/extension.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts index 28ed773f20f..3026178faca 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts @@ -6,19 +6,19 @@ import * as assert from 'assert'; import { ExtensionState } from 'vs/workbench/contrib/extensions/common/extensions'; import { Extension } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService'; -import { ITestInstantiationService, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices'; import { IGalleryExtension, IGalleryExtensionProperties, ILocalExtension, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; import { URI } from 'vs/base/common/uri'; import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { generateUuid } from 'vs/base/common/uuid'; +import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; suite('Extension Test', () => { - let instantiationService: ITestInstantiationService; + let instantiationService: TestInstantiationService; setup(() => { - instantiationService = workbenchInstantiationService(); + instantiationService = new TestInstantiationService(); }); test('extension is not outdated when there is no local and gallery', () => { From 3626e6ab0c6ff6ec862822551a2c492615cc4fc8 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 10 Mar 2022 11:23:01 +0100 Subject: [PATCH 098/175] Adds inlineCompletionsNew and inlineCompletionsAdditions proposed APIs to avoid breaking changes when finalizing inline completions API. --- .../workbench/api/common/extHost.api.impl.ts | 10 ++ .../api/common/extHostLanguageFeatures.ts | 106 ++++++++++++++- src/vs/workbench/api/common/extHostTypes.ts | 27 ++++ .../common/extensionsApiProposals.ts | 2 + ...e.proposed.inlineCompletionsAdditions.d.ts | 22 +++ .../vscode.proposed.inlineCompletionsNew.d.ts | 125 ++++++++++++++++++ 6 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts create mode 100644 src/vscode-dts/vscode.proposed.inlineCompletionsNew.d.ts diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 69c421cc22d..b73eee6eeb4 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -495,6 +495,13 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I checkProposedApiEnabled(extension, 'inlineCompletions'); return extHostLanguageFeatures.registerInlineCompletionsProvider(extension, checkSelector(selector), provider); }, + registerInlineCompletionItemProviderNew(selector: vscode.DocumentSelector, provider: vscode.InlineCompletionItemProviderNew): vscode.Disposable { + checkProposedApiEnabled(extension, 'inlineCompletionsNew'); + if (provider.handleDidShowCompletionItem && !isProposedApiEnabled(extension, 'inlineCompletionsAdditions')) { + throw new Error(`When the method "handleDidShowCompletionItem" is implemented on a provider, the usage of the proposed api 'inlineCompletionsAdditions' must be declared!`); + } + return extHostLanguageFeatures.registerInlineCompletionsProviderNew(extension, checkSelector(selector), provider); + }, registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable { return extHostLanguageFeatures.registerDocumentLinkProvider(extension, checkSelector(selector), provider); }, @@ -1205,6 +1212,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I InlineValueVariableLookup: extHostTypes.InlineValueVariableLookup, InlineValueEvaluatableExpression: extHostTypes.InlineValueEvaluatableExpression, InlineCompletionTriggerKind: extHostTypes.InlineCompletionTriggerKind, + InlineCompletionTriggerKindNew: extHostTypes.InlineCompletionTriggerKindNew, EventEmitter: Emitter, ExtensionKind: extHostTypes.ExtensionKind, ExtensionMode: extHostTypes.ExtensionMode, @@ -1218,7 +1226,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I FoldingRangeKind: extHostTypes.FoldingRangeKind, FunctionBreakpoint: extHostTypes.FunctionBreakpoint, InlineCompletionItem: extHostTypes.InlineSuggestion, + InlineCompletionItemNew: extHostTypes.InlineSuggestionNew, InlineCompletionList: extHostTypes.InlineSuggestions, + InlineCompletionListNew: extHostTypes.InlineSuggestionsNew, Hover: extHostTypes.Hover, IndentAction: languageConfiguration.IndentAction, Location: extHostTypes.Location, diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 59e2eba0ee7..be656cf7ee6 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -7,7 +7,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { mixin } from 'vs/base/common/objects'; import type * as vscode from 'vscode'; import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters'; -import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit, Location } from 'vs/workbench/api/common/extHostTypes'; +import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit, Location, InlineCompletionTriggerKindNew } from 'vs/workbench/api/common/extHostTypes'; import { ISingleEditOperation } from 'vs/editor/common/core/editOperation'; import * as languages from 'vs/editor/common/languages'; import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; @@ -34,6 +34,7 @@ import { StopWatch } from 'vs/base/common/stopwatch'; import { isCancellationError } from 'vs/base/common/errors'; import { Emitter } from 'vs/base/common/event'; import { raceCancellationError } from 'vs/base/common/async'; +import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; // --- adapter @@ -1112,6 +1113,101 @@ class InlineCompletionAdapter { } } +class InlineCompletionAdapterNew { + private readonly _cache = new Cache('InlineCompletionItemNew'); + private readonly _disposables = new Map(); + + private readonly isAdditionProposedApiEnabled = isProposedApiEnabled(this.extension, 'inlineCompletionsAdditions'); + + constructor( + private readonly extension: IExtensionDescription, + private readonly _documents: ExtHostDocuments, + private readonly _provider: vscode.InlineCompletionItemProviderNew, + private readonly _commands: CommandsConverter, + ) { } + + private readonly languageTriggerKindToVSCodeTriggerKind: Record = { + [languages.InlineCompletionTriggerKind.Automatic]: InlineCompletionTriggerKindNew.Automatic, + [languages.InlineCompletionTriggerKind.Explicit]: InlineCompletionTriggerKindNew.Invoke, + }; + + public async provideInlineCompletions(resource: URI, position: IPosition, context: languages.InlineCompletionContext, token: CancellationToken): Promise { + const doc = this._documents.getDocument(resource); + const pos = typeConvert.Position.to(position); + + const result = await this._provider.provideInlineCompletionItems(doc, pos, { + selectedCompletionInfo: + context.selectedSuggestionInfo + ? { + range: typeConvert.Range.to(context.selectedSuggestionInfo.range), + text: context.selectedSuggestionInfo.text + } + : undefined, + triggerKind: this.languageTriggerKindToVSCodeTriggerKind[context.triggerKind] + }, token); + + if (!result) { + // undefined and null are valid results + return undefined; + } + + if (token.isCancellationRequested) { + // cancelled -> return without further ado, esp no caching + // of results as they will leak + return undefined; + } + + const normalizedResult = isArray(result) ? result : result.items; + + const pid = this._cache.add(normalizedResult); + let disposableStore: DisposableStore | undefined = undefined; + + return { + pid, + items: normalizedResult.map((item, idx) => { + let command: languages.Command | undefined = undefined; + if (item.command) { + if (!disposableStore) { + disposableStore = new DisposableStore(); + this._disposables.set(pid, disposableStore); + } + command = this._commands.toInternal(item.command, disposableStore); + } + + const insertText = item.insertText; + if (insertText === undefined) { + throw new Error('text or insertText must be defined'); + } + return ({ + text: typeof insertText === 'string' ? insertText : { snippet: insertText.value }, + range: item.range ? typeConvert.Range.from(item.range) : undefined, + command, + idx: idx, + completeBracketPairs: this.isAdditionProposedApiEnabled ? item.completeBracketPairs : false + }); + }), + }; + } + + public disposeCompletions(pid: number) { + this._cache.delete(pid); + const d = this._disposables.get(pid); + if (d) { + d.clear(); + } + this._disposables.delete(pid); + } + + public handleDidShowCompletionItem(pid: number, idx: number): void { + const completionItem = this._cache.get(pid, idx); + if (completionItem) { + if (this._provider.handleDidShowCompletionItem && isProposedApiEnabled(this.extension, 'inlineCompletionsAdditions')) { + this._provider.handleDidShowCompletionItem(completionItem); + } + } + } +} + export class InlineCompletionController implements vscode.InlineCompletionController { private static readonly map = new WeakMap, InlineCompletionController>(); @@ -1616,7 +1712,7 @@ type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | Hov | SelectionRangeAdapter | CallHierarchyAdapter | TypeHierarchyAdapter | DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter | EvaluatableExpressionAdapter | InlineValuesAdapter - | LinkedEditingRangeAdapter | InlayHintsAdapter | InlineCompletionAdapter; + | LinkedEditingRangeAdapter | InlayHintsAdapter | InlineCompletionAdapter | InlineCompletionAdapterNew; class AdapterData { constructor( @@ -2050,6 +2146,12 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF return this._createDisposable(handle); } + registerInlineCompletionsProviderNew(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlineCompletionItemProviderNew): vscode.Disposable { + const handle = this._addNewAdapter(new InlineCompletionAdapterNew(extension, this._documents, provider, this._commands.converter), extension); + this._proxy.$registerInlineCompletionsSupport(handle, this._transformDocumentSelector(selector)); + return this._createDisposable(handle); + } + $provideInlineCompletions(handle: number, resource: UriComponents, position: IPosition, context: languages.InlineCompletionContext, token: CancellationToken): Promise { return this._withAdapter(handle, InlineCompletionAdapter, adapter => adapter.provideInlineCompletions(URI.revive(resource), position, context, token), undefined, token); } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index f5640ee5b01..7e0a90244ef 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1612,6 +1612,28 @@ export class InlineSuggestions implements vscode.InlineCompletionList { } } +@es5ClassCompat +export class InlineSuggestionNew implements vscode.InlineCompletionItemNew { + insertText: string; + range?: Range; + command?: vscode.Command; + + constructor(insertText: string, range?: Range, command?: vscode.Command) { + this.insertText = insertText; + this.range = range; + this.command = command; + } +} + +@es5ClassCompat +export class InlineSuggestionsNew implements vscode.InlineCompletionListNew { + items: vscode.InlineCompletionItemNew[]; + + constructor(items: vscode.InlineCompletionItemNew[]) { + this.items = items; + } +} + export enum ViewColumn { Active = -1, Beside = -2, @@ -2587,6 +2609,11 @@ export enum InlineCompletionTriggerKind { Explicit = 1, } +export enum InlineCompletionTriggerKindNew { + Invoke = 0, + Automatic = 1, +} + @es5ClassCompat export class InlineValueText implements vscode.InlineValueText { readonly range: Range; diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index ccf5e7d290a..45bfa8fd464 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -25,6 +25,8 @@ export const allApiProposals = Object.freeze({ fsChunks: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.fsChunks.d.ts', idToken: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.idToken.d.ts', inlineCompletions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.inlineCompletions.d.ts', + inlineCompletionsAdditions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts', + inlineCompletionsNew: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.inlineCompletionsNew.d.ts', ipc: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.ipc.d.ts', notebookCellExecutionState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookCellExecutionState.d.ts', notebookConcatTextDocument: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookConcatTextDocument.d.ts', diff --git a/src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts b/src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts new file mode 100644 index 00000000000..c79cf048df9 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + // https://github.com/microsoft/vscode/issues/124024 @hediet @alexdima + + export interface InlineCompletionItemNew { + /** + * If set to `true`, unopened closing brackets are removed and unclosed opening brackets are closed. + * Defaults to `false`. + */ + completeBracketPairs?: boolean; + } + + export interface InlineCompletionItemProviderNew { + // eslint-disable-next-line vscode-dts-provider-naming + handleDidShowCompletionItem?(completionItem: InlineCompletionItemNew): void; + } +} diff --git a/src/vscode-dts/vscode.proposed.inlineCompletionsNew.d.ts b/src/vscode-dts/vscode.proposed.inlineCompletionsNew.d.ts new file mode 100644 index 00000000000..9556b4455d1 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.inlineCompletionsNew.d.ts @@ -0,0 +1,125 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + // https://github.com/microsoft/vscode/issues/124024 @hediet @alexdima + // Temporary API to allow for safe migration. + + export namespace languages { + /** + * Registers an inline completion provider. + * + * @return A {@link Disposable} that unregisters this provider when being disposed. + */ + // TODO@API what are the rules when multiple providers apply + export function registerInlineCompletionItemProviderNew(selector: DocumentSelector, provider: InlineCompletionItemProviderNew): Disposable; + } + + export interface InlineCompletionItemProviderNew { + /** + * Provides inline completion items for the given position and document. + * If inline completions are enabled, this method will be called whenever the user stopped typing. + * It will also be called when the user explicitly triggers inline completions or asks for the next or previous inline completion. + * Use `context.triggerKind` to distinguish between these scenarios. + */ + provideInlineCompletionItems(document: TextDocument, position: Position, context: InlineCompletionContextNew, token: CancellationToken): ProviderResult; + } + + export interface InlineCompletionContextNew { + /** + * How the completion was triggered. + */ + readonly triggerKind: InlineCompletionTriggerKindNew; + + /** + * Provides information about the currently selected item in the autocomplete widget if it is visible. + * + * If set, provided inline completions must extend the text of the selected item + * and use the same range, otherwise they are not shown as preview. + * As an example, if the document text is `console.` and the selected item is `.log` replacing the `.` in the document, + * the inline completion must also replace `.` and start with `.log`, for example `.log()`. + * + * Inline completion providers are requested again whenever the selected item changes. + * + * The user must configure `"editor.suggest.preview": true` for this feature. + */ + readonly selectedCompletionInfo: SelectedCompletionInfoNew | undefined; + } + + // TODO@API find a better name, xyzFilter, xyzConstraint + export interface SelectedCompletionInfoNew { + range: Range; + text: string; + } + + /** + * How an {@link InlineCompletionItemProvider inline completion provider} was triggered. + */ + export enum InlineCompletionTriggerKindNew { + /** + * Completion was triggered explicitly by a user gesture. + * Return multiple completion items to enable cycling through them. + */ + Invoke = 0, + + /** + * Completion was triggered automatically while editing. + * It is sufficient to return a single completion item in this case. + */ + Automatic = 1, + } + + /** + * @deprecated Return an array of Inline Completion items directly. Will be removed eventually. + */ + // TODO@API We could keep this and allow for `vscode.Command` instances that explain + // the result. That would replace the existing proposed menu-identifier and be more LSP friendly + // TODO@API maybe use MarkdownString + export class InlineCompletionListNew { + items: InlineCompletionItemNew[]; + + // command: Command; "Show More..." + + // description: MarkdownString + + /** + * @deprecated Return an array of Inline Completion items directly. Will be removed eventually. + */ + constructor(items: InlineCompletionItemNew[]); + } + + export class InlineCompletionItemNew { + /** + * The text to replace the range with. Must be set. + * Is used both for the preview and the accept operation. + * + * The text the range refers to must be a subword of this value (`AB` and `BEF` are subwords of `ABCDEF`, but `Ab` is not). + * Additionally, if possible, it should be a prefix of this value for a better user-experience. + * + * However, any indentation of the text to replace does not matter for the subword constraint. + * Thus, ` B` can be replaced with ` ABC`, effectively removing a whitespace and inserting `A` and `C`. + */ + insertText: string | SnippetString; + + /** + * The range to replace. + * Must begin and end on the same line. + * + * Prefer replacements over insertions to avoid cache invalidation: + * Instead of reporting a completion that inserts an extension at the end of a word, + * the whole word (or even the whole line) should be replaced with the extended word (or extended line) to improve the UX. + * That way, when the user presses backspace, the cache can be reused and there is no flickering. + */ + range?: Range; + + /** + * An optional {@link Command} that is executed *after* inserting this completion. + */ + command?: Command; + + constructor(insertText: string, range?: Range, command?: Command); + } +} From 5cbc67a72eca5f6ed33ae6dc98e16b0fa18e0398 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 10 Mar 2022 14:17:24 +0100 Subject: [PATCH 099/175] Show hover feedback on commentable lines (#144834) Fixes #144832 --- .../browser/commentsEditorContribution.ts | 89 +++++++++++++++++-- .../contrib/comments/browser/media/review.css | 4 +- 2 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index f967fcde19f..aadf040bcb4 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -9,7 +9,7 @@ import { coalesce, findFirstInSorted } from 'vs/base/common/arrays'; import { CancelablePromise, createCancelablePromise, Delayer } from 'vs/base/common/async'; import { onUnexpectedError } from 'vs/base/common/errors'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { DisposableStore } from 'vs/base/common/lifecycle'; +import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import 'vs/css!./media/review'; import { IActiveCodeEditor, ICodeEditor, IEditorMouseEvent, isCodeEditor, isDiffEditor, IViewZone } from 'vs/editor/browser/editorBrowser'; import { EditorAction, registerEditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; @@ -40,6 +40,7 @@ import { IViewsService } from 'vs/workbench/common/views'; import { COMMENTS_VIEW_ID } from 'vs/workbench/contrib/comments/browser/commentsTreeViewer'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { COMMENTS_SECTION, ICommentsConfiguration } from 'vs/workbench/contrib/comments/common/commentsConfiguration'; +import { Emitter } from 'vs/base/common/event'; export const ID = 'editor.contrib.review'; @@ -67,7 +68,7 @@ class CommentingRangeDecoration { return this._decorationId; } - constructor(private _editor: ICodeEditor, private _ownerId: string, private _extensionId: string | undefined, private _label: string | undefined, private _range: IRange, commentingOptions: ModelDecorationOptions, private commentingRangesInfo: languages.CommentingRanges) { + constructor(private _editor: ICodeEditor, private _ownerId: string, private _extensionId: string | undefined, private _label: string | undefined, private _range: IRange, commentingOptions: ModelDecorationOptions, private commentingRangesInfo: languages.CommentingRanges, public readonly isHover: boolean = false) { const startLineNumber = _range.startLineNumber; const endLineNumber = _range.endLineNumber; let commentingRangeDecorations = [{ @@ -100,8 +101,14 @@ class CommentingRangeDecoration { } class CommentingRangeDecorator { - private decorationOptions: ModelDecorationOptions; + private decorationOptions!: ModelDecorationOptions; + private hoverDecorationOptions!: ModelDecorationOptions; private commentingRangeDecorations: CommentingRangeDecoration[] = []; + private _editor: ICodeEditor | undefined; + private _infos: ICommentInfo[] | undefined; + private _lastHover: number = -1; + private _onDidChangeDecorationsCount: Emitter = new Emitter(); + public readonly onDidChangeDecorationsCount = this._onDidChangeDecorationsCount.event; constructor() { const decorationOptions: IModelDecorationOptions = { @@ -111,9 +118,30 @@ class CommentingRangeDecorator { }; this.decorationOptions = ModelDecorationOptions.createDynamic(decorationOptions); + + const hoverDecorationOptions: IModelDecorationOptions = { + description: 'commenting-range-decorator', + isWholeLine: true, + linesDecorationsClassName: `comment-range-glyph comment-diff-added line-hover` + }; + + this.hoverDecorationOptions = ModelDecorationOptions.createDynamic(hoverDecorationOptions); + } + + public updateHover(hoverLine?: number) { + if (this._editor && this._infos && (hoverLine !== this._lastHover)) { + this._doUpdate(this._editor, this._infos, hoverLine); + } + this._lastHover = hoverLine ?? -1; } public update(editor: ICodeEditor, commentInfos: ICommentInfo[]) { + this._editor = editor; + this._infos = commentInfos; + this._doUpdate(editor, commentInfos); + } + + private _doUpdate(editor: ICodeEditor, commentInfos: ICommentInfo[], hoverLine: number = -1) { let model = editor.getModel(); if (!model) { return; @@ -122,22 +150,47 @@ class CommentingRangeDecorator { let commentingRangeDecorations: CommentingRangeDecoration[] = []; for (const info of commentInfos) { info.commentingRanges.ranges.forEach(range => { - commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, range, this.decorationOptions, info.commentingRanges)); + if ((range.startLineNumber <= hoverLine) && (range.endLineNumber >= hoverLine)) { + const beforeRange = new Range(range.startLineNumber, 1, hoverLine, 1); + const hoverRange = new Range(hoverLine, 1, hoverLine, 1); + const afterRange = new Range(hoverLine, 1, range.endLineNumber, 1); + commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, beforeRange, this.decorationOptions, info.commentingRanges, true)); + commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, hoverRange, this.hoverDecorationOptions, info.commentingRanges, true)); + commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, afterRange, this.decorationOptions, info.commentingRanges, true)); + } else { + commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, info.extensionId, info.label, range, this.decorationOptions, info.commentingRanges)); + } }); } let oldDecorations = this.commentingRangeDecorations.map(decoration => decoration.id); editor.deltaDecorations(oldDecorations, []); + const rangesDifference = this.commentingRangeDecorations.length - commentingRangeDecorations.length; this.commentingRangeDecorations = commentingRangeDecorations; + if (rangesDifference) { + this._onDidChangeDecorationsCount.fire(this.commentingRangeDecorations.length); + } } public getMatchedCommentAction(line: number) { + // keys is ownerId + const foundHoverActions = new Map(); let result = []; for (const decoration of this.commentingRangeDecorations) { const range = decoration.getActiveRange(); if (range && range.startLineNumber <= line && line <= range.endLineNumber) { - result.push(decoration.getCommentAction()); + // We can have 3 commenting ranges that match from the same owner because of how + // the line hover decoration is done. We only want to use the action from 1 of them. + const action = decoration.getCommentAction(); + if (decoration.isHover) { + if (foundHoverActions.get(action.ownerId) === action.commentingRangesInfo) { + continue; + } else { + foundHoverActions.set(action.ownerId, action.commentingRangesInfo); + } + } + result.push(action); } } @@ -164,6 +217,7 @@ export class CommentController implements IEditorContribution { private _computeCommentingRangePromise!: CancelablePromise | null; private _computeCommentingRangeScheduler!: Delayer> | null; private _pendingCommentCache: { [key: string]: { [key: string]: string } }; + private _editorMouseDisposable: IDisposable | undefined; constructor( editor: ICodeEditor, @@ -187,6 +241,13 @@ export class CommentController implements IEditorContribution { this.editor = editor; this._commentingRangeDecorator = new CommentingRangeDecorator(); + this.globalToDispose.add(this._commentingRangeDecorator.onDidChangeDecorationsCount(count => { + if (count === 0) { + this.clearMouseMoveListener(); + } else if (!this._editorMouseDisposable) { + this.registerMouseMoveListener(); + } + })); this.globalToDispose.add(this.commentService.onDidDeleteDataProvider(ownerId => { delete this._pendingCommentCache[ownerId]; @@ -207,6 +268,19 @@ export class CommentController implements IEditorContribution { this.beginCompute(); } + private registerMouseMoveListener() { + this._editorMouseDisposable = this.editor.onMouseMove(e => this.onEditorMouseMove(e)); + } + + private clearMouseMoveListener() { + this._editorMouseDisposable?.dispose(); + this._editorMouseDisposable = undefined; + } + + private onEditorMouseMove(e: IEditorMouseEvent): void { + this._commentingRangeDecorator.updateHover(e.target.position?.lineNumber); + } + private beginCompute(): Promise { this._computePromise = createCancelablePromise(token => { const editorURI = this.editor && this.editor.hasModel() && this.editor.getModel().uri; @@ -323,6 +397,7 @@ export class CommentController implements IEditorContribution { public dispose(): void { this.globalToDispose.dispose(); this.localToDispose.dispose(); + this._editorMouseDisposable?.dispose(); this._commentWidgets.forEach(widget => widget.dispose()); @@ -336,6 +411,10 @@ export class CommentController implements IEditorContribution { this.localToDispose.add(this.editor.onMouseDown(e => this.onEditorMouseDown(e))); this.localToDispose.add(this.editor.onMouseUp(e => this.onEditorMouseUp(e))); + if (this._editorMouseDisposable) { + this.clearMouseMoveListener(); + this.registerMouseMoveListener(); + } this._computeCommentingRangeScheduler = new Delayer(200); this.localToDispose.add({ diff --git a/src/vs/workbench/contrib/comments/browser/media/review.css b/src/vs/workbench/contrib/comments/browser/media/review.css index d093db1a8d6..052312767e5 100644 --- a/src/vs/workbench/contrib/comments/browser/media/review.css +++ b/src/vs/workbench/contrib/comments/browser/media/review.css @@ -388,6 +388,7 @@ div.preview.inline .monaco-editor .comment-range-glyph { } .monaco-editor .margin-view-overlays > div:hover > .comment-range-glyph.comment-diff-added:before, +.monaco-editor .margin-view-overlays .comment-range-glyph.comment-diff-added.line-hover:before, .monaco-editor .comment-range-glyph.comment-thread:before { position: absolute; height: 100%; @@ -402,7 +403,8 @@ div.preview.inline .monaco-editor .comment-range-glyph { justify-content: center; } -.monaco-editor .margin-view-overlays > div:hover > .comment-range-glyph.comment-diff-added:before { +.monaco-editor .margin-view-overlays > div:hover > .comment-range-glyph.comment-diff-added:before, +.monaco-editor .margin-view-overlays .comment-range-glyph.comment-diff-added.line-hover:before { content: "+"; } From 04229c64e0c82a2bbd46807dd94633ad495cde2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 10 Mar 2022 09:47:39 +0100 Subject: [PATCH 100/175] add PRs to my work notebook --- .vscode/notebooks/my-work.github-issues | 27 ++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.vscode/notebooks/my-work.github-issues b/.vscode/notebooks/my-work.github-issues index b298da45049..53dad858d0d 100644 --- a/.vscode/notebooks/my-work.github-issues +++ b/.vscode/notebooks/my-work.github-issues @@ -7,7 +7,7 @@ { "kind": 2, "language": "github-issues", - "value": "// list of repos we work in\n$repos=repo:microsoft/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-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\n\n// current milestone name\n$milestone=milestone:\"March 2022\"" + "value": "// list of repos we work in\r\n$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\r\n\r\n// current milestone name\r\n$milestone=milestone:\"March 2022\"" }, { "kind": 1, @@ -113,5 +113,30 @@ "kind": 2, "language": "github-issues", "value": "$repos assignee:@me is:open label:\"needs more info\"" + }, + { + "kind": 1, + "language": "markdown", + "value": "### Pull Requests" + }, + { + "kind": 1, + "language": "markdown", + "value": "✅ Approved" + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repos author:@me is:open is:pr review:approved" + }, + { + "kind": 1, + "language": "markdown", + "value": "⌛ Pending Approval" + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repos author:@me is:open is:pr review:required" } ] \ No newline at end of file From ced1b62449eba6d11218ebb5e1557f6874de6d6d Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 10 Mar 2022 14:53:49 +0100 Subject: [PATCH 101/175] Check task uri when quick resolving dependencies Part of #144761 --- .../contrib/tasks/browser/abstractTaskService.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index fe8032b4490..62b66ab4749 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -1585,8 +1585,13 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer let resolverData: Map | undefined; - async function quickResolve(that: AbstractTaskService, identifier: string | TaskIdentifier) { + async function quickResolve(that: AbstractTaskService, uri: URI | string, identifier: string | TaskIdentifier) { const foundTasks = await that._findWorkspaceTasks((task: Task | ConfiguringTask): boolean => { + const taskUri = ((ConfiguringTask.is(task) || CustomTask.is(task)) ? task._source.config.workspaceFolder?.uri : undefined); + const originalUri = (typeof uri === 'string' ? uri : uri.toString()); + if (taskUri?.toString() !== originalUri) { + return false; + } if (Types.isString(identifier)) { return ((task._label === identifier) || (task.configurationProperties.identifier === identifier)); } else { @@ -1649,7 +1654,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer return undefined; } if ((resolverData === undefined) && (grouped === undefined)) { - return (await quickResolve(this, identifier)) ?? fullResolve(this, uri, identifier); + return (await quickResolve(this, uri, identifier)) ?? fullResolve(this, uri, identifier); } else { return fullResolve(this, uri, identifier); } From 75cc7c1856aec05504c95b8819ae3cd38e8887cf Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 10 Mar 2022 15:06:14 +0100 Subject: [PATCH 102/175] Convert `ExtensionRunningLocation` to a type --- .../abstractRuntimeExtensionsEditor.ts | 4 +- .../extensions/browser/extensionService.ts | 36 +++-- .../common/abstractExtensionService.ts | 53 +++---- .../services/extensions/common/extensions.ts | 31 +++-- .../electron-browser/extensionService.ts | 46 +++---- .../test/browser/extensionService.test.ts | 130 +++++++++--------- 6 files changed, 150 insertions(+), 150 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts index c72727c939e..a570f894674 100644 --- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts @@ -11,7 +11,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionsWorkbenchService, IExtension } from 'vs/workbench/contrib/extensions/common/extensions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IExtensionService, IExtensionsStatus, IExtensionHostProfile, ExtensionRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionService, IExtensionsStatus, IExtensionHostProfile, ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; import { IListVirtualDelegate, IListRenderer } from 'vs/base/browser/ui/list/list'; import { WorkbenchList } from 'vs/platform/list/browser/listService'; import { append, $, Dimension, clearNode, addDisposableListener } from 'vs/base/browser/dom'; @@ -370,7 +370,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { } let extraLabel: string | null = null; - if (element.status.runningLocation === ExtensionRunningLocation.LocalWebWorker) { + if (element.status.runningLocation && element.status.runningLocation.type === ExtensionHostKind.LocalWebWorker) { extraLabel = `$(globe) web worker`; } else if (element.description.extensionLocation.scheme === Schemas.vscodeRemote) { const hostLabel = this._labelService.getHostLabel(Schemas.vscodeRemote, this._environmentService.remoteAuthority); diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts index ff5696b45fa..755dbba42bc 100644 --- a/src/vs/workbench/services/extensions/browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/browser/extensionService.ts @@ -9,11 +9,11 @@ import { IWorkbenchExtensionEnablementService, IWebExtensionsScannerService } fr import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IExtensionService, IExtensionHost, toExtensionDescription, ExtensionRunningLocation, extensionRunningLocationToString } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionService, IExtensionHost, toExtensionDescription, ExtensionRunningLocation, extensionRunningLocationToString, ExtensionHostKind, RemoteRunningLocation, LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { IProductService } from 'vs/platform/product/common/productService'; -import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString } from 'vs/workbench/services/extensions/common/abstractExtensionService'; +import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString, filterByRunningLocation } from 'vs/workbench/services/extensions/common/abstractExtensionService'; import { RemoteExtensionHost, IRemoteExtensionHostDataProvider, IRemoteExtensionHostInitData } from 'vs/workbench/services/extensions/common/remoteExtensionHost'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { WebWorkerExtensionHost } from 'vs/workbench/services/extensions/browser/webWorkerExtensionHost'; @@ -72,7 +72,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten logService ); - this._runningLocation = new Map(); + this._runningLocation = new Map(); // Initialize installed extensions first and do it only after workbench is ready this._lifecycleService.when(LifecyclePhase.Ready).then(async () => { @@ -111,7 +111,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten return { getInitData: async () => { const allExtensions = await this.getExtensions(); - const localWebWorkerExtensions = filterByRunningLocation(allExtensions, this._runningLocation, ExtensionRunningLocation.LocalWebWorker); + const localWebWorkerExtensions = filterByRunningLocation(allExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); return { autoStart: true, extensions: localWebWorkerExtensions @@ -130,20 +130,20 @@ export class ExtensionService extends AbstractExtensionService implements IExten }; } - protected _pickRunningLocation(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation { + protected _pickRunningLocation(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation | null { const result = ExtensionService.pickRunningLocation(extensionKinds, isInstalledLocally, isInstalledRemotely, preference); this._logService.trace(`pickRunningLocation for ${extensionId.value}, extension kinds: [${extensionKinds.join(', ')}], isInstalledLocally: ${isInstalledLocally}, isInstalledRemotely: ${isInstalledRemotely}, preference: ${extensionRunningPreferenceToString(preference)} => ${extensionRunningLocationToString(result)}`); return result; } - public static pickRunningLocation(extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation { + public static pickRunningLocation(extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation | null { const result: ExtensionRunningLocation[] = []; let canRunRemotely = false; for (const extensionKind of extensionKinds) { if (extensionKind === 'ui' && isInstalledRemotely) { // ui extensions run remotely if possible (but only as a last resort) if (preference === ExtensionRunningPreference.Remote) { - return ExtensionRunningLocation.Remote; + return new RemoteRunningLocation(); } else { canRunRemotely = true; } @@ -151,24 +151,24 @@ export class ExtensionService extends AbstractExtensionService implements IExten if (extensionKind === 'workspace' && isInstalledRemotely) { // workspace extensions run remotely if possible if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Remote) { - return ExtensionRunningLocation.Remote; + return new RemoteRunningLocation(); } else { - result.push(ExtensionRunningLocation.Remote); + result.push(new RemoteRunningLocation()); } } if (extensionKind === 'web' && (isInstalledLocally || isInstalledRemotely)) { // web worker extensions run in the local web worker if possible if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Local) { - return ExtensionRunningLocation.LocalWebWorker; + return new LocalWebWorkerRunningLocation(); } else { - result.push(ExtensionRunningLocation.LocalWebWorker); + result.push(new LocalWebWorkerRunningLocation()); } } } if (canRunRemotely) { - result.push(ExtensionRunningLocation.Remote); + result.push(new RemoteRunningLocation()); } - return (result.length > 0 ? result[0] : ExtensionRunningLocation.None); + return (result.length > 0 ? result[0] : null); } protected _createExtensionHosts(_isInitialStart: boolean): IExtensionHost[] { @@ -202,9 +202,9 @@ export class ExtensionService extends AbstractExtensionService implements IExten this._runningLocation = this._runningLocationClassifier.determineRunningLocation(localExtensions, remoteExtensions); // Some remote extensions could run locally in the web worker, so store them - const remoteExtensionsThatNeedToRunLocally = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionRunningLocation.LocalWebWorker); - localExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionRunningLocation.LocalWebWorker); - remoteExtensions = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionRunningLocation.Remote); + const remoteExtensionsThatNeedToRunLocally = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); + localExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); + remoteExtensions = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionHostKind.Remote); // Add locally the remote extensions that need to run locally in the web worker for (const ext of remoteExtensionsThatNeedToRunLocally) { @@ -246,10 +246,6 @@ export class ExtensionService extends AbstractExtensionService implements IExten } } -function filterByRunningLocation(extensions: IExtensionDescription[], runningLocation: Map, desiredRunningLocation: ExtensionRunningLocation): IExtensionDescription[] { - return extensions.filter(ext => runningLocation.get(ExtensionIdentifier.toKey(ext.identifier)) === desiredRunningLocation); -} - function includes(extensions: IExtensionDescription[], identifier: ExtensionIdentifier): boolean { for (const extension of extensions) { if (ExtensionIdentifier.equals(extension.identifier, identifier)) { diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index aeb23b01d1e..1a047e67240 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -162,7 +162,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx private _deltaExtensionsQueue: DeltaExtensionsQueueItem[]; private _inHandleDeltaExtensions: boolean; - protected _runningLocation: Map; + protected _runningLocation: Map; // --- Members used per extension host process protected _extensionHostManagers: IExtensionHostManager[]; @@ -264,7 +264,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx return this._extensionManifestPropertiesService.getExtensionKind(extensionDescription); } - protected abstract _pickRunningLocation(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation; + protected abstract _pickRunningLocation(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation | null; protected _getExtensionHostManager(kind: ExtensionHostKind): IExtensionHostManager | null { for (const extensionHostManager of this._extensionHostManagers) { @@ -375,19 +375,19 @@ export abstract class AbstractExtensionService extends Disposable implements IEx private async _updateExtensionsOnExtHosts(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise { const groupedToRemove: ExtensionIdentifier[][] = []; - const groupRemove = (extensionHostKind: ExtensionHostKind, extensionRunningLocation: ExtensionRunningLocation) => { - groupedToRemove[extensionHostKind] = filterByRunningLocation(toRemove, extId => extId, this._runningLocation, extensionRunningLocation); + const groupRemove = (extensionHostKind: ExtensionHostKind) => { + groupedToRemove[extensionHostKind] = _filterByRunningLocation(toRemove, extId => extId, this._runningLocation, extensionHostKind); }; - groupRemove(ExtensionHostKind.LocalProcess, ExtensionRunningLocation.LocalProcess); - groupRemove(ExtensionHostKind.LocalWebWorker, ExtensionRunningLocation.LocalWebWorker); - groupRemove(ExtensionHostKind.Remote, ExtensionRunningLocation.Remote); + groupRemove(ExtensionHostKind.LocalProcess); + groupRemove(ExtensionHostKind.LocalWebWorker); + groupRemove(ExtensionHostKind.Remote); for (const extensionId of toRemove) { this._runningLocation.delete(ExtensionIdentifier.toKey(extensionId)); } const groupedToAdd: IExtensionDescription[][] = []; - const groupAdd = (extensionHostKind: ExtensionHostKind, extensionRunningLocation: ExtensionRunningLocation) => { - groupedToAdd[extensionHostKind] = filterByRunningLocation(toAdd, ext => ext.identifier, this._runningLocation, extensionRunningLocation); + const groupAdd = (extensionHostKind: ExtensionHostKind) => { + groupedToAdd[extensionHostKind] = filterByRunningLocation(toAdd, this._runningLocation, extensionHostKind); }; for (const extension of toAdd) { const extensionKind = this._getExtensionKind(extension); @@ -395,9 +395,9 @@ export abstract class AbstractExtensionService extends Disposable implements IEx const runningLocation = this._pickRunningLocation(extension.identifier, extensionKind, !isRemote, isRemote, ExtensionRunningPreference.None); this._runningLocation.set(ExtensionIdentifier.toKey(extension.identifier), runningLocation); } - groupAdd(ExtensionHostKind.LocalProcess, ExtensionRunningLocation.LocalProcess); - groupAdd(ExtensionHostKind.LocalWebWorker, ExtensionRunningLocation.LocalWebWorker); - groupAdd(ExtensionHostKind.Remote, ExtensionRunningLocation.Remote); + groupAdd(ExtensionHostKind.LocalProcess); + groupAdd(ExtensionHostKind.LocalWebWorker); + groupAdd(ExtensionHostKind.Remote); const promises: Promise[] = []; @@ -430,7 +430,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx const extensionKind = this._getExtensionKind(extension); const isRemote = extension.extensionLocation.scheme === Schemas.vscodeRemote; const runningLocation = this._pickRunningLocation(extension.identifier, extensionKind, !isRemote, isRemote, ExtensionRunningPreference.None); - if (runningLocation === ExtensionRunningLocation.None) { + if (!runningLocation) { return false; } @@ -564,12 +564,8 @@ export abstract class AbstractExtensionService extends Disposable implements IEx for (const extension of this._registry.getAllExtensionDescriptions()) { if (isEqualOrParent(testLocation, extension.extensionLocation)) { const runningLocation = this._runningLocation.get(ExtensionIdentifier.toKey(extension.identifier)); - if (runningLocation === ExtensionRunningLocation.LocalProcess) { - extensionHostKind = ExtensionHostKind.LocalProcess; - } else if (runningLocation === ExtensionRunningLocation.LocalWebWorker) { - extensionHostKind = ExtensionHostKind.LocalWebWorker; - } else if (runningLocation === ExtensionRunningLocation.Remote) { - extensionHostKind = ExtensionHostKind.Remote; + if (runningLocation) { + extensionHostKind = runningLocation.type; } break; } @@ -771,7 +767,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx messages: this._extensionsMessages.get(extensionKey) || [], activationTimes: this._extensionHostActivationTimes.get(extensionKey), runtimeErrors: this._extensionHostExtensionRuntimeErrors.get(extensionKey) || [], - runningLocation: this._runningLocation.get(extensionKey) || ExtensionRunningLocation.None, + runningLocation: this._runningLocation.get(extensionKey) || null, }; } } @@ -1097,7 +1093,7 @@ class ExtensionInfo { class ExtensionRunningLocationClassifier { constructor( private readonly getExtensionKind: (extensionDescription: IExtensionDescription) => ExtensionKind[], - private readonly pickRunningLocation: (extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference) => ExtensionRunningLocation, + private readonly pickRunningLocation: (extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference) => ExtensionRunningLocation | null, ) { } @@ -1110,7 +1106,7 @@ class ExtensionRunningLocationClassifier { return result; } - public determineRunningLocation(_localExtensions: IExtensionDescription[], _remoteExtensions: IExtensionDescription[]): Map { + public determineRunningLocation(_localExtensions: IExtensionDescription[], _remoteExtensions: IExtensionDescription[]): Map { const localExtensions = this._toExtensionWithKind(_localExtensions); const remoteExtensions = this._toExtensionWithKind(_remoteExtensions); @@ -1127,7 +1123,7 @@ class ExtensionRunningLocationClassifier { localExtensions.forEach((ext) => collectExtension(ext)); remoteExtensions.forEach((ext) => collectExtension(ext)); - const runningLocation = new Map(); + const runningLocation = new Map(); allExtensions.forEach((ext) => { const isInstalledLocally = Boolean(ext.local); const isInstalledRemotely = Boolean(ext.remote); @@ -1244,6 +1240,13 @@ class ProposedApiController { } } -function filterByRunningLocation(extensions: T[], extId: (item: T) => ExtensionIdentifier, runningLocation: Map, desiredRunningLocation: ExtensionRunningLocation): T[] { - return extensions.filter(ext => runningLocation.get(ExtensionIdentifier.toKey(extId(ext))) === desiredRunningLocation); +export function filterByRunningLocation(extensions: IExtensionDescription[], runningLocation: Map, desiredExtensionHostKind: ExtensionHostKind): IExtensionDescription[] { + return _filterByRunningLocation(extensions, ext => ext.identifier, runningLocation, desiredExtensionHostKind); +} + +function _filterByRunningLocation(extensions: T[], extId: (item: T) => ExtensionIdentifier, runningLocation: Map, desiredExtensionHostKind: ExtensionHostKind): T[] { + return extensions.filter((ext) => { + const extRunningLocation = runningLocation.get(ExtensionIdentifier.toKey(extId(ext))); + return (extRunningLocation && extRunningLocation.type === desiredExtensionHostKind); + }); } diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 6398b447a1a..1d57b5cbf5d 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -36,22 +36,27 @@ export interface IMessage { extensionPointId: string; } -export const enum ExtensionRunningLocation { - None, - LocalProcess, - LocalWebWorker, - Remote +export class LocalProcessRunningLocation { + public readonly type = ExtensionHostKind.LocalProcess; } +export class LocalWebWorkerRunningLocation { + public readonly type = ExtensionHostKind.LocalWebWorker; +} +export class RemoteRunningLocation { + public readonly type = ExtensionHostKind.Remote; +} +export type ExtensionRunningLocation = LocalProcessRunningLocation | LocalWebWorkerRunningLocation | RemoteRunningLocation; -export function extensionRunningLocationToString(location: ExtensionRunningLocation) { - switch (location) { - case ExtensionRunningLocation.None: - return 'None'; - case ExtensionRunningLocation.LocalProcess: +export function extensionRunningLocationToString(location: ExtensionRunningLocation | null) { + if (!location) { + return 'None'; + } + switch (location.type) { + case ExtensionHostKind.LocalProcess: return 'LocalProcess'; - case ExtensionRunningLocation.LocalWebWorker: + case ExtensionHostKind.LocalWebWorker: return 'LocalWebWorker'; - case ExtensionRunningLocation.Remote: + case ExtensionHostKind.Remote: return 'Remote'; } } @@ -60,7 +65,7 @@ export interface IExtensionsStatus { messages: IMessage[]; activationTimes: ActivationTimes | undefined; runtimeErrors: Error[]; - runningLocation: ExtensionRunningLocation; + runningLocation: ExtensionRunningLocation | null; } export class MissingExtensionDependency { diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 783fe97db1d..fee743deec3 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -7,7 +7,7 @@ import { LocalProcessExtensionHost } from 'vs/workbench/services/extensions/elec import { CachedExtensionScanner } from 'vs/workbench/services/extensions/electron-sandbox/cachedExtensionScanner'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString } from 'vs/workbench/services/extensions/common/abstractExtensionService'; +import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString, filterByRunningLocation } from 'vs/workbench/services/extensions/common/abstractExtensionService'; import * as nls from 'vs/nls'; import { runWhenIdle } from 'vs/base/common/async'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -22,7 +22,7 @@ import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecyc import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { IExtensionService, toExtension, ExtensionHostKind, IExtensionHost, webWorkerExtHostConfig, ExtensionRunningLocation, WebWorkerExtHostConfigValue, extensionRunningLocationToString, extensionHostKindToString } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionService, toExtension, ExtensionHostKind, IExtensionHost, webWorkerExtHostConfig, ExtensionRunningLocation, WebWorkerExtHostConfigValue, extensionRunningLocationToString, extensionHostKindToString, LocalProcessRunningLocation, RemoteRunningLocation, LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; import { IExtensionHostManager } from 'vs/workbench/services/extensions/common/extensionHostManager'; import { ExtensionIdentifier, IExtension, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { ExtensionKind } from 'vs/platform/environment/common/environment'; @@ -151,14 +151,14 @@ export class ExtensionService extends AbstractExtensionService implements IExten ])); } - private _createLocalExtensionHostDataProvider(isInitialStart: boolean, desiredRunningLocation: ExtensionRunningLocation) { + private _createLocalExtensionHostDataProvider(isInitialStart: boolean, desiredExtensionHostKind: ExtensionHostKind) { return { getInitData: async () => { if (isInitialStart) { // Here we load even extensions that would be disabled by workspace trust const localExtensions = this._checkEnabledAndProposedAPI(await this._scanAllLocalExtensions(), /* ignore workspace trust */true); const runningLocation = this._runningLocationClassifier.determineRunningLocation(localExtensions, []); - const localProcessExtensions = filterByRunningLocation(localExtensions, runningLocation, desiredRunningLocation); + const localProcessExtensions = filterByRunningLocation(localExtensions, runningLocation, desiredExtensionHostKind); return { autoStart: false, extensions: localProcessExtensions @@ -166,7 +166,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten } else { // restart case const allExtensions = await this.getExtensions(); - const localProcessExtensions = filterByRunningLocation(allExtensions, this._runningLocation, desiredRunningLocation); + const localProcessExtensions = filterByRunningLocation(allExtensions, this._runningLocation, desiredExtensionHostKind); return { autoStart: true, extensions: localProcessExtensions @@ -186,59 +186,59 @@ export class ExtensionService extends AbstractExtensionService implements IExten }; } - protected _pickRunningLocation(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation { + protected _pickRunningLocation(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation | null { const result = ExtensionService.pickRunningLocation(extensionKinds, isInstalledLocally, isInstalledRemotely, preference, Boolean(this._environmentService.remoteAuthority), this._enableLocalWebWorker); this._logService.trace(`pickRunningLocation for ${extensionId.value}, extension kinds: [${extensionKinds.join(', ')}], isInstalledLocally: ${isInstalledLocally}, isInstalledRemotely: ${isInstalledRemotely}, preference: ${extensionRunningPreferenceToString(preference)} => ${extensionRunningLocationToString(result)}`); return result; } - public static pickRunningLocation(extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference, hasRemoteExtHost: boolean, hasWebWorkerExtHost: boolean): ExtensionRunningLocation { + public static pickRunningLocation(extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference, hasRemoteExtHost: boolean, hasWebWorkerExtHost: boolean): ExtensionRunningLocation | null { const result: ExtensionRunningLocation[] = []; for (const extensionKind of extensionKinds) { if (extensionKind === 'ui' && isInstalledLocally) { // ui extensions run locally if possible if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Local) { - return ExtensionRunningLocation.LocalProcess; + return new LocalProcessRunningLocation(); } else { - result.push(ExtensionRunningLocation.LocalProcess); + result.push(new LocalProcessRunningLocation()); } } if (extensionKind === 'workspace' && isInstalledRemotely) { // workspace extensions run remotely if possible if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Remote) { - return ExtensionRunningLocation.Remote; + return new RemoteRunningLocation(); } else { - result.push(ExtensionRunningLocation.Remote); + result.push(new RemoteRunningLocation()); } } if (extensionKind === 'workspace' && !hasRemoteExtHost) { // workspace extensions also run locally if there is no remote if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Local) { - return ExtensionRunningLocation.LocalProcess; + return new LocalProcessRunningLocation(); } else { - result.push(ExtensionRunningLocation.LocalProcess); + result.push(new LocalProcessRunningLocation()); } } if (extensionKind === 'web' && isInstalledLocally && hasWebWorkerExtHost) { // web worker extensions run in the local web worker if possible if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Local) { - return ExtensionRunningLocation.LocalWebWorker; + return new LocalWebWorkerRunningLocation(); } else { - result.push(ExtensionRunningLocation.LocalWebWorker); + result.push(new LocalWebWorkerRunningLocation()); } } } - return (result.length > 0 ? result[0] : ExtensionRunningLocation.None); + return (result.length > 0 ? result[0] : null); } protected _createExtensionHosts(isInitialStart: boolean): IExtensionHost[] { const result: IExtensionHost[] = []; - const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionRunningLocation.LocalProcess)); + const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionHostKind.LocalProcess)); result.push(localProcessExtHost); if (this._enableLocalWebWorker) { - const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, this._lazyLocalWebWorker, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionRunningLocation.LocalWebWorker)); + const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, this._lazyLocalWebWorker, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionHostKind.LocalWebWorker)); result.push(webWorkerExtHost); } @@ -474,9 +474,9 @@ export class ExtensionService extends AbstractExtensionService implements IExten this._runningLocation = this._runningLocationClassifier.determineRunningLocation(localExtensions, remoteExtensions); // remove non-UI extensions from the local extensions - const localProcessExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionRunningLocation.LocalProcess); - const localWebWorkerExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionRunningLocation.LocalWebWorker); - remoteExtensions = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionRunningLocation.Remote); + const localProcessExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionHostKind.LocalProcess); + const localWebWorkerExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); + remoteExtensions = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionHostKind.Remote); const result = this._registry.deltaExtensions(remoteExtensions.concat(localProcessExtensions).concat(localWebWorkerExtensions), []); if (result.removedDueToLooping.length > 0) { @@ -630,10 +630,6 @@ function getRemoteAuthorityPrefix(remoteAuthority: string): string { return remoteAuthority.substring(0, plusIndex); } -function filterByRunningLocation(extensions: IExtensionDescription[], runningLocation: Map, desiredRunningLocation: ExtensionRunningLocation): IExtensionDescription[] { - return extensions.filter(ext => runningLocation.get(ExtensionIdentifier.toKey(ext.identifier)) === desiredRunningLocation); -} - registerSingleton(IExtensionService, ExtensionService); class RestartExtensionHostAction extends Action2 { diff --git a/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts b/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts index ec46f3b43be..95c7347a8c0 100644 --- a/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts +++ b/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts @@ -6,84 +6,84 @@ import * as assert from 'assert'; import { ExtensionService as BrowserExtensionService } from 'vs/workbench/services/extensions/browser/extensionService'; import { ExtensionRunningPreference } from 'vs/workbench/services/extensions/common/abstractExtensionService'; -import { ExtensionRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; +import { ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; suite('BrowserExtensionService', () => { test('pickRunningLocation', () => { - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.None); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], false, true, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], true, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], true, true, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, false, ExtensionRunningPreference.None), ExtensionRunningLocation.None); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, false, ExtensionRunningPreference.None), ExtensionRunningLocation.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, true, ExtensionRunningPreference.None), ExtensionRunningLocation.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, false, ExtensionRunningPreference.None), null); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); }); }); From c2b51748cf0dfbff9de89d80884efa9c553d611b Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 10 Mar 2022 15:07:28 +0100 Subject: [PATCH 103/175] Investigate potential rst grammar to include as a built-in extension (#144680) --- extensions/restructuredtext/.vscodeignore | 2 + extensions/restructuredtext/cgmanifest.json | 17 + .../language-configuration.json | 34 + extensions/restructuredtext/package.json | 39 + extensions/restructuredtext/package.nls.json | 4 + .../syntaxes/rst.tmLanguage.json | 732 ++++++++++ extensions/restructuredtext/yarn.lock | 4 + .../test/colorize-fixtures/test.rst | 98 ++ .../test/colorize-results/test_rst.json | 1298 +++++++++++++++++ 9 files changed, 2228 insertions(+) create mode 100644 extensions/restructuredtext/.vscodeignore create mode 100644 extensions/restructuredtext/cgmanifest.json create mode 100644 extensions/restructuredtext/language-configuration.json create mode 100644 extensions/restructuredtext/package.json create mode 100644 extensions/restructuredtext/package.nls.json create mode 100644 extensions/restructuredtext/syntaxes/rst.tmLanguage.json create mode 100644 extensions/restructuredtext/yarn.lock create mode 100644 extensions/vscode-colorize-tests/test/colorize-fixtures/test.rst create mode 100644 extensions/vscode-colorize-tests/test/colorize-results/test_rst.json diff --git a/extensions/restructuredtext/.vscodeignore b/extensions/restructuredtext/.vscodeignore new file mode 100644 index 00000000000..0a622e7e300 --- /dev/null +++ b/extensions/restructuredtext/.vscodeignore @@ -0,0 +1,2 @@ +test/** +cgmanifest.json diff --git a/extensions/restructuredtext/cgmanifest.json b/extensions/restructuredtext/cgmanifest.json new file mode 100644 index 00000000000..0932073877b --- /dev/null +++ b/extensions/restructuredtext/cgmanifest.json @@ -0,0 +1,17 @@ +{ + "registrations": [ + { + "component": { + "type": "git", + "git": { + "name": "trond-snekvik/vscode-rst", + "repositoryUrl": "https://github.com/trond-snekvik/vscode-rst", + "commitHash": "f0fe19ffde6509be52ad9267a57e1b3df665f072" + } + }, + "license": "MIT", + "version": "1.5.1" + } + ], + "version": 1 +} diff --git a/extensions/restructuredtext/language-configuration.json b/extensions/restructuredtext/language-configuration.json new file mode 100644 index 00000000000..d98c8c34c12 --- /dev/null +++ b/extensions/restructuredtext/language-configuration.json @@ -0,0 +1,34 @@ +{ + "comments": { + "lineComment": ".." + }, + "brackets": [ + ["(", ")"], + ["<", ">"], + ["[", "]"] + ], + "surroundingPairs": [ + ["(", ")"], + ["<", ">"], + ["`", "`"], + ["*", "*"], + ["|", "|"], + ["[", "]"] + ], + "autoClosingPairs": [ + { "open": "(", "close": ")" }, + { "open": "<", "close": ">" }, + { "open": "'", "close": "'"}, + { "open": "`", "close": "`", "notIn": ["string"]}, + { "open": "\"", "close": "\""}, + { "open": "[", "close": "]"} + ], + "autoCloseBefore": ":})>`\\n ", + "onEnterRules": [ + { + "beforeText": "^\\s*\\.\\. *$|(?" + }, + { + "match": "{[`*]+}" + }, + { + "match": "\\([`*]+\\)" + }, + { + "match": "\\[[`*]+\\]" + }, + { + "match": "\"[`*]+\"" + } + ] + }, + "table": { + "begin": "^\\s*\\+[=+-]+\\+\\s*$", + "end": "^(?![+|])", + "beginCaptures": { + "0": { + "name": "keyword.control.table" + } + }, + "patterns": [ + { + "match": "[=+|-]", + "name": "keyword.control.table" + } + ] + }, + "simple-table": { + "match": "^[=\\s]+$", + "name": "keyword.control.table" + }, + "ref": { + "begin": "(:ref:)`", + "end": "`|^\\s*$", + "name": "entity.name.tag", + "beginCaptures": { + "1": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "match": "<.*?>", + "name": "markup.underline.link" + } + ] + }, + "reference": { + "match": "[\\w-]*[a-zA-Z\\d-]__?\\b", + "name": "entity.name.tag" + }, + "macro": { + "match": "\\|[^\\|]+\\|", + "name": "entity.name.tag" + }, + "literal": { + "match": "(:\\S+:)(`.*?`\\\\?)", + "captures": { + "1": { + "name": "keyword.control" + }, + "2": { + "name": "entity.name.tag" + } + } + }, + "monospaced": { + "begin": "(?<=[\\s\"'(\\[{<]|^)``[^\\s`]", + "end": "``|^\\s*$", + "name": "string.interpolated" + }, + "citation": { + "begin": "(?<=[\\s\"'(\\[{<]|^)`[^\\s`]", + "end": "`_{,2}|^\\s*$", + "name": "entity.name.tag", + "applyEndPatternLast": 0 + }, + "bold": { + "begin": "(?<=[\\s\"'(\\[{<]|^)\\*{2}[^\\s*]", + "end": "\\*{2}|^\\s*$", + "name": "markup.bold" + }, + "italic": { + "begin": "(?<=[\\s\"'(\\[{<]|^)\\*[^\\s*]", + "end": "\\*|^\\s*$", + "name": "markup.italic" + }, + "escaped": { + "match": "\\\\.", + "name": "constant.character.escape" + }, + "list": { + "match": "^\\s*(\\d+\\.|\\* -|[a-zA-Z#]\\.|[iIvVxXmMcC]+\\.|\\(\\d+\\)|\\d+\\)|[*+-])\\s+", + "name": "keyword.control" + }, + "line-block": { + "match": "^\\|\\s+", + "name": "keyword.control" + }, + "raw-html": { + "begin": "^(\\s*)(\\.{2}\\s+raw\\s*::)\\s+(html)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "3": { + "name": "variable.parameter.html" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "text.html.derivative" + } + ] + }, + "anchor": { + "match": "^\\.{2}\\s+(_[^:]+:)\\s*", + "name": "entity.name.tag.anchor" + }, + "replace-include": { + "match": "^\\s*(\\.{2})\\s+(\\|[^\\|]+\\|)\\s+(replace::)", + "captures": { + "1": { + "name": "keyword.control" + }, + "2": { + "name": "entity.name.tag" + }, + "3": { + "name": "keyword.control" + } + } + }, + "footnote": { + "match": "^\\s*\\.{2}\\s+\\[(?:[\\w\\.-]+|[#*]|#\\w+)\\]\\s+", + "name": "entity.name.tag" + }, + "footnote-ref": { + "match": "\\[(?:[\\w\\.-]+|[#*])\\]_", + "name": "entity.name.tag" + }, + "substitution": { + "match": "^\\.{2}\\s*\\|([^|]+)\\|", + "name": "entity.name.tag" + }, + "options-list": { + "match": "^((?:-\\w|--[\\w-]+|/\\w+)(?:,? ?[\\w-]+)*)(?: |\\t|$)", + "name": "variable.parameter" + }, + "blocks": { + "patterns": [ + { + "include": "#domains" + }, + { + "include": "#doctest" + }, + { + "include": "#code-block-cpp" + }, + { + "include": "#code-block-py" + }, + { + "include": "#code-block-console" + }, + { + "include": "#code-block-javascript" + }, + { + "include": "#code-block-yaml" + }, + { + "include": "#code-block-cmake" + }, + { + "include": "#code-block-kconfig" + }, + { + "include": "#code-block-ruby" + }, + { + "include": "#code-block-dts" + }, + { + "include": "#code-block" + }, + { + "include": "#doctest-block" + }, + { + "include": "#raw-html" + }, + { + "include": "#block" + }, + { + "include": "#literal-block" + }, + { + "include": "#block-comment" + } + ] + }, + "block-comment": { + "begin": "^(\\s*)\\.{2}", + "while": "^\\1(?=\\s)|^\\s*$", + "name": "comment.block" + }, + "literal-block": { + "begin": "^(\\s*)(.*)(::)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "patterns": [ + { + "include": "#inline-markup" + } + ] + }, + "3": { + "name": "keyword.control" + } + } + }, + "block": { + "begin": "^(\\s*)(\\.{2}\\s+\\S+::)(.*)", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "3": { + "name": "variable" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "#body" + } + ] + }, + "block-param": { + "patterns": [ + { + "match": "(:param\\s+(.+?):)(?:\\s|$)", + "captures": { + "1": { + "name": "keyword.control" + }, + "2": { + "name": "variable.parameter" + } + } + }, + { + "match": "(:.+?:)(?:$|\\s+(.*))", + "captures": { + "1": { + "name": "keyword.control" + }, + "2": { + "patterns": [ + { + "match": "\\b(0x[a-fA-F\\d]+|\\d+)\\b", + "name": "constant.numeric" + }, + { + "include": "#inline-markup" + } + ] + } + } + } + ] + }, + "domains": { + "patterns": [ + { + "include": "#domain-cpp" + }, + { + "include": "#domain-py" + }, + { + "include": "#domain-auto" + }, + { + "include": "#domain-js" + } + ] + }, + "domain-cpp": { + "begin": "^(\\s*)(\\.{2}\\s+(?:cpp|c):(?:class|struct|function|member|var|type|enum|enum-struct|enum-class|enumerator|union|concept)::)\\s*(?:(@\\w+)|(.*))", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "3": { + "name": "entity.name.tag" + }, + "4": { + "patterns": [ + { + "include": "source.cpp" + } + ] + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "#body" + } + ] + }, + "domain-py": { + "begin": "^(\\s*)(\\.{2}\\s+py:(?:module|function|data|exception|class|attribute|property|method|staticmethod|classmethod|decorator|decoratormethod)::)\\s*(.*)", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "3": { + "patterns": [ + { + "include": "source.python" + } + ] + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "#body" + } + ] + }, + "domain-auto": { + "begin": "^(\\s*)(\\.{2}\\s+auto(?:class|module|exception|function|decorator|data|method|attribute|property)::)\\s*(.*)", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control.py" + }, + "3": { + "patterns": [ + { + "include": "source.python" + } + ] + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "#body" + } + ] + }, + "domain-js": { + "begin": "^(\\s*)(\\.{2}\\s+js:\\w+::)\\s*(.*)", + "end": "^(?!\\1[ \\t]|$)", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "3": { + "patterns": [ + { + "include": "source.js" + } + ] + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "#body" + } + ] + }, + "doctest": { + "begin": "^(>>>)\\s*(.*)", + "end": "^\\s*$", + "beginCaptures": { + "1": { + "name": "keyword.control" + }, + "2": { + "patterns": [ + { + "include": "source.python" + } + ] + } + } + }, + "code-block-cpp": { + "begin": "^(\\s*)(\\.{2}\\s+(code|code-block)::)\\s*(c|c\\+\\+|cpp|C|C\\+\\+|CPP|Cpp)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "4": { + "name": "variable.parameter.codeblock.cpp" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "source.cpp" + } + ] + }, + "code-block-console": { + "begin": "^(\\s*)(\\.{2}\\s+(code|code-block)::)\\s*(console|shell|bash)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "4": { + "name": "variable.parameter.codeblock.console" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "source.shell" + } + ] + }, + "code-block-py": { + "begin": "^(\\s*)(\\.{2}\\s+(code|code-block)::)\\s*(python)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "4": { + "name": "variable.parameter.codeblock.py" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "source.python" + } + ] + }, + "code-block-javascript": { + "begin": "^(\\s*)(\\.{2}\\s+(code|code-block)::)\\s*(javascript)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "4": { + "name": "variable.parameter.codeblock.js" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "source.js" + } + ] + }, + "code-block-yaml": { + "begin": "^(\\s*)(\\.{2}\\s+(code|code-block)::)\\s*(ya?ml)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "4": { + "name": "variable.parameter.codeblock.yaml" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "source.yaml" + } + ] + }, + "code-block-cmake": { + "begin": "^(\\s*)(\\.{2}\\s+(code|code-block)::)\\s*(cmake)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "4": { + "name": "variable.parameter.codeblock.cmake" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "source.cmake" + } + ] + }, + "code-block-kconfig": { + "begin": "^(\\s*)(\\.{2}\\s+(code|code-block)::)\\s*([kK]config)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "4": { + "name": "variable.parameter.codeblock.kconfig" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "source.kconfig" + } + ] + }, + "code-block-ruby": { + "begin": "^(\\s*)(\\.{2}\\s+(code|code-block)::)\\s*(ruby)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "4": { + "name": "variable.parameter.codeblock.ruby" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "source.ruby" + } + ] + }, + "code-block-dts": { + "begin": "^(\\s*)(\\.{2}\\s+(code|code-block)::)\\s*(dts|DTS|devicetree)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + }, + "4": { + "name": "variable.parameter.codeblock.dts" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "source.dts" + } + ] + }, + "code-block": { + "begin": "^(\\s*)(\\.{2}\\s+(code|code-block)::)", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#block-param" + } + ] + }, + "doctest-block": { + "begin": "^(\\s*)(\\.{2}\\s+doctest::)\\s*$", + "while": "^\\1(?=\\s)|^\\s*$", + "beginCaptures": { + "2": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#block-param" + }, + { + "include": "source.python" + } + ] + } + } +} \ No newline at end of file diff --git a/extensions/restructuredtext/yarn.lock b/extensions/restructuredtext/yarn.lock new file mode 100644 index 00000000000..fb57ccd13af --- /dev/null +++ b/extensions/restructuredtext/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + diff --git a/extensions/vscode-colorize-tests/test/colorize-fixtures/test.rst b/extensions/vscode-colorize-tests/test/colorize-fixtures/test.rst new file mode 100644 index 00000000000..749bf14f800 --- /dev/null +++ b/extensions/vscode-colorize-tests/test/colorize-fixtures/test.rst @@ -0,0 +1,98 @@ +*italics*, **bold**, ``literal``. + +1. A list +2. With items + - With sub-lists ... + - ... of things. +3. Other things + +definition list + A list of terms and their definition + +Literal block:: + + x = 2 + 3 + + +Section separators are all interchangeable. + +===== +Title +===== + +-------- +Subtitle +-------- + +Section 1 +========= + +Section 2 +--------- + +Section 3 +~~~~~~~~~ + +| Keeping line +| breaks. + + ++-------------+--------------+ +| Fancy table | with columns | ++=============+==============+ +| row 1, col 1| row 1, col 2 | ++-------------+--------------+ + +============ ============ +Simple table with columns +============ ============ +row 1, col1 row 1, col 2 +============ ============ + +Block quote is indented. + + This space intentionally not important. + +Doctest block + +>>> 2 +3 +5 + +A footnote [#note]_. + +.. [#note] https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#footnotes + + +Citation [cite]_. + +.. [cite] https://bing.com + +a simple link_. + +A `fancier link`_ . + +.. _link: https://docutils.sourceforge.io/ +.. _fancier link: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html + + +An `inline link `__ . + +.. image:: https://code.visualstudio.com/assets/images/code-stable.png + +.. function: example() + :module: mod + + +:sub:`subscript` +:sup:`superscript` + +.. This is a comment. + +.. + And a bigger, + longer comment. + + +A |subst| of something. + +.. |subst| replace:: substitution diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_rst.json b/extensions/vscode-colorize-tests/test/colorize-results/test_rst.json new file mode 100644 index 00000000000..0cd405f260f --- /dev/null +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_rst.json @@ -0,0 +1,1298 @@ +[ + { + "c": "*italics*", + "t": "source.rst markup.italic", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": ", ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "**bold**", + "t": "source.rst markup.bold", + "r": { + "dark_plus": "markup.bold: #569CD6", + "light_plus": "markup.bold: #000080", + "dark_vs": "markup.bold: #569CD6", + "light_vs": "markup.bold: #000080", + "hc_black": "default: #FFFFFF", + "hc_light": "markup.bold: #000080" + } + }, + { + "c": ", ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "``literal``", + "t": "source.rst string.interpolated", + "r": { + "dark_plus": "string: #CE9178", + "light_plus": "string: #A31515", + "dark_vs": "string: #CE9178", + "light_vs": "string: #A31515", + "hc_black": "string: #CE9178", + "hc_light": "string: #A31515" + } + }, + { + "c": ".", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "1. ", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "A list", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "2. ", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "With items", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": " - ", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "With sub-lists ...", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": " - ", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "... of things.", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "3. ", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "Other things", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "definition list", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": " A list of terms and their definition", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "Literal block", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "::", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": " x = 2 + 3", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "Section separators are all interchangeable.", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "=====", + "t": "source.rst markup.heading", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6", + "hc_light": "markup.heading: #800000" + } + }, + { + "c": "Title", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "=====", + "t": "source.rst markup.heading", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6", + "hc_light": "markup.heading: #800000" + } + }, + { + "c": "--------", + "t": "source.rst markup.heading", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6", + "hc_light": "markup.heading: #800000" + } + }, + { + "c": "Subtitle", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "--------", + "t": "source.rst markup.heading", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6", + "hc_light": "markup.heading: #800000" + } + }, + { + "c": "Section 1", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "=========", + "t": "source.rst markup.heading", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6", + "hc_light": "markup.heading: #800000" + } + }, + { + "c": "Section 2", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "---------", + "t": "source.rst markup.heading", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6", + "hc_light": "markup.heading: #800000" + } + }, + { + "c": "Section 3", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "~~~~~~~~~", + "t": "source.rst markup.heading", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6", + "hc_light": "markup.heading: #800000" + } + }, + { + "c": "| ", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "Keeping line", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "| ", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "breaks.", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "+-------------+--------------+", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "|", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": " Fancy table ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "|", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": " with columns ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "|", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "+=============+==============+", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "|", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": " row 1, col 1", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "|", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": " row 1, col 2 ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "|", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "+-------------+--------------+", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "============ ============", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "Simple table with columns", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "============ ============", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "row 1, col1 row 1, col 2", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "============ ============", + "t": "source.rst keyword.control.table", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "Block quote is indented.", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": " This space intentionally not important.", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "Doctest block", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": ">>>", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": " ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "2", + "t": "source.rst constant.numeric.dec.python", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #098658", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #098658", + "hc_black": "constant.numeric: #B5CEA8", + "hc_light": "constant.numeric: #098658" + } + }, + { + "c": " ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "+", + "t": "source.rst keyword.operator.arithmetic.python", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4", + "hc_light": "keyword.operator: #000000" + } + }, + { + "c": "3", + "t": "source.rst constant.numeric.dec.python", + "r": { + "dark_plus": "constant.numeric: #B5CEA8", + "light_plus": "constant.numeric: #098658", + "dark_vs": "constant.numeric: #B5CEA8", + "light_vs": "constant.numeric: #098658", + "hc_black": "constant.numeric: #B5CEA8", + "hc_light": "constant.numeric: #098658" + } + }, + { + "c": "5", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "A footnote [#note]_.", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": ".. [#note] ", + "t": "source.rst entity.name.tag", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": "https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#footnotes", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "Citation ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "[cite]_", + "t": "source.rst entity.name.tag", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": ".", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": ".. [cite] ", + "t": "source.rst entity.name.tag", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": "https://bing.com", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "a simple ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "link_", + "t": "source.rst entity.name.tag", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": ".", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "A ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "`fancier link`_", + "t": "source.rst entity.name.tag", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": " .", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": ".. _link: ", + "t": "source.rst entity.name.tag.anchor", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": "https://docutils.sourceforge.io/", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": ".. _fancier link: ", + "t": "source.rst entity.name.tag.anchor", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": "https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "An ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "`inline link `__", + "t": "source.rst entity.name.tag", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": " .", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": ".. image::", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": " https://code.visualstudio.com/assets/images/code-stable.png", + "t": "source.rst variable", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE", + "hc_light": "variable: #001080" + } + }, + { + "c": ".. function: example()", + "t": "source.rst comment.block", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668", + "hc_light": "comment: #008000" + } + }, + { + "c": " :module: mod", + "t": "source.rst comment.block", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668", + "hc_light": "comment: #008000" + } + }, + { + "c": ":sub:", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "`subscript`", + "t": "source.rst entity.name.tag", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": ":sup:", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": "`superscript`", + "t": "source.rst entity.name.tag", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": ".. This is a comment.", + "t": "source.rst comment.block", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668", + "hc_light": "comment: #008000" + } + }, + { + "c": "..", + "t": "source.rst comment.block", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668", + "hc_light": "comment: #008000" + } + }, + { + "c": " And a bigger,", + "t": "source.rst comment.block", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668", + "hc_light": "comment: #008000" + } + }, + { + "c": " longer comment.", + "t": "source.rst comment.block", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668", + "hc_light": "comment: #008000" + } + }, + { + "c": "A ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "|subst|", + "t": "source.rst entity.name.tag", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": " of something.", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "..", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": " ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "|subst|", + "t": "source.rst entity.name.tag", + "r": { + "dark_plus": "entity.name.tag: #569CD6", + "light_plus": "entity.name.tag: #800000", + "dark_vs": "entity.name.tag: #569CD6", + "light_vs": "entity.name.tag: #800000", + "hc_black": "entity.name.tag: #569CD6", + "hc_light": "entity.name.tag: #800000" + } + }, + { + "c": " ", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + }, + { + "c": "replace::", + "t": "source.rst keyword.control", + "r": { + "dark_plus": "keyword.control: #C586C0", + "light_plus": "keyword.control: #AF00DB", + "dark_vs": "keyword.control: #569CD6", + "light_vs": "keyword.control: #0000FF", + "hc_black": "keyword.control: #C586C0", + "hc_light": "keyword.control: #AF00DB" + } + }, + { + "c": " substitution", + "t": "source.rst", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "hc_light": "default: #292929" + } + } +] \ No newline at end of file From 9109c6531f923991f5054c420e1456297ccb59a2 Mon Sep 17 00:00:00 2001 From: Johannes Date: Thu, 10 Mar 2022 16:17:17 +0100 Subject: [PATCH 104/175] clean-up keybindings and menu registrations for accept suggestion command --- .../suggest/browser/suggestController.ts | 70 +++++++++---------- 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/src/vs/editor/contrib/suggest/browser/suggestController.ts b/src/vs/editor/contrib/suggest/browser/suggestController.ts index 6a30fa5a353..79266686612 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestController.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestController.ts @@ -31,11 +31,10 @@ import { SnippetParser } from 'vs/editor/contrib/snippet/browser/snippetParser'; import { ISuggestMemoryService } from 'vs/editor/contrib/suggest/browser/suggestMemory'; import { WordContextKey } from 'vs/editor/contrib/suggest/browser/wordContextKey'; import * as nls from 'vs/nls'; -import { MenuRegistry } from 'vs/platform/actions/common/actions'; import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ILogService } from 'vs/platform/log/common/log'; import { CompletionItem, Context as SuggestContext, ISuggestItemPreselector, suggestWidgetStatusbarMenu } from './suggest'; import { SuggestAlternatives } from './suggestAlternatives'; @@ -728,44 +727,39 @@ registerEditorCommand(new SuggestCommand({ precondition: SuggestContext.Visible, handler(x) { x.acceptSelectedSuggestion(true, false); - } + }, + kbOpts: [{ + // normal tab + primary: KeyCode.Tab, + kbExpr: ContextKeyExpr.and(SuggestContext.Visible, EditorContextKeys.textInputFocus), + weight, + }, { + // accept on enter has special rules + primary: KeyCode.Enter, + kbExpr: ContextKeyExpr.and(SuggestContext.Visible, EditorContextKeys.textInputFocus, SuggestContext.AcceptSuggestionsOnEnter, SuggestContext.MakesTextEdit), + weight, + }], + menuOpts: [{ + menuId: suggestWidgetStatusbarMenu, + title: nls.localize('accept.insert', "Insert"), + group: 'left', + order: 1, + when: SuggestContext.HasInsertAndReplaceRange.toNegated() + }, { + menuId: suggestWidgetStatusbarMenu, + title: nls.localize('accept.insert', "Insert"), + group: 'left', + order: 1, + when: ContextKeyExpr.and(SuggestContext.HasInsertAndReplaceRange, SuggestContext.InsertMode.isEqualTo('insert')) + }, { + menuId: suggestWidgetStatusbarMenu, + title: nls.localize('accept.replace', "Replace"), + group: 'left', + order: 1, + when: ContextKeyExpr.and(SuggestContext.HasInsertAndReplaceRange, SuggestContext.InsertMode.isEqualTo('replace')) + }] })); -// normal tab -KeybindingsRegistry.registerKeybindingRule({ - id: 'acceptSelectedSuggestion', - when: ContextKeyExpr.and(SuggestContext.Visible, EditorContextKeys.textInputFocus), - primary: KeyCode.Tab, - weight -}); - -// accept on enter has special rules -KeybindingsRegistry.registerKeybindingRule({ - id: 'acceptSelectedSuggestion', - when: ContextKeyExpr.and(SuggestContext.Visible, EditorContextKeys.textInputFocus, SuggestContext.AcceptSuggestionsOnEnter, SuggestContext.MakesTextEdit), - primary: KeyCode.Enter, - weight, -}); - -MenuRegistry.appendMenuItem(suggestWidgetStatusbarMenu, { - command: { id: 'acceptSelectedSuggestion', title: nls.localize('accept.insert', "Insert") }, - group: 'left', - order: 1, - when: SuggestContext.HasInsertAndReplaceRange.toNegated() -}); -MenuRegistry.appendMenuItem(suggestWidgetStatusbarMenu, { - command: { id: 'acceptSelectedSuggestion', title: nls.localize('accept.insert', "Insert") }, - group: 'left', - order: 1, - when: ContextKeyExpr.and(SuggestContext.HasInsertAndReplaceRange, SuggestContext.InsertMode.isEqualTo('insert')) -}); -MenuRegistry.appendMenuItem(suggestWidgetStatusbarMenu, { - command: { id: 'acceptSelectedSuggestion', title: nls.localize('accept.replace', "Replace") }, - group: 'left', - order: 1, - when: ContextKeyExpr.and(SuggestContext.HasInsertAndReplaceRange, SuggestContext.InsertMode.isEqualTo('replace')) -}); - registerEditorCommand(new SuggestCommand({ id: 'acceptAlternativeSelectedSuggestion', precondition: ContextKeyExpr.and(SuggestContext.Visible, EditorContextKeys.textInputFocus), From 32d40cf44e893e87ac33ac4f08de1e5f7fe077fc Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 11 Mar 2022 00:51:37 +0900 Subject: [PATCH 105/175] chore: update to electron 17 (#143223) * chore: bump electron@17.0.0 * Revert "chore: revert to electron@13 (#143851)" This reverts commit df645f14506142d6b20be6f6bda6bc40286ff739. * chore: bump electron@17.1.0 * Revert "ci: fix build with latest node-gyp" This reverts commit c3e948aa30f54b0ad20f1a99627949cda4ad0c9f. * chore: revert ci changes for node v16 * chore: update yarn.lock * chore: bump electron@17.1.1 --- .github/workflows/ci.yml | 33 +-- .github/workflows/rich-navigation.yml | 15 +- .yarnrc | 2 +- build/.cachesalt | 2 +- .../darwin/product-build-darwin-sign.yml | 2 +- .../darwin/product-build-darwin.yml | 6 +- build/azure-pipelines/distro-build.yml | 2 +- build/azure-pipelines/exploration-build.yml | 2 +- .../linux/product-build-alpine.yml | 2 +- .../linux/product-build-linux-client.yml | 12 +- .../linux/product-build-linux-server.yml | 2 +- .../linux/snap-build-linux.yml | 2 +- build/azure-pipelines/product-compile.yml | 2 +- build/azure-pipelines/product-release.yml | 2 +- .../publish-types/publish-types.yml | 2 +- build/azure-pipelines/sdl-scan.yml | 8 +- .../azure-pipelines/web/product-build-web.yml | 2 +- .../win32/product-build-win32.yml | 2 +- build/lib/layersChecker.js | 18 ++ build/lib/layersChecker.ts | 18 ++ build/npm/postinstall.js | 1 + build/package.json | 2 +- build/yarn.lock | 8 +- cgmanifest.json | 12 +- extensions/configuration-editing/package.json | 2 +- extensions/configuration-editing/yarn.lock | 8 +- .../client/src/node/nodeFs.ts | 2 +- extensions/css-language-features/package.json | 2 +- .../css-language-features/server/package.json | 2 +- .../server/src/node/nodeFs.ts | 2 +- .../css-language-features/server/yarn.lock | 8 +- extensions/css-language-features/yarn.lock | 8 +- extensions/debug-auto-launch/package.json | 2 +- extensions/debug-auto-launch/yarn.lock | 8 +- extensions/debug-server-ready/package.json | 2 +- extensions/debug-server-ready/yarn.lock | 8 +- extensions/emmet/package.json | 2 +- extensions/emmet/yarn.lock | 8 +- extensions/extension-editing/package.json | 2 +- extensions/extension-editing/yarn.lock | 8 +- extensions/git-base/package.json | 2 +- extensions/git-base/yarn.lock | 8 +- extensions/git/package.json | 2 +- extensions/git/src/git.ts | 19 +- extensions/git/yarn.lock | 8 +- extensions/github-authentication/package.json | 2 +- extensions/github-authentication/yarn.lock | 8 +- extensions/github/package.json | 2 +- extensions/github/yarn.lock | 8 +- extensions/grunt/package.json | 2 +- extensions/grunt/yarn.lock | 8 +- extensions/gulp/package.json | 2 +- extensions/gulp/yarn.lock | 8 +- .../html-language-features/package.json | 2 +- .../server/package.json | 2 +- .../html-language-features/server/yarn.lock | 8 +- extensions/html-language-features/yarn.lock | 8 +- extensions/jake/package.json | 2 +- extensions/jake/yarn.lock | 8 +- .../json-language-features/package.json | 2 +- .../server/package.json | 2 +- .../server/src/node/jsonServerMain.ts | 2 +- .../json-language-features/server/yarn.lock | 8 +- extensions/json-language-features/yarn.lock | 8 +- extensions/merge-conflict/package.json | 2 +- extensions/merge-conflict/yarn.lock | 8 +- .../microsoft-authentication/package.json | 2 +- extensions/microsoft-authentication/yarn.lock | 8 +- extensions/npm/package.json | 2 +- extensions/npm/yarn.lock | 8 +- extensions/php-language-features/package.json | 2 +- extensions/php-language-features/yarn.lock | 8 +- .../typescript-language-features/package.json | 2 +- .../src/extension.ts | 2 +- .../typescript-language-features/yarn.lock | 8 +- extensions/vscode-api-tests/package.json | 2 +- extensions/vscode-api-tests/yarn.lock | 8 +- extensions/vscode-colorize-tests/package.json | 2 +- extensions/vscode-colorize-tests/yarn.lock | 8 +- .../vscode-custom-editor-tests/package.json | 2 +- .../vscode-custom-editor-tests/yarn.lock | 8 +- extensions/vscode-notebook-tests/package.json | 2 +- extensions/vscode-notebook-tests/yarn.lock | 8 +- extensions/vscode-test-resolver/package.json | 2 +- .../src/util/processes.ts | 4 +- extensions/vscode-test-resolver/yarn.lock | 8 +- package.json | 8 +- remote/.yarnrc | 2 +- remote/package.json | 2 +- remote/yarn.lock | 106 ++++++---- src/main.js | 2 - src/vs/base/node/languagePacks.js | 2 +- src/vs/base/node/pfs.ts | 6 +- .../parts/sandbox/common/electronTypes.ts | 86 ++++---- .../sandbox/electron-sandbox/electronTypes.ts | 2 +- src/vs/base/test/node/pfs/pfs.test.ts | 2 +- src/vs/code/electron-main/app.ts | 2 +- .../test/node/nativeModules.test.ts | 6 +- .../files/browser/htmlFileSystemProvider.ts | 3 +- .../issue/electron-main/issueMainService.ts | 9 +- .../electron-main/webviewMainService.ts | 10 +- .../platform/windows/electron-main/window.ts | 8 +- .../contrib/files/browser/fileImportExport.ts | 3 +- .../test/node/encoding/encoding.test.ts | 3 - test/automation/package.json | 2 +- test/automation/yarn.lock | 8 +- test/integration/browser/package.json | 2 +- test/integration/browser/yarn.lock | 8 +- test/smoke/package.json | 2 +- test/smoke/yarn.lock | 8 +- test/unit/electron/index.js | 4 - test/unit/node/index.js | 1 - yarn.lock | 195 +++++++++--------- 113 files changed, 509 insertions(+), 453 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e837bb4b72..12973f26771 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/setup-node@v2 with: - node-version: 14 + node-version: 16 - uses: actions/setup-python@v2 with: @@ -57,18 +57,7 @@ jobs: env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - run: | - # update node-gyp to latest for support in detecting VS 2022 toolchain - npm install -g node-gyp@latest - # Resolve to node-gyp.js - # Remove this once node-version > 17.4.x or > 16.14.0, - # which ships with npm > 8.4.0 that has support for VS 2022 toolchain. - $env:npm_config_node_gyp=$(Join-Path $(Get-Command node-gyp.cmd).Path "..\node_modules\node-gyp\bin\node-gyp.js" -Resolve) - # Electron <= 13 does not ship with correct config.gypi headers, - # remove this once we update to newer versions. - # Refs https://github.com/nodejs/node-gyp/pull/2497 - $env:npm_config_force_process_config="true" - yarn --frozen-lockfile --network-timeout 180000 + run: yarn --frozen-lockfile --network-timeout 180000 - name: Create node_modules archive if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} run: | @@ -124,7 +113,7 @@ jobs: - uses: actions/setup-node@v2 with: - node-version: 14 + node-version: 16 - name: Compute node modules cache key id: nodeModulesCacheKey @@ -134,8 +123,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules20-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-cacheNodeModules20- + key: ${{ runner.os }}-cacheNodeModules21-${{ steps.nodeModulesCacheKey.outputs.value }} + restore-keys: ${{ runner.os }}-cacheNodeModules21- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -196,7 +185,7 @@ jobs: - uses: actions/setup-node@v2 with: - node-version: 14 + node-version: 16 - name: Compute node modules cache key id: nodeModulesCacheKey @@ -206,8 +195,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules20-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-cacheNodeModules20- + key: ${{ runner.os }}-cacheNodeModules21-${{ steps.nodeModulesCacheKey.outputs.value }} + restore-keys: ${{ runner.os }}-cacheNodeModules21- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} @@ -270,7 +259,7 @@ jobs: - uses: actions/setup-node@v2 with: - node-version: 14 + node-version: 16 - name: Compute node modules cache key id: nodeModulesCacheKey @@ -280,8 +269,8 @@ jobs: uses: actions/cache@v2 with: path: "**/node_modules" - key: ${{ runner.os }}-cacheNodeModules20-${{ steps.nodeModulesCacheKey.outputs.value }} - restore-keys: ${{ runner.os }}-cacheNodeModules20- + key: ${{ runner.os }}-cacheNodeModules21-${{ steps.nodeModulesCacheKey.outputs.value }} + restore-keys: ${{ runner.os }}-cacheNodeModules21- - name: Get yarn cache directory path id: yarnCacheDirPath if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} diff --git a/.github/workflows/rich-navigation.yml b/.github/workflows/rich-navigation.yml index add178c1498..a154e88f61f 100644 --- a/.github/workflows/rich-navigation.yml +++ b/.github/workflows/rich-navigation.yml @@ -24,22 +24,11 @@ jobs: - uses: actions/setup-node@v2 with: - node-version: 14 + node-version: 16 - name: Install dependencies if: steps.caching-stage.outputs.cache-hit != 'true' - run: | - # update node-gyp to latest for support in detecting VS 2022 toolchain - npm install -g node-gyp@latest - # Resolve to node-gyp.js - # Remove this once node-version > 17.4.x or > 16.14.0, - # which ships with npm > 8.4.0 that has support for VS 2022 toolchain. - $env:npm_config_node_gyp=$(Join-Path $(Get-Command node-gyp.cmd).Path "..\node_modules\node-gyp\bin\node-gyp.js" -Resolve) - # Electron <= 13 does not ship with correct config.gypi headers, - # remove this once we update to newer versions. - # Refs https://github.com/nodejs/node-gyp/pull/2497 - $env:npm_config_force_process_config="true" - yarn --frozen-lockfile + run: yarn --frozen-lockfile env: CHILD_CONCURRENCY: 1 diff --git a/.yarnrc b/.yarnrc index 481bf7bfa46..01cf0e4783d 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,4 +1,4 @@ disturl "https://electronjs.org/headers" -target "13.5.2" +target "17.1.1" runtime "electron" build_from_source "true" diff --git a/build/.cachesalt b/build/.cachesalt index b33738fb265..5eb7ff93bd8 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2022-02-28T10:04:13.972Z +2022-03-02T05:48:19.264Z diff --git a/build/azure-pipelines/darwin/product-build-darwin-sign.yml b/build/azure-pipelines/darwin/product-build-darwin-sign.yml index 7d28236e2bf..e67678d9335 100644 --- a/build/azure-pipelines/darwin/product-build-darwin-sign.yml +++ b/build/azure-pipelines/darwin/product-build-darwin-sign.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 585676c9835..e0d4c43d8e3 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" @@ -79,10 +79,6 @@ steps: set -e export npm_config_arch=$(VSCODE_ARCH) export npm_config_node_gyp=$(which node-gyp) - # Electron <= 13 does not ship with correct config.gypi headers, - # remove this once we update to newer versions. - # Refs https://github.com/nodejs/node-gyp/pull/2497 - export npm_config_force_process_config=true for i in {1..3}; do # try 3 times, for Terrapin yarn --frozen-lockfile && break diff --git a/build/azure-pipelines/distro-build.yml b/build/azure-pipelines/distro-build.yml index 53b62b47a4e..307f226dc0a 100644 --- a/build/azure-pipelines/distro-build.yml +++ b/build/azure-pipelines/distro-build.yml @@ -11,7 +11,7 @@ pr: steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" diff --git a/build/azure-pipelines/exploration-build.yml b/build/azure-pipelines/exploration-build.yml index 5b6599d8dab..a80650bb92d 100644 --- a/build/azure-pipelines/exploration-build.yml +++ b/build/azure-pipelines/exploration-build.yml @@ -7,7 +7,7 @@ pr: none steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" diff --git a/build/azure-pipelines/linux/product-build-alpine.yml b/build/azure-pipelines/linux/product-build-alpine.yml index e425e670cd3..d2563b82f68 100644 --- a/build/azure-pipelines/linux/product-build-alpine.yml +++ b/build/azure-pipelines/linux/product-build-alpine.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" diff --git a/build/azure-pipelines/linux/product-build-linux-client.yml b/build/azure-pipelines/linux/product-build-linux-client.yml index 8b4b20a50ea..f44c386caf5 100644 --- a/build/azure-pipelines/linux/product-build-linux-client.yml +++ b/build/azure-pipelines/linux/product-build-linux-client.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" @@ -99,7 +99,7 @@ steps: if [ -z "$CC" ] || [ -z "$CXX" ]; then # Download clang based on chromium revision used by vscode - curl -s https://raw.githubusercontent.com/chromium/chromium/91.0.4472.164/tools/clang/scripts/update.py | python - --output-dir=$PWD/.build/CR_Clang --host-os=linux + curl -s https://raw.githubusercontent.com/chromium/chromium/98.0.4758.109/tools/clang/scripts/update.py | python - --output-dir=$PWD/.build/CR_Clang --host-os=linux # Download libcxx headers and objects from upstream electron releases DEBUG=libcxx-fetcher \ VSCODE_LIBCXX_OBJECTS_DIR=$PWD/.build/libcxx-objects \ @@ -109,12 +109,12 @@ steps: node build/linux/libcxx-fetcher.js # Set compiler toolchain # Flags for the client build are based on - # https://source.chromium.org/chromium/chromium/src/+/refs/tags/91.0.4472.164:build/config/arm.gni - # https://source.chromium.org/chromium/chromium/src/+/refs/tags/91.0.4472.164:build/config/compiler/BUILD.gn - # https://source.chromium.org/chromium/chromium/src/+/refs/tags/91.0.4472.164:build/config/c++/BUILD.gn + # https://source.chromium.org/chromium/chromium/src/+/refs/tags/98.0.4758.109:build/config/arm.gni + # https://source.chromium.org/chromium/chromium/src/+/refs/tags/98.0.4758.109:build/config/compiler/BUILD.gn + # https://source.chromium.org/chromium/chromium/src/+/refs/tags/98.0.4758.109:build/config/c++/BUILD.gn export CC=$PWD/.build/CR_Clang/bin/clang export CXX=$PWD/.build/CR_Clang/bin/clang++ - export CXXFLAGS="-nostdinc++ -D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS -D__NO_INLINE__ -isystem$PWD/.build/libcxx_headers/include -isystem$PWD/.build/libcxxabi_headers/include -fPIC -flto=thin -fsplit-lto-unit" + export CXXFLAGS="-nostdinc++ -D__NO_INLINE__ -isystem$PWD/.build/libcxx_headers -isystem$PWD/.build/libcxx_headers/include -isystem$PWD/.build/libcxxabi_headers/include -fPIC -flto=thin -fsplit-lto-unit" export LDFLAGS="-stdlib=libc++ -fuse-ld=lld -flto=thin -L$PWD/.build/libcxx-objects -lc++abi -Wl,--lto-O0" export VSCODE_REMOTE_CC=$(which gcc) export VSCODE_REMOTE_CXX=$(which g++) diff --git a/build/azure-pipelines/linux/product-build-linux-server.yml b/build/azure-pipelines/linux/product-build-linux-server.yml index ecea0861ee6..0f3bb9586f5 100644 --- a/build/azure-pipelines/linux/product-build-linux-server.yml +++ b/build/azure-pipelines/linux/product-build-linux-server.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" diff --git a/build/azure-pipelines/linux/snap-build-linux.yml b/build/azure-pipelines/linux/snap-build-linux.yml index 33a80b74391..12829334956 100644 --- a/build/azure-pipelines/linux/snap-build-linux.yml +++ b/build/azure-pipelines/linux/snap-build-linux.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: DownloadPipelineArtifact@0 displayName: "Download Pipeline Artifact" diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 44364c76bec..b3cec3a3ab1 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" diff --git a/build/azure-pipelines/product-release.yml b/build/azure-pipelines/product-release.yml index fa6396b1486..a1086945595 100644 --- a/build/azure-pipelines/product-release.yml +++ b/build/azure-pipelines/product-release.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureCLI@2 inputs: diff --git a/build/azure-pipelines/publish-types/publish-types.yml b/build/azure-pipelines/publish-types/publish-types.yml index 043bb5141ba..031fafd4c75 100644 --- a/build/azure-pipelines/publish-types/publish-types.yml +++ b/build/azure-pipelines/publish-types/publish-types.yml @@ -12,7 +12,7 @@ pool: steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - bash: | TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`) diff --git a/build/azure-pipelines/sdl-scan.yml b/build/azure-pipelines/sdl-scan.yml index 0b4e16d4570..8d685b57a38 100644 --- a/build/azure-pipelines/sdl-scan.yml +++ b/build/azure-pipelines/sdl-scan.yml @@ -47,7 +47,7 @@ stages: outputFormat: "pre" - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" @@ -139,7 +139,7 @@ stages: toolMajorVersion: "V2" - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" @@ -191,7 +191,7 @@ stages: if [ -z "$CC" ] || [ -z "$CXX" ]; then # Download clang based on chromium revision used by vscode - curl -s https://raw.githubusercontent.com/chromium/chromium/91.0.4472.164/tools/clang/scripts/update.py | python - --output-dir=$PWD/.build/CR_Clang --host-os=linux + curl -s https://raw.githubusercontent.com/chromium/chromium/96.0.4664.110/tools/clang/scripts/update.py | python - --output-dir=$PWD/.build/CR_Clang --host-os=linux # Download libcxx headers and objects from upstream electron releases DEBUG=libcxx-fetcher \ VSCODE_LIBCXX_OBJECTS_DIR=$PWD/.build/libcxx-objects \ @@ -202,7 +202,7 @@ stages: # Set compiler toolchain export CC=$PWD/.build/CR_Clang/bin/clang export CXX=$PWD/.build/CR_Clang/bin/clang++ - export CXXFLAGS="-nostdinc++ -D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS -isystem$PWD/.build/libcxx_headers/include -isystem$PWD/.build/libcxxabi_headers/include -fPIC -flto=thin -fsplit-lto-unit" + export CXXFLAGS="-nostdinc++ -D__NO_INLINE__ -isystem$PWD/.build/libcxx_headers -isystem$PWD/.build/libcxx_headers/include -isystem$PWD/.build/libcxxabi_headers/include -fPIC -flto=thin -fsplit-lto-unit" export LDFLAGS="-stdlib=libc++ -fuse-ld=lld -flto=thin -fsplit-lto-unit -L$PWD/.build/libcxx-objects -lc++abi" export VSCODE_REMOTE_CC=$(which gcc) export VSCODE_REMOTE_CXX=$(which g++) diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index aced8b3076f..a33530fd4a5 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: AzureKeyVault@1 displayName: "Azure Key Vault: Get Secrets" diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 49d2e4d7d56..344309018ae 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "14.x" + versionSpec: "16.x" - task: UsePythonVersion@0 inputs: diff --git a/build/lib/layersChecker.js b/build/lib/layersChecker.js index 021c58c17fe..9fb019ef81c 100644 --- a/build/lib/layersChecker.js +++ b/build/lib/layersChecker.js @@ -53,6 +53,21 @@ const CORE_TYPES = [ 'trimLeft', 'trimRight', 'queueMicrotask', + 'Array', + 'Uint8Array', + 'Uint16Array', + 'Uint32Array', + 'Int8Array', + 'Int16Array', + 'Int32Array', + 'Float32Array', + 'Float64Array', + 'Uint8ClampedArray', + 'BigUint64Array', + 'BigInt64Array', + 'btoa', + 'atob', + 'AbortSignal', 'MessageChannel', 'MessagePort' ]; @@ -145,6 +160,9 @@ const RULES = [ target: '**/vs/**/browser/**', allowedTypes: CORE_TYPES, disallowedTypes: NATIVE_TYPES, + allowedDefinitions: [ + '@types/node/stream/consumers.d.ts' // node.js started to duplicate types from lib.dom.d.ts so we have to account for that + ], disallowedDefinitions: [ '@types/node' // no node.js ] diff --git a/build/lib/layersChecker.ts b/build/lib/layersChecker.ts index 6a860200085..a31873d2ac8 100644 --- a/build/lib/layersChecker.ts +++ b/build/lib/layersChecker.ts @@ -54,6 +54,21 @@ const CORE_TYPES = [ 'trimLeft', 'trimRight', 'queueMicrotask', + 'Array', + 'Uint8Array', + 'Uint16Array', + 'Uint32Array', + 'Int8Array', + 'Int16Array', + 'Int32Array', + 'Float32Array', + 'Float64Array', + 'Uint8ClampedArray', + 'BigUint64Array', + 'BigInt64Array', + 'btoa', + 'atob', + 'AbortSignal', 'MessageChannel', 'MessagePort' ]; @@ -158,6 +173,9 @@ const RULES = [ target: '**/vs/**/browser/**', allowedTypes: CORE_TYPES, disallowedTypes: NATIVE_TYPES, + allowedDefinitions: [ + '@types/node/stream/consumers.d.ts' // node.js started to duplicate types from lib.dom.d.ts so we have to account for that + ], disallowedDefinitions: [ '@types/node' // no node.js ] diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index 9751651f122..2e809b1f233 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -61,6 +61,7 @@ for (let dir of dirs) { if (process.env['VSCODE_REMOTE_CC']) { env['CC'] = process.env['VSCODE_REMOTE_CC']; } if (process.env['VSCODE_REMOTE_CXX']) { env['CXX'] = process.env['VSCODE_REMOTE_CXX']; } if (process.env['CXXFLAGS']) { delete env['CXXFLAGS']; } + if (process.env['CFLAGS']) { delete env['CFLAGS']; } if (process.env['LDFLAGS']) { delete env['LDFLAGS']; } if (process.env['VSCODE_REMOTE_NODE_GYP']) { env['npm_config_node_gyp'] = process.env['VSCODE_REMOTE_NODE_GYP']; } diff --git a/build/package.json b/build/package.json index 456b7e87ed5..eb85be5acaf 100644 --- a/build/package.json +++ b/build/package.json @@ -29,7 +29,7 @@ "@types/minimist": "^1.2.1", "@types/mkdirp": "^1.0.1", "@types/mocha": "^8.2.0", - "@types/node": "14.x", + "@types/node": "16.x", "@types/p-limit": "^2.2.0", "@types/plist": "^3.0.2", "@types/pump": "^1.0.1", diff --git a/build/yarn.lock b/build/yarn.lock index 13d05a4352c..925ed369f62 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -507,10 +507,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb" integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/p-limit@^2.2.0": version "2.2.0" diff --git a/cgmanifest.json b/cgmanifest.json index 407e42c7d81..73a12fa107a 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "chromium", "repositoryUrl": "https://chromium.googlesource.com/chromium/src", - "commitHash": "8a33e05d162c4f39afa2dcb150e8c2548aa4ccea" + "commitHash": "cbadbe267bec5c3c673d5a2f2fdef15541f5bfc1" } }, "licenseDetail": [ @@ -40,7 +40,7 @@ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ], "isOnlyProductionDependency": true, - "version": "91.0.4472.164" + "version": "98.0.4758.109" }, { "component": { @@ -48,11 +48,11 @@ "git": { "name": "nodejs", "repositoryUrl": "https://github.com/nodejs/node", - "commitHash": "bd60e93357a118204ea238d94e7a9e4209d93062" + "commitHash": "40ecd5601193c316e62e9216e8a4259130686208" } }, "isOnlyProductionDependency": true, - "version": "14.16.0" + "version": "16.13.0" }, { "component": { @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "2727847acabd39933ccd95b92f2c12454c0a24e7" + "commitHash": "d35270ebb1dc5e1b8efcc19f4b5623ebd6f6a471" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "13.5.2" + "version": "17.1.1" }, { "component": { diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index 685de8e280a..0b501ce9d04 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -144,7 +144,7 @@ ] }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "repository": { "type": "git", diff --git a/extensions/configuration-editing/yarn.lock b/extensions/configuration-editing/yarn.lock index d4882d39e4b..f7ac959fc09 100644 --- a/extensions/configuration-editing/yarn.lock +++ b/extensions/configuration-editing/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== jsonc-parser@^2.2.1: version "2.2.1" diff --git a/extensions/css-language-features/client/src/node/nodeFs.ts b/extensions/css-language-features/client/src/node/nodeFs.ts index 0b572018884..e0d3f9e1403 100644 --- a/extensions/css-language-features/client/src/node/nodeFs.ts +++ b/extensions/css-language-features/client/src/node/nodeFs.ts @@ -14,7 +14,7 @@ export function getNodeFSRequestService(): RequestService { } } return { - getContent(location: string, encoding?: string) { + getContent(location: string, encoding?: BufferEncoding) { ensureFileUri(location); return new Promise((c, e) => { const uri = Uri.parse(location); diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json index bd8db6d0259..202fe248ad9 100644 --- a/extensions/css-language-features/package.json +++ b/extensions/css-language-features/package.json @@ -852,7 +852,7 @@ "vscode-uri": "^3.0.3" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "repository": { "type": "git", diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index 63dee355923..f0e40cec7bd 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -16,7 +16,7 @@ }, "devDependencies": { "@types/mocha": "^8.2.0", - "@types/node": "14.x" + "@types/node": "16.x" }, "scripts": { "compile": "gulp compile-extension:css-language-features-server", diff --git a/extensions/css-language-features/server/src/node/nodeFs.ts b/extensions/css-language-features/server/src/node/nodeFs.ts index c72617e3af1..35e55622dc9 100644 --- a/extensions/css-language-features/server/src/node/nodeFs.ts +++ b/extensions/css-language-features/server/src/node/nodeFs.ts @@ -16,7 +16,7 @@ export function getNodeFSRequestService(): RequestService { } } return { - getContent(location: string, encoding?: string) { + getContent(location: string, encoding?: BufferEncoding) { ensureFileUri(location); return new Promise((c, e) => { const uri = Uri.parse(location); diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index ab6b163aee2..fdc1e37513d 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== vscode-css-languageservice@^5.1.13: version "5.1.13" diff --git a/extensions/css-language-features/yarn.lock b/extensions/css-language-features/yarn.lock index 0875cabea4d..60ba7c2dcc3 100644 --- a/extensions/css-language-features/yarn.lock +++ b/extensions/css-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== balanced-match@^1.0.0: version "1.0.0" diff --git a/extensions/debug-auto-launch/package.json b/extensions/debug-auto-launch/package.json index b0c765fa2cc..82c9054c456 100644 --- a/extensions/debug-auto-launch/package.json +++ b/extensions/debug-auto-launch/package.json @@ -36,7 +36,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "prettier": { "printWidth": 100, diff --git a/extensions/debug-auto-launch/yarn.lock b/extensions/debug-auto-launch/yarn.lock index f7a30098ef4..22c406bc73f 100644 --- a/extensions/debug-auto-launch/yarn.lock +++ b/extensions/debug-auto-launch/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/debug-server-ready/package.json b/extensions/debug-server-ready/package.json index 64aa227aa53..29cee88c0c5 100644 --- a/extensions/debug-server-ready/package.json +++ b/extensions/debug-server-ready/package.json @@ -153,7 +153,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "repository": { "type": "git", diff --git a/extensions/debug-server-ready/yarn.lock b/extensions/debug-server-ready/yarn.lock index f7a30098ef4..22c406bc73f 100644 --- a/extensions/debug-server-ready/yarn.lock +++ b/extensions/debug-server-ready/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 4b303046a26..659be1e0fce 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -500,7 +500,7 @@ "deps": "yarn add @vscode/emmet-helper" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "dependencies": { "@emmetio/abbreviation": "^2.2.0", diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index b62efc8c7a2..955f10670ee 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -60,10 +60,10 @@ resolved "https://registry.yarnpkg.com/@emmetio/stream-reader/-/stream-reader-2.2.0.tgz#46cffea119a0a003312a21c2d9b5628cb5fcd442" integrity sha1-Rs/+oRmgoAMxKiHC2bVijLX81EI= -"@types/node@14.x": - version "14.18.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.0.tgz#98df2397f6936bfbff4f089e40e06fa5dd88d32a" - integrity sha512-0GeIl2kmVMXEnx8tg1SlG6Gg8vkqirrW752KqolYo1PHevhhZN3bhJ67qHj+bQaINhX0Ra3TlWwRvMCd9iEfNQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@vscode/emmet-helper@^2.3.0": version "2.8.4" diff --git a/extensions/extension-editing/package.json b/extensions/extension-editing/package.json index dbc18aa142b..abceee2bc7d 100644 --- a/extensions/extension-editing/package.json +++ b/extensions/extension-editing/package.json @@ -68,7 +68,7 @@ }, "devDependencies": { "@types/markdown-it": "0.0.2", - "@types/node": "14.x" + "@types/node": "16.x" }, "repository": { "type": "git", diff --git a/extensions/extension-editing/yarn.lock b/extensions/extension-editing/yarn.lock index 171c0baaa6f..ac87f5e2686 100644 --- a/extensions/extension-editing/yarn.lock +++ b/extensions/extension-editing/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.2.tgz#5d9ad19e6e6508cdd2f2596df86fd0aade598660" integrity sha1-XZrRnm5lCM3S8llt+G/Qqt5ZhmA= -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/node@^6.0.46": version "6.0.78" diff --git a/extensions/git-base/package.json b/extensions/git-base/package.json index 3fc19c587ff..acc95e1316c 100644 --- a/extensions/git-base/package.json +++ b/extensions/git-base/package.json @@ -102,7 +102,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "repository": { "type": "git", diff --git a/extensions/git-base/yarn.lock b/extensions/git-base/yarn.lock index 22e3e094fdc..3244e2ea667 100644 --- a/extensions/git-base/yarn.lock +++ b/extensions/git-base/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.17.33" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.33.tgz#011ee28e38dc7aee1be032ceadf6332a0ab15b12" - integrity sha512-noEeJ06zbn3lOh4gqe2v7NMGS33jrulfNqYFDjjEbhpDEHR5VTxgYNQSBqBlJIsBJW3uEYDgD6kvMnrrhGzq8g== +"@types/node@16.x": + version "16.11.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.21.tgz#474d7589a30afcf5291f59bd49cca9ad171ffde4" + integrity sha512-Pf8M1XD9i1ksZEcCP8vuSNwooJ/bZapNmIzpmsMaL+jMI+8mEYU3PKvs+xDNuQcJWF/x24WzY4qxLtB0zNow9A== vscode-nls@^4.0.0: version "4.1.2" diff --git a/extensions/git/package.json b/extensions/git/package.json index 73fd380e91d..dbf2f8ffc87 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -2467,7 +2467,7 @@ "@types/byline": "4.2.31", "@types/file-type": "^5.2.1", "@types/mocha": "^8.2.0", - "@types/node": "14.x", + "@types/node": "16.x", "@types/which": "^1.0.28" }, "repository": { diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 0e71140326e..39ed6847423 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -7,6 +7,7 @@ import { promises as fs, exists, realpath } from 'fs'; import * as path from 'path'; import * as os from 'os'; import * as cp from 'child_process'; +import { fileURLToPath } from 'url'; import * as which from 'which'; import { EventEmitter } from 'events'; import * as iconv from '@vscode/iconv-lite-umd'; @@ -605,13 +606,27 @@ export class Git { GIT_PAGER: 'cat' }); - if (options.cwd) { - options.cwd = sanitizePath(options.cwd); + const cwd = this.getCwd(options); + if (cwd) { + options.cwd = sanitizePath(cwd); } return cp.spawn(this.path, args, options); } + private getCwd(options: SpawnOptions): string | undefined { + const cwd = options.cwd; + if (typeof cwd === 'undefined' || typeof cwd === 'string') { + return cwd; + } + + if (cwd.protocol === 'file:') { + return fileURLToPath(cwd); + } + + return undefined; + } + private log(output: string): void { this._onOutput.emit('log', output); } diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock index 8c832b81988..f69be195555 100644 --- a/extensions/git/yarn.lock +++ b/extensions/git/yarn.lock @@ -26,10 +26,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb" integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/which@^1.0.28": version "1.0.28" diff --git a/extensions/github-authentication/package.json b/extensions/github-authentication/package.json index 3b232bbaaf3..5d6627698f3 100644 --- a/extensions/github-authentication/package.json +++ b/extensions/github-authentication/package.json @@ -65,7 +65,7 @@ "vscode-tas-client": "^0.1.31" }, "devDependencies": { - "@types/node": "14.x", + "@types/node": "16.x", "@types/node-fetch": "^2.5.7", "@types/uuid": "8.0.0" }, diff --git a/extensions/github-authentication/yarn.lock b/extensions/github-authentication/yarn.lock index 557bd53b837..52663b01ef9 100644 --- a/extensions/github-authentication/yarn.lock +++ b/extensions/github-authentication/yarn.lock @@ -15,10 +15,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.5.tgz#3d03acd3b3414cf67faf999aed11682ed121f22b" integrity sha512-90hiq6/VqtQgX8Sp0EzeIsv3r+ellbGj4URKj5j30tLlZvRUpnAe9YbYnjl3pJM93GyXU0tghHhvXHq+5rnCKA== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/uuid@8.0.0": version "8.0.0" diff --git a/extensions/github/package.json b/extensions/github/package.json index 7c0013fd7a8..f86f98683af 100644 --- a/extensions/github/package.json +++ b/extensions/github/package.json @@ -80,7 +80,7 @@ "vscode-nls": "^4.1.2" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "repository": { "type": "git", diff --git a/extensions/github/yarn.lock b/extensions/github/yarn.lock index fabc2469c44..9933736b08e 100644 --- a/extensions/github/yarn.lock +++ b/extensions/github/yarn.lock @@ -99,10 +99,10 @@ dependencies: "@types/node" ">= 8" -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/node@>= 8": version "14.0.23" diff --git a/extensions/grunt/package.json b/extensions/grunt/package.json index 7e5c605ec00..8dd9eced530 100644 --- a/extensions/grunt/package.json +++ b/extensions/grunt/package.json @@ -20,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/grunt/yarn.lock b/extensions/grunt/yarn.lock index f7a30098ef4..22c406bc73f 100644 --- a/extensions/grunt/yarn.lock +++ b/extensions/grunt/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/gulp/package.json b/extensions/gulp/package.json index 995da7fbe5d..8352957083e 100644 --- a/extensions/gulp/package.json +++ b/extensions/gulp/package.json @@ -20,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/gulp/yarn.lock b/extensions/gulp/yarn.lock index f7a30098ef4..22c406bc73f 100644 --- a/extensions/gulp/yarn.lock +++ b/extensions/gulp/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/html-language-features/package.json b/extensions/html-language-features/package.json index 5f348e11286..20fd71e95ae 100644 --- a/extensions/html-language-features/package.json +++ b/extensions/html-language-features/package.json @@ -267,7 +267,7 @@ "vscode-uri": "^3.0.3" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "repository": { "type": "git", diff --git a/extensions/html-language-features/server/package.json b/extensions/html-language-features/server/package.json index 0b26ed646a2..1bac84c7561 100644 --- a/extensions/html-language-features/server/package.json +++ b/extensions/html-language-features/server/package.json @@ -18,7 +18,7 @@ }, "devDependencies": { "@types/mocha": "^8.2.0", - "@types/node": "14.x" + "@types/node": "16.x" }, "scripts": { "compile": "npx gulp compile-extension:html-language-features-server", diff --git a/extensions/html-language-features/server/yarn.lock b/extensions/html-language-features/server/yarn.lock index 5ef1243cf83..2ca47c7c4e6 100644 --- a/extensions/html-language-features/server/yarn.lock +++ b/extensions/html-language-features/server/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== vscode-css-languageservice@^5.1.13: version "5.1.13" diff --git a/extensions/html-language-features/yarn.lock b/extensions/html-language-features/yarn.lock index 5a834689bfa..f9db6d421a7 100644 --- a/extensions/html-language-features/yarn.lock +++ b/extensions/html-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@vscode/extension-telemetry@0.4.6": version "0.4.6" diff --git a/extensions/jake/package.json b/extensions/jake/package.json index 4bb8793f3ee..0e5ebc4ea8b 100644 --- a/extensions/jake/package.json +++ b/extensions/jake/package.json @@ -20,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/jake/yarn.lock b/extensions/jake/yarn.lock index f7a30098ef4..22c406bc73f 100644 --- a/extensions/jake/yarn.lock +++ b/extensions/jake/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/json-language-features/package.json b/extensions/json-language-features/package.json index 983230c2928..520cb43cb5a 100644 --- a/extensions/json-language-features/package.json +++ b/extensions/json-language-features/package.json @@ -147,7 +147,7 @@ "vscode-nls": "^5.0.0" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "repository": { "type": "git", diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index ab5a28f62b7..65cd7dc407c 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -20,7 +20,7 @@ }, "devDependencies": { "@types/mocha": "^8.2.0", - "@types/node": "14.x" + "@types/node": "16.x" }, "scripts": { "prepublishOnly": "npm run clean && npm run compile", diff --git a/extensions/json-language-features/server/src/node/jsonServerMain.ts b/extensions/json-language-features/server/src/node/jsonServerMain.ts index 4cb387095aa..ad1ae439e59 100644 --- a/extensions/json-language-features/server/src/node/jsonServerMain.ts +++ b/extensions/json-language-features/server/src/node/jsonServerMain.ts @@ -36,7 +36,7 @@ function getHTTPRequestService(): RequestService { function getFileRequestService(): RequestService { return { - getContent(location: string, encoding?: string) { + getContent(location: string, encoding?: BufferEncoding) { return new Promise((c, e) => { const uri = Uri.parse(location); fs.readFile(uri.fsPath, encoding, (err, buf) => { diff --git a/extensions/json-language-features/server/yarn.lock b/extensions/json-language-features/server/yarn.lock index ae20eed06c0..20cebe1fe27 100644 --- a/extensions/json-language-features/server/yarn.lock +++ b/extensions/json-language-features/server/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== jsonc-parser@^3.0.0: version "3.0.0" diff --git a/extensions/json-language-features/yarn.lock b/extensions/json-language-features/yarn.lock index 9f393dd5453..5315a0e5315 100644 --- a/extensions/json-language-features/yarn.lock +++ b/extensions/json-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@vscode/extension-telemetry@0.4.6": version "0.4.6" diff --git a/extensions/merge-conflict/package.json b/extensions/merge-conflict/package.json index 3aa6b16014d..128538a8ad9 100644 --- a/extensions/merge-conflict/package.json +++ b/extensions/merge-conflict/package.json @@ -159,7 +159,7 @@ "vscode-nls": "^5.0.0" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "repository": { "type": "git", diff --git a/extensions/merge-conflict/yarn.lock b/extensions/merge-conflict/yarn.lock index ede1d9c7736..699f1238a9b 100644 --- a/extensions/merge-conflict/yarn.lock +++ b/extensions/merge-conflict/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== vscode-nls@^5.0.0: version "5.0.0" diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json index aed500cc870..82fecbf5e91 100644 --- a/extensions/microsoft-authentication/package.json +++ b/extensions/microsoft-authentication/package.json @@ -47,7 +47,7 @@ "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, "devDependencies": { - "@types/node": "14.x", + "@types/node": "16.x", "@types/node-fetch": "^2.5.7", "@types/randombytes": "^2.0.0", "@types/sha.js": "^2.4.0", diff --git a/extensions/microsoft-authentication/yarn.lock b/extensions/microsoft-authentication/yarn.lock index ca07545f9e3..459cfdb7324 100644 --- a/extensions/microsoft-authentication/yarn.lock +++ b/extensions/microsoft-authentication/yarn.lock @@ -15,10 +15,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.23.tgz#676fa0883450ed9da0bb24156213636290892806" integrity sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/randombytes@^2.0.0": version "2.0.0" diff --git a/extensions/npm/package.json b/extensions/npm/package.json index b674260dd5b..6df1a4835e7 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -28,7 +28,7 @@ }, "devDependencies": { "@types/minimatch": "^3.0.3", - "@types/node": "14.x", + "@types/node": "16.x", "@types/which": "^2.0.0" }, "resolutions": { diff --git a/extensions/npm/yarn.lock b/extensions/npm/yarn.lock index 4728dbc860c..bba9ffdbf39 100644 --- a/extensions/npm/yarn.lock +++ b/extensions/npm/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/which@^2.0.0": version "2.0.0" diff --git a/extensions/php-language-features/package.json b/extensions/php-language-features/package.json index 03176a05573..8c0d484535b 100644 --- a/extensions/php-language-features/package.json +++ b/extensions/php-language-features/package.json @@ -78,7 +78,7 @@ "which": "^2.0.2" }, "devDependencies": { - "@types/node": "14.x", + "@types/node": "16.x", "@types/which": "^2.0.0" }, "repository": { diff --git a/extensions/php-language-features/yarn.lock b/extensions/php-language-features/yarn.lock index 09b31c80123..8dec3aadc63 100644 --- a/extensions/php-language-features/yarn.lock +++ b/extensions/php-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/which@^2.0.0": version "2.0.0" diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 15e218f5683..74feda84ac4 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -41,7 +41,7 @@ "vscode-uri": "^3.0.3" }, "devDependencies": { - "@types/node": "14.x", + "@types/node": "16.x", "@types/semver": "^5.5.0" }, "scripts": { diff --git a/extensions/typescript-language-features/src/extension.ts b/extensions/typescript-language-features/src/extension.ts index 523b4c840c3..e6ae13e5daa 100644 --- a/extensions/typescript-language-features/src/extension.ts +++ b/extensions/typescript-language-features/src/extension.ts @@ -66,5 +66,5 @@ export function activate( } export function deactivate() { - fs.rmdirSync(temp.getInstanceTempDir(), { recursive: true }); + fs.rmSync(temp.getInstanceTempDir(), { recursive: true, force: true }); } diff --git a/extensions/typescript-language-features/yarn.lock b/extensions/typescript-language-features/yarn.lock index 40d17f3173a..d388994e0bc 100644 --- a/extensions/typescript-language-features/yarn.lock +++ b/extensions/typescript-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/semver@^5.5.0": version "5.5.0" diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 7e7be57a43b..abe4aff2dc3 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -199,7 +199,7 @@ }, "devDependencies": { "@types/mocha": "^8.2.0", - "@types/node": "14.x" + "@types/node": "16.x" }, "repository": { "type": "git", diff --git a/extensions/vscode-api-tests/yarn.lock b/extensions/vscode-api-tests/yarn.lock index b54d6b48836..13c5c61dbd9 100644 --- a/extensions/vscode-api-tests/yarn.lock +++ b/extensions/vscode-api-tests/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== diff --git a/extensions/vscode-colorize-tests/package.json b/extensions/vscode-colorize-tests/package.json index b27439bf8b6..e2517c811f2 100644 --- a/extensions/vscode-colorize-tests/package.json +++ b/extensions/vscode-colorize-tests/package.json @@ -20,7 +20,7 @@ "jsonc-parser": "2.2.1" }, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "contributes": { "semanticTokenTypes": [ diff --git a/extensions/vscode-colorize-tests/yarn.lock b/extensions/vscode-colorize-tests/yarn.lock index 15725cff502..44d4327771e 100644 --- a/extensions/vscode-colorize-tests/yarn.lock +++ b/extensions/vscode-colorize-tests/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== jsonc-parser@2.2.1: version "2.2.1" diff --git a/extensions/vscode-custom-editor-tests/package.json b/extensions/vscode-custom-editor-tests/package.json index 778f5c56cf0..1a17bd5d6cb 100644 --- a/extensions/vscode-custom-editor-tests/package.json +++ b/extensions/vscode-custom-editor-tests/package.json @@ -22,7 +22,7 @@ }, "devDependencies": { "@types/mocha": "^8.2.0", - "@types/node": "14.x", + "@types/node": "16.x", "@types/p-limit": "^2.2.0" }, "contributes": { diff --git a/extensions/vscode-custom-editor-tests/yarn.lock b/extensions/vscode-custom-editor-tests/yarn.lock index 52588b92820..2943060a078 100644 --- a/extensions/vscode-custom-editor-tests/yarn.lock +++ b/extensions/vscode-custom-editor-tests/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.3.tgz#bbeb55fbc73f28ea6de601fbfa4613f58d785323" integrity sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/p-limit@^2.2.0": version "2.2.0" diff --git a/extensions/vscode-notebook-tests/package.json b/extensions/vscode-notebook-tests/package.json index 3cf93067634..e0a672ca179 100644 --- a/extensions/vscode-notebook-tests/package.json +++ b/extensions/vscode-notebook-tests/package.json @@ -33,7 +33,7 @@ }, "dependencies": {}, "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "contributes": { "commands": [ diff --git a/extensions/vscode-notebook-tests/yarn.lock b/extensions/vscode-notebook-tests/yarn.lock index 995b2c2f8b3..e724e7fffa3 100644 --- a/extensions/vscode-notebook-tests/yarn.lock +++ b/extensions/vscode-notebook-tests/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json index 37fdefbfe2a..da90e7e3809 100644 --- a/extensions/vscode-test-resolver/package.json +++ b/extensions/vscode-test-resolver/package.json @@ -32,7 +32,7 @@ ], "main": "./out/extension", "devDependencies": { - "@types/node": "14.x" + "@types/node": "16.x" }, "capabilities": { "untrustedWorkspaces": { diff --git a/extensions/vscode-test-resolver/src/util/processes.ts b/extensions/vscode-test-resolver/src/util/processes.ts index 3bc12725522..f16d0678c52 100644 --- a/extensions/vscode-test-resolver/src/util/processes.ts +++ b/extensions/vscode-test-resolver/src/util/processes.ts @@ -16,14 +16,14 @@ export function terminateProcess(p: cp.ChildProcess, extensionPath: string): Ter const options: any = { stdio: ['pipe', 'pipe', 'ignore'] }; - cp.execFileSync('taskkill', ['/T', '/F', '/PID', p.pid.toString()], options); + cp.execFileSync('taskkill', ['/T', '/F', '/PID', p.pid!.toString()], options); } catch (err) { return { success: false, error: err }; } } else if (process.platform === 'darwin' || process.platform === 'linux') { try { const cmd = path.join(extensionPath, 'scripts', 'terminateProcess.sh'); - const result = cp.spawnSync(cmd, [p.pid.toString()]); + const result = cp.spawnSync(cmd, [p.pid!.toString()]); if (result.error) { return { success: false, error: result.error }; } diff --git a/extensions/vscode-test-resolver/yarn.lock b/extensions/vscode-test-resolver/yarn.lock index 995b2c2f8b3..e724e7fffa3 100644 --- a/extensions/vscode-test-resolver/yarn.lock +++ b/extensions/vscode-test-resolver/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== diff --git a/package.json b/package.json index 183eb42597b..5950607e6e9 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "@parcel/watcher": "2.0.5", "@vscode/iconv-lite-umd": "0.7.0", "@vscode/ripgrep": "^1.14.2", - "@vscode/sqlite3": "4.0.12", + "@vscode/sqlite3": "5.0.7", "@vscode/sudo-prompt": "9.3.1", "@vscode/vscode-languagedetection": "1.0.21", "applicationinsights": "1.4.2", @@ -71,7 +71,7 @@ "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.3", "jschardet": "3.0.0", - "keytar": "7.6.0", + "keytar": "7.9.0", "minimist": "^1.2.5", "native-is-elevated": "0.4.3", "native-keymap": "3.3.0", @@ -108,7 +108,7 @@ "@types/keytar": "^4.4.0", "@types/minimist": "^1.2.1", "@types/mocha": "^8.2.0", - "@types/node": "14.x", + "@types/node": "16.x", "@types/sinon": "^10.0.2", "@types/sinon-test": "^2.4.2", "@types/trusted-types": "^1.0.6", @@ -135,7 +135,7 @@ "cssnano": "^4.1.11", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "13.5.2", + "electron": "17.1.1", "eslint": "8.7.0", "eslint-plugin-header": "3.1.1", "eslint-plugin-jsdoc": "^19.1.0", diff --git a/remote/.yarnrc b/remote/.yarnrc index 7ee8b67ae99..1df1b5f2441 100644 --- a/remote/.yarnrc +++ b/remote/.yarnrc @@ -1,4 +1,4 @@ disturl "http://nodejs.org/dist" -target "14.16.0" +target "16.13.0" runtime "node" build_from_source "true" diff --git a/remote/package.json b/remote/package.json index 896b5292e41..9713259516a 100644 --- a/remote/package.json +++ b/remote/package.json @@ -14,7 +14,7 @@ "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.3", "jschardet": "3.0.0", - "keytar": "7.6.0", + "keytar": "7.9.0", "minimist": "^1.2.5", "native-watchdog": "1.4.0", "node-pty": "0.11.0-beta11", diff --git a/remote/yarn.lock b/remote/yarn.lock index 48a2ef7b2d6..c8aec72a423 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -285,12 +285,12 @@ debug@^4.3.1: dependencies: ms "2.1.2" -decompress-response@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" - integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== dependencies: - mimic-response "^2.0.0" + mimic-response "^3.1.0" deep-extend@^0.6.0: version "0.6.0" @@ -302,10 +302,10 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +detect-libc@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" + integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== diagnostic-channel-publishers@^0.3.3: version "0.3.5" @@ -476,18 +476,25 @@ jschardet@3.0.0: resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882" integrity sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ== -keytar@7.6.0: - version "7.6.0" - resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.6.0.tgz#498e796443cb543d31722099443f29d7b5c44100" - integrity sha512-H3cvrTzWb11+iv0NOAnoNAPgEapVZnYLVHZQyxmh7jdmVfR/c0jNNFEZ6AI38W/4DeTGTaY66ZX4Z1SbfKPvCQ== +keytar@7.9.0: + version "7.9.0" + resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb" + integrity sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ== dependencies: - node-addon-api "^3.0.0" - prebuild-install "^6.0.0" + node-addon-api "^4.3.0" + prebuild-install "^7.0.1" -mimic-response@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" - integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" @@ -536,23 +543,28 @@ native-watchdog@1.4.0: resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.4.0.tgz#547a1f9f88754c38089c622d405ed1e324c7a545" integrity sha512-4FynAeGtTpoQ2+5AxVJXGEGsOzPsNYDh8Xmawjgs7YWJe+bbbgt7CYlA/Qx6X+kwtN5Ey1aNSm9MqZa0iNKkGw== -node-abi@^2.21.0: - version "2.30.1" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.30.1.tgz#c437d4b1fe0e285aaf290d45b45d4d7afedac4cf" - integrity sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w== +node-abi@^3.3.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.8.0.tgz#679957dc8e7aa47b0a02589dbfde4f77b29ccb32" + integrity sha512-tzua9qWWi7iW4I42vUPKM+SfaF0vQSLAm4yO5J83mSwB7GeoWrDKC/K+8YCnYNwqP5duwazbw2X9l4m8SC2cUw== dependencies: - semver "^5.4.1" - -node-addon-api@^3.0.0, node-addon-api@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" - integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== + semver "^7.3.5" node-addon-api@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.1.0.tgz#98b21931557466c6729e51cb77cd39c965f42239" integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw== +node-addon-api@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" + integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== + +node-addon-api@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + node-gyp-build@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" @@ -597,22 +609,22 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= -prebuild-install@^6.0.0: - version "6.1.4" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.1.4.tgz#ae3c0142ad611d58570b89af4986088a4937e00f" - integrity sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ== +prebuild-install@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.0.1.tgz#c10075727c318efe72412f333e0ef625beaf3870" + integrity sha512-QBSab31WqkyxpnMWQxubYAHR5S9B2+r81ucocew34Fkl98FhvKIF50jIJnNOBmAZfyNV7vE5T6gd3hTVWgY6tg== dependencies: - detect-libc "^1.0.3" + detect-libc "^2.0.0" expand-template "^2.0.3" github-from-package "0.0.0" minimist "^1.2.3" mkdirp-classic "^0.5.3" napi-build-utils "^1.0.1" - node-abi "^2.21.0" + node-abi "^3.3.0" npmlog "^4.0.1" pump "^3.0.0" rc "^1.2.7" - simple-get "^3.0.3" + simple-get "^4.0.0" tar-fs "^2.0.0" tunnel-agent "^0.6.0" @@ -686,6 +698,13 @@ semver@^5.4.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -706,12 +725,12 @@ simple-concat@^1.0.0: resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== -simple-get@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" - integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== +simple-get@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== dependencies: - decompress-response "^4.2.0" + decompress-response "^6.0.0" once "^1.3.1" simple-concat "^1.0.0" @@ -925,6 +944,11 @@ xterm@4.19.0-beta.2: resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.19.0-beta.2.tgz#abc63abba8ee5e3dec88f4ebae13b8198151acbf" integrity sha512-pi9hUmkwRbOOJlbG5pNiTDaBXNsTq2+Kh6V7cs9i7j8sW3QMDk66dc/ZFNh0293/U987u87NdFWljD/V+g068g== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yauzl@^2.9.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" diff --git a/src/main.js b/src/main.js index 9419e5ae33f..c9347d4516b 100644 --- a/src/main.js +++ b/src/main.js @@ -26,8 +26,6 @@ const { stripComments } = require('./vs/base/common/stripComments'); const product = require('../product.json'); const { app, protocol, crashReporter } = require('electron'); -app.allowRendererProcessReuse = false; - // Enable portable support const portable = bootstrapNode.configurePortable(product); diff --git a/src/vs/base/node/languagePacks.js b/src/vs/base/node/languagePacks.js index 5c14fade878..f99d3808de5 100644 --- a/src/vs/base/node/languagePacks.js +++ b/src/vs/base/node/languagePacks.js @@ -46,7 +46,7 @@ * @returns {Promise} */ function rimraf(location) { - return new Promise((c, e) => fs.rmdir(location, { recursive: true }, err => (err && err.code !== 'ENOENT') ? e(err) : c())); + return new Promise((c, e) => fs.rm(location, { recursive: true, force: true, maxRetries: 3 }, err => err ? e(err) : c())); } /** diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index c04d2722df6..2283c4a61d6 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -43,7 +43,7 @@ async function rimraf(path: string, mode = RimRafMode.UNLINK): Promise { throw new Error('rimraf - will refuse to recursively delete root'); } - // delete: via rmDir + // delete: via rm if (mode === RimRafMode.UNLINK) { return rimrafUnlink(path); } @@ -79,7 +79,7 @@ async function rimrafMove(path: string): Promise { } async function rimrafUnlink(path: string): Promise { - return Promises.rmdir(path, { recursive: true, maxRetries: 3 }); + return promisify(fs.rm)(path, { recursive: true, force: true, maxRetries: 3 }); } export function rimrafSync(path: string): void { @@ -87,7 +87,7 @@ export function rimrafSync(path: string): void { throw new Error('rimraf - will refuse to recursively delete root'); } - fs.rmdirSync(path, { recursive: true }); + fs.rmSync(path, { recursive: true, force: true, maxRetries: 3 }); } //#endregion diff --git a/src/vs/base/parts/sandbox/common/electronTypes.ts b/src/vs/base/parts/sandbox/common/electronTypes.ts index 01622e6bbab..d2d75da87ce 100644 --- a/src/vs/base/parts/sandbox/common/electronTypes.ts +++ b/src/vs/base/parts/sandbox/common/electronTypes.ts @@ -7,11 +7,10 @@ // ####################################################################### // ### ### // ### electron.d.ts types we need in a common layer for reuse ### -// ### (copied from Electron 11.x) ### +// ### (copied from Electron 16.x) ### // ### ### // ####################################################################### - export interface MessageBoxOptions { /** * Content of the message box. @@ -34,6 +33,13 @@ export interface MessageBoxOptions { * the message box opens. */ defaultId?: number; + /** + * Pass an instance of AbortSignal to optionally close the message box, the message + * box will behave as if it was cancelled by the user. On macOS, `signal` does not + * work with message boxes that do not have a parent window, since those message + * boxes run synchronously due to platform limitations. + */ + signal?: AbortSignal; /** * Title of the message box, some platforms will not show it. */ @@ -50,7 +56,12 @@ export interface MessageBoxOptions { * Initial checked state of the checkbox. `false` by default. */ checkboxChecked?: boolean; - // icon?: NativeImage; + /** + * Custom width of the text in the message box. + * + * @platform darwin + */ + textWidth?: number; /** * The index of the button to be used to cancel the dialog, via the `Esc` key. By * default this is assigned to the first button with "cancel" or "no" as the label. @@ -88,21 +99,10 @@ export interface MessageBoxReturnValue { checkboxChecked: boolean; } -export interface OpenDevToolsOptions { - /** - * Opens the devtools with specified dock state, can be `right`, `bottom`, - * `undocked`, `detach`. Defaults to last used dock state. In `undocked` mode it's - * possible to dock back. In `detach` mode it's not. - */ - mode: ('right' | 'bottom' | 'undocked' | 'detach'); - /** - * Whether to bring the opened devtools window to the foreground. The default is - * `true`. - */ - activate?: boolean; -} - export interface SaveDialogOptions { + /** + * The dialog title. Cannot be displayed on some _Linux_ desktop environments. + */ title?: string; /** * Absolute directory path, absolute file path, or file name to use by default. @@ -143,6 +143,25 @@ export interface SaveDialogOptions { securityScopedBookmarks?: boolean; } +export interface SaveDialogReturnValue { + /** + * whether or not the dialog was canceled. + */ + canceled: boolean; + /** + * If the dialog is canceled, this will be `undefined`. + */ + filePath?: string; + /** + * Base64 encoded string which contains the security scoped bookmark data for the + * saved file. `securityScopedBookmarks` must be enabled for this to be present. + * (For return values, see table here.) + * + * @platform darwin,mas + */ + bookmark?: string; +} + export interface OpenDialogOptions { title?: string; defaultPath?: string; @@ -191,25 +210,6 @@ export interface OpenDialogReturnValue { bookmarks?: string[]; } -export interface SaveDialogReturnValue { - /** - * whether or not the dialog was canceled. - */ - canceled: boolean; - /** - * If the dialog is canceled, this will be `undefined`. - */ - filePath?: string; - /** - * Base64 encoded string which contains the security scoped bookmark data for the - * saved file. `securityScopedBookmarks` must be enabled for this to be present. - * (For return values, see table here.) - * - * @platform darwin,mas - */ - bookmark?: string; -} - export interface FileFilter { // Docs: https://electronjs.org/docs/api/structures/file-filter @@ -218,6 +218,20 @@ export interface FileFilter { name: string; } +export interface OpenDevToolsOptions { + /** + * Opens the devtools with specified dock state, can be `right`, `bottom`, + * `undocked`, `detach`. Defaults to last used dock state. In `undocked` mode it's + * possible to dock back. In `detach` mode it's not. + */ + mode: ('right' | 'bottom' | 'undocked' | 'detach'); + /** + * Whether to bring the opened devtools window to the foreground. The default is + * `true`. + */ + activate?: boolean; +} + export interface InputEvent { // Docs: https://electronjs.org/docs/api/structures/input-event diff --git a/src/vs/base/parts/sandbox/electron-sandbox/electronTypes.ts b/src/vs/base/parts/sandbox/electron-sandbox/electronTypes.ts index 8f36cb6f045..58589dbec1d 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/electronTypes.ts +++ b/src/vs/base/parts/sandbox/electron-sandbox/electronTypes.ts @@ -7,7 +7,7 @@ // ####################################################################### // ### ### // ### electron.d.ts types we expose from electron-sandbox ### -// ### (copied from Electron 11.x) ### +// ### (copied from Electron 16.x) ### // ### ### // ####################################################################### diff --git a/src/vs/base/test/node/pfs/pfs.test.ts b/src/vs/base/test/node/pfs/pfs.test.ts index 09bc57bf432..e45782e236f 100644 --- a/src/vs/base/test/node/pfs/pfs.test.ts +++ b/src/vs/base/test/node/pfs/pfs.test.ts @@ -273,7 +273,7 @@ flakySuite('PFS', function () { const linkTarget = await Promises.readlink(targetLinkMD5JSFolderLinked); assert.strictEqual(linkTarget, targetLinkMD5JSFolder); - await Promises.rmdir(targetLinkTestFolder, { recursive: true }); + await Promises.rm(targetLinkTestFolder); } // Copy with `preserveSymlinks: false` and verify result diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 21f6f2b27da..1a0e05a9c2a 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -275,7 +275,7 @@ export class CodeApplication extends Disposable { //#region Code Cache - type SessionWithCodeCachePathSupport = typeof Session & { + type SessionWithCodeCachePathSupport = Session & { /** * Sets code cache directory. By default, the directory will be `Code Cache` under * the respective user data folder. diff --git a/src/vs/platform/environment/test/node/nativeModules.test.ts b/src/vs/platform/environment/test/node/nativeModules.test.ts index 89177b4d0ee..6b7dfad6741 100644 --- a/src/vs/platform/environment/test/node/nativeModules.test.ts +++ b/src/vs/platform/environment/test/node/nativeModules.test.ts @@ -35,12 +35,12 @@ flakySuite('Native Modules (all platforms)', () => { assert.ok(typeof watchDog.start === 'function', testErrorMessage('native-watchdog')); }); - test('node-pty', async () => { + (process.type === 'renderer' ? test.skip /* TODO@electron module is not context aware yet and thus cannot load in Electron renderer used by tests */ : test)('node-pty', async () => { const nodePty = await import('node-pty'); assert.ok(typeof nodePty.spawn === 'function', testErrorMessage('node-pty')); }); - test('spdlog', async () => { + (process.type === 'renderer' ? test.skip /* TODO@electron module is not context aware yet and thus cannot load in Electron renderer used by tests */ : test)('spdlog', async () => { const spdlog = await import('spdlog'); assert.ok(typeof spdlog.createRotatingLogger === 'function', testErrorMessage('spdlog')); assert.ok(typeof spdlog.version === 'number', testErrorMessage('spdlog')); @@ -109,7 +109,7 @@ flakySuite('Native Modules (all platforms)', () => { (!isWindows ? suite.skip : suite)('Native Modules (Windows)', () => { - test('windows-mutex', async () => { + (process.type === 'renderer' ? test.skip /* TODO@electron module is not context aware yet and thus cannot load in Electron renderer used by tests */ : test)('windows-mutex', async () => { const mutex = await import('windows-mutex'); assert.ok(mutex && typeof mutex.isActive === 'function', testErrorMessage('windows-mutex')); assert.ok(typeof mutex.isActive === 'function', testErrorMessage('windows-mutex')); diff --git a/src/vs/platform/files/browser/htmlFileSystemProvider.ts b/src/vs/platform/files/browser/htmlFileSystemProvider.ts index 34a91c39cbe..bdde288717f 100644 --- a/src/vs/platform/files/browser/htmlFileSystemProvider.ts +++ b/src/vs/platform/files/browser/htmlFileSystemProvider.ts @@ -144,7 +144,8 @@ export class HTMLFileSystemProvider implements IFileSystemProviderWithFileReadWr // Entire file else { - const reader: ReadableStreamDefaultReader = file.stream().getReader(); + // TODO@electron: duplicate type definitions originate from `@types/node/stream/consumers.d.ts` + const reader: ReadableStreamDefaultReader = (file.stream() as unknown as ReadableStream).getReader(); let res = await reader.read(); while (!res.done) { diff --git a/src/vs/platform/issue/electron-main/issueMainService.ts b/src/vs/platform/issue/electron-main/issueMainService.ts index 2e6b1fadec5..828e7ae65b3 100644 --- a/src/vs/platform/issue/electron-main/issueMainService.ts +++ b/src/vs/platform/issue/electron-main/issueMainService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { BrowserWindow, Display, ipcMain, IpcMainEvent, screen } from 'electron'; +import { BrowserWindow, BrowserWindowConstructorOptions, Display, ipcMain, IpcMainEvent, screen } from 'electron'; import { arch, release, type } from 'os'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { DisposableStore } from 'vs/base/common/lifecycle'; @@ -337,10 +337,11 @@ export class IssueMainService implements ICommonIssueService { nativeWindowOpen: true, zoomFactor: zoomLevelToZoomFactor(options.zoomLevel), sandbox: true, - contextIsolation: true, + contextIsolation: true }, - alwaysOnTop: options.alwaysOnTop - }); + alwaysOnTop: options.alwaysOnTop, + experimentalDarkMode: true + } as BrowserWindowConstructorOptions & { experimentalDarkMode: boolean }); window.setMenuBarVisibility(false); diff --git a/src/vs/platform/webview/electron-main/webviewMainService.ts b/src/vs/platform/webview/electron-main/webviewMainService.ts index 350768d61a4..9b51a3a8b37 100644 --- a/src/vs/platform/webview/electron-main/webviewMainService.ts +++ b/src/vs/platform/webview/electron-main/webviewMainService.ts @@ -50,8 +50,10 @@ export class WebviewMainService extends Disposable implements IWebviewManagerSer public async findInFrame(windowId: WebviewWindowId, frameName: string, text: string, options: { findNext?: boolean; forward?: boolean }): Promise { const initialFrame = this.getFrameByName(windowId, frameName); - type WebFrameMainWithFindSupport = typeof WebFrameMain & { + type WebFrameMainWithFindSupport = WebFrameMain & { findInFrame?(text: string, findOptions: FindInFrameOptions): void; + on(event: 'found-in-frame', listener: Function): WebFrameMain; + removeListener(event: 'found-in-frame', listener: Function): WebFrameMain; }; const frame = initialFrame as unknown as WebFrameMainWithFindSupport; if (typeof frame.findInFrame === 'function') { @@ -62,17 +64,17 @@ export class WebviewMainService extends Disposable implements IWebviewManagerSer const foundInFrameHandler = (_: unknown, result: FoundInFrameResult) => { if (result.finalUpdate) { this._onFoundInFrame.fire(result); - initialFrame.removeListener('found-in-frame', foundInFrameHandler); + frame.removeListener('found-in-frame', foundInFrameHandler); } }; - initialFrame.on('found-in-frame', foundInFrameHandler); + frame.on('found-in-frame', foundInFrameHandler); } } public async stopFindInFrame(windowId: WebviewWindowId, frameName: string, options: { keepSelection?: boolean }): Promise { const initialFrame = this.getFrameByName(windowId, frameName); - type WebFrameMainWithFindSupport = typeof WebFrameMain & { + type WebFrameMainWithFindSupport = WebFrameMain & { stopFindInFrame?(stopOption: 'keepSelection' | 'clearSelection'): void; }; diff --git a/src/vs/platform/windows/electron-main/window.ts b/src/vs/platform/windows/electron-main/window.ts index 319206f946a..b6fe6d5f906 100644 --- a/src/vs/platform/windows/electron-main/window.ts +++ b/src/vs/platform/windows/electron-main/window.ts @@ -175,7 +175,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { const windowSettings = this.configurationService.getValue('window'); - const options: BrowserWindowConstructorOptions = { + const options: BrowserWindowConstructorOptions & { experimentalDarkMode: boolean } = { width: this.windowState.width, height: this.windowState.height, x: this.windowState.x, @@ -193,6 +193,9 @@ export class CodeWindow extends Disposable implements ICodeWindow { spellcheck: false, nativeWindowOpen: true, zoomFactor: zoomLevelToZoomFactor(windowSettings?.zoomLevel), + // Enable experimental css highlight api https://chromestatus.com/feature/5436441440026624 + // Refs https://github.com/microsoft/vscode/issues/140098 + enableBlinkFeatures: 'HighlightAPI', ...this.environmentMainService.sandbox ? // Sandbox @@ -205,7 +208,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { nodeIntegration: true, contextIsolation: false } - } + }, + experimentalDarkMode: true }; // Apply icon to window diff --git a/src/vs/workbench/contrib/files/browser/fileImportExport.ts b/src/vs/workbench/contrib/files/browser/fileImportExport.ts index aa35e3e270b..08fdd59d803 100644 --- a/src/vs/workbench/contrib/files/browser/fileImportExport.ts +++ b/src/vs/workbench/contrib/files/browser/fileImportExport.ts @@ -317,7 +317,8 @@ export class BrowserFileUpload { // Read the file in chunks using File.stream() web APIs try { - const reader: ReadableStreamDefaultReader = file.stream().getReader(); + // TODO@electron: duplicate type definitions originate from `@types/node/stream/consumers.d.ts` + const reader: ReadableStreamDefaultReader = (file.stream() as unknown as ReadableStream).getReader(); let res = await reader.read(); while (!res.done) { diff --git a/src/vs/workbench/services/textfile/test/node/encoding/encoding.test.ts b/src/vs/workbench/services/textfile/test/node/encoding/encoding.test.ts index 58ecba3461d..feca56101de 100644 --- a/src/vs/workbench/services/textfile/test/node/encoding/encoding.test.ts +++ b/src/vs/workbench/services/textfile/test/node/encoding/encoding.test.ts @@ -322,9 +322,6 @@ suite('Encoding', () => { }); test('toDecodeStream - decodes buffer entirely', async function () { - if (!process.versions.electron) { - this.skip(); // TODO@bpasero enable once we ship Electron 16 - } const emojis = Buffer.from('🖥️💻💾'); const incompleteEmojis = emojis.slice(0, emojis.length - 1); diff --git a/test/automation/package.json b/test/automation/package.json index 0c9f304d98c..7a7b3c5a560 100644 --- a/test/automation/package.json +++ b/test/automation/package.json @@ -29,7 +29,7 @@ "devDependencies": { "@types/mkdirp": "^1.0.1", "@types/ncp": "2.0.1", - "@types/node": "14.x", + "@types/node": "16.x", "@types/tmp": "0.2.2", "cpx2": "3.0.0", "npm-run-all": "^4.1.5", diff --git a/test/automation/yarn.lock b/test/automation/yarn.lock index d2311cbb4f1..b5ccab17e0f 100644 --- a/test/automation/yarn.lock +++ b/test/automation/yarn.lock @@ -21,10 +21,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.1.tgz#3b5c3a26393c19b400844ac422bd0f631a94d69d" integrity sha512-aK9jxMypeSrhiYofWWBf/T7O+KwaiAHzM4sveCdWPn71lzUSMimRnKzhXDKfKwV1kWoBo2P1aGgaIYGLf9/ljw== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/tmp@0.2.2": version "0.2.2" diff --git a/test/integration/browser/package.json b/test/integration/browser/package.json index 594808bf0d7..446c8b69e5f 100644 --- a/test/integration/browser/package.json +++ b/test/integration/browser/package.json @@ -8,7 +8,7 @@ }, "devDependencies": { "@types/mkdirp": "^1.0.1", - "@types/node": "14.x", + "@types/node": "16.x", "@types/optimist": "0.0.29", "@types/rimraf": "^2.0.4", "@types/tmp": "0.1.0", diff --git a/test/integration/browser/yarn.lock b/test/integration/browser/yarn.lock index a5682ee9a90..b3498682cd8 100644 --- a/test/integration/browser/yarn.lock +++ b/test/integration/browser/yarn.lock @@ -33,10 +33,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.0.tgz#b417deda18cf8400f278733499ad5547ed1abec4" integrity sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/optimist@0.0.29": version "0.0.29" diff --git a/test/smoke/package.json b/test/smoke/package.json index 98e25ed8745..e0e9c671d83 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -21,7 +21,7 @@ "@types/mkdirp": "^1.0.1", "@types/mocha": "^8.2.0", "@types/ncp": "2.0.1", - "@types/node": "14.x", + "@types/node": "16.x", "@types/node-fetch": "^2.5.10", "@types/rimraf": "3.0.2", "npm-run-all": "^4.1.5", diff --git a/test/smoke/yarn.lock b/test/smoke/yarn.lock index 136ea693019..7eda3e418f9 100644 --- a/test/smoke/yarn.lock +++ b/test/smoke/yarn.lock @@ -58,10 +58,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b" integrity sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/rimraf@3.0.2": version "3.0.2" diff --git a/test/unit/electron/index.js b/test/unit/electron/index.js index f5dc37d1093..2c3ad1ab9fc 100644 --- a/test/unit/electron/index.js +++ b/test/unit/electron/index.js @@ -20,10 +20,6 @@ const net = require('net'); const createStatsCollector = require('mocha/lib/stats-collector'); const { applyReporter, importMochaReporter } = require('../reporter'); -// Disable render process reuse, we still have -// non-context aware native modules in the renderer. -app.allowRendererProcessReuse = false; - const optimist = require('optimist') .describe('grep', 'only run tests matching ').alias('grep', 'g').alias('grep', 'f').string('grep') .describe('run', 'only run tests from ').string('run') diff --git a/test/unit/node/index.js b/test/unit/node/index.js index 12b9e021ca3..d59ff18c3f5 100644 --- a/test/unit/node/index.js +++ b/test/unit/node/index.js @@ -30,7 +30,6 @@ const excludeModules = [ 'vs/base/parts/storage/test/node/storage.test.js', // same as above, due to direct dependency to sqlite native module 'vs/workbench/contrib/testing/test/common/testResultStorage.test.js', // TODO@connor4312 https://github.com/microsoft/vscode/issues/137853 'vs/workbench/contrib/testing/test/common/testResultService.test.js', // TODO@connor4312 https://github.com/microsoft/vscode/issues/137853 - 'vs/platform/files/test/common/files.test.js' // TODO@bpasero enable once we ship Electron 16 ]; /** diff --git a/yarn.lock b/yarn.lock index 2b99fa1349d..4e4a101bbfd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -683,23 +683,6 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d" integrity sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g== -"@electron/get@^1.0.1": - version "1.12.3" - resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.12.3.tgz#fa2723385c4b565a34c4c82f46087aa2a5fbf6d0" - integrity sha512-NFwSnVZQK7dhOYF1NQCt+HGqgL1aNdj0LUSx75uCqnZJqyiWCVdAMFV4b4/kC8HjUJAnsvdSEmjEt4G2qNQ9+Q== - dependencies: - debug "^4.1.1" - env-paths "^2.2.0" - filenamify "^4.1.0" - fs-extra "^8.1.0" - got "^9.6.0" - progress "^2.0.3" - semver "^6.2.0" - sumchecker "^3.0.1" - optionalDependencies: - global-agent "^2.0.2" - global-tunnel-ng "^2.7.1" - "@electron/get@^1.12.4": version "1.13.0" resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.13.0.tgz#95c6bcaff4f9a505ea46792424f451efea89228c" @@ -716,6 +699,22 @@ global-agent "^2.0.2" global-tunnel-ng "^2.7.1" +"@electron/get@^1.13.0": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.13.1.tgz#42a0aa62fd1189638bd966e23effaebb16108368" + integrity sha512-U5vkXDZ9DwXtkPqlB45tfYnnYBN8PePp1z/XDCupnSpdrxT8/ThCv9WCwPLf9oqiSGZTkH6dx2jDUPuoXpjkcA== + dependencies: + debug "^4.1.1" + env-paths "^2.2.0" + fs-extra "^8.1.0" + got "^9.6.0" + progress "^2.0.3" + semver "^6.2.0" + sumchecker "^3.0.1" + optionalDependencies: + global-agent "^3.0.0" + global-tunnel-ng "^2.7.1" + "@eslint/eslintrc@^1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" @@ -1308,10 +1307,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-4.2.22.tgz#cf488a0f6b4a9c245d09927f4f757ca278b9c8ce" integrity sha512-LXRap3bb4AjtLZ5NOFc4ssVZrQPTgdPcNm++0SEJuJZaOA+xHkojJNYqy33A5q/94BmG5tA6yaMeD4VdCv5aSA== -"@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== +"@types/node@16.x": + version "16.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/node@^10.11.7": version "10.12.21" @@ -1569,12 +1568,12 @@ https-proxy-agent "^5.0.0" proxy-from-env "^1.1.0" -"@vscode/sqlite3@4.0.12": - version "4.0.12" - resolved "https://registry.yarnpkg.com/@vscode/sqlite3/-/sqlite3-4.0.12.tgz#50b36c788b5d130c02612b27eaf6905dc2156a43" - integrity sha512-45Nbq4vgUhcejdDkX/G9K5BMMgRkBqtHtbChbvXHesMfk88USt4i94i9EM0DfHO7ijl3oIwGqzIob6lgeYi41w== +"@vscode/sqlite3@5.0.7": + version "5.0.7" + resolved "https://registry.yarnpkg.com/@vscode/sqlite3/-/sqlite3-5.0.7.tgz#358df36bb0e9e735c54785e3e4b9b2dce1d32895" + integrity sha512-NlsOf+Hir2r4zopI1qMvzWXPwPJuFscirkmFTniTAT24Yz2FWcyZxzK7UT8iSNiTqOCPz48yF55ZVHaz7tTuVQ== dependencies: - nan "2.14.2" + node-addon-api "^4.2.0" "@vscode/sudo-prompt@9.3.1": version "9.3.1" @@ -3893,12 +3892,12 @@ decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" -decompress-response@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" - integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== dependencies: - mimic-response "^2.0.0" + mimic-response "^3.1.0" decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" @@ -4090,10 +4089,10 @@ detect-indent@^5.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +detect-libc@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" + integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== detect-newline@^2.0.0: version "2.1.0" @@ -4298,12 +4297,12 @@ electron-to-chromium@^1.4.17: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.45.tgz#cf1144091d6683cbd45a231954a745f02fb24598" integrity sha512-czF9eYVuOmlY/vxyMQz2rGlNSjZpxNQYBe1gmQv7al171qOIhgyO9k7D5AKlgeTCSPKk+LHhj5ZyIdmEub9oNg== -electron@13.5.2: - version "13.5.2" - resolved "https://registry.yarnpkg.com/electron/-/electron-13.5.2.tgz#5c5826e58a5e12bb5ca8047b789d07b45260ecbc" - integrity sha512-CPakwDpy5m8dL0383F5uJboQcVtn9bT/+6/wdDKo8LuTUO9aER1TF41v7feZgZW2c+UwoGPWa814ElSQ3qta2A== +electron@17.1.1: + version "17.1.1" + resolved "https://registry.yarnpkg.com/electron/-/electron-17.1.1.tgz#a936907faf68a0a4ae24e8f79c8b22995661c54b" + integrity sha512-S+PIsCOfxB+9DkPsbnWpbLQx6+3P5FGedCeVQ/vhZEX8zD4Wj2F118HGFX6ShEfsaTYE623ESK/f+b2ueHpEpQ== dependencies: - "@electron/get" "^1.0.1" + "@electron/get" "^1.13.0" "@types/node" "^14.6.2" extract-zip "^1.0.3" @@ -5117,20 +5116,6 @@ file-uri-to-path@1.0.0: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== -filename-reserved-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" - integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= - -filenamify@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-4.2.0.tgz#c99716d676869585b3b5d328b3f06590d032e89f" - integrity sha512-pkgE+4p7N1n7QieOopmn3TqJaefjdWXwEkj2XLZJLKfOgcQKkn11ahvGNgTD8mLggexLiDFQxeTs14xVU22XPA== - dependencies: - filename-reserved-regex "^2.0.0" - strip-outer "^1.0.1" - trim-repeated "^1.0.0" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -5649,6 +5634,18 @@ global-agent@^2.0.2: semver "^7.3.2" serialize-error "^7.0.1" +global-agent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-3.0.0.tgz#ae7cd31bd3583b93c5a16437a1afe27cc33a1ab6" + integrity sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q== + dependencies: + boolean "^3.0.1" + es6-error "^4.1.1" + matcher "^3.0.0" + roarr "^2.15.3" + semver "^7.3.2" + serialize-error "^7.0.1" + global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -7232,13 +7229,13 @@ keygrip@~1.1.0: dependencies: tsscmp "1.0.6" -keytar@7.6.0: - version "7.6.0" - resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.6.0.tgz#498e796443cb543d31722099443f29d7b5c44100" - integrity sha512-H3cvrTzWb11+iv0NOAnoNAPgEapVZnYLVHZQyxmh7jdmVfR/c0jNNFEZ6AI38W/4DeTGTaY66ZX4Z1SbfKPvCQ== +keytar@7.9.0: + version "7.9.0" + resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb" + integrity sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ== dependencies: - node-addon-api "^3.0.0" - prebuild-install "^6.0.0" + node-addon-api "^4.3.0" + prebuild-install "^7.0.1" keyv@^3.0.0: version "3.1.0" @@ -7901,10 +7898,10 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -mimic-response@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" - integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" @@ -8144,7 +8141,7 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@2.14.2, nan@^2.12.1, nan@^2.13.2: +nan@^2.12.1, nan@^2.13.2: version "2.14.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== @@ -8242,23 +8239,33 @@ nise@^5.1.0: just-extend "^4.0.2" path-to-regexp "^1.7.0" -node-abi@^2.21.0: - version "2.30.1" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.30.1.tgz#c437d4b1fe0e285aaf290d45b45d4d7afedac4cf" - integrity sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w== +node-abi@^3.3.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.8.0.tgz#679957dc8e7aa47b0a02589dbfde4f77b29ccb32" + integrity sha512-tzua9qWWi7iW4I42vUPKM+SfaF0vQSLAm4yO5J83mSwB7GeoWrDKC/K+8YCnYNwqP5duwazbw2X9l4m8SC2cUw== dependencies: - semver "^5.4.1" - -node-addon-api@^3.0.0, node-addon-api@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" - integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== + semver "^7.3.5" node-addon-api@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.1.0.tgz#98b21931557466c6729e51cb77cd39c965f42239" integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw== +node-addon-api@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" + integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== + +node-addon-api@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.2.0.tgz#117cbb5a959dff0992e1c586ae0393573e4d2a87" + integrity sha512-eazsqzwG2lskuzBqCGPi7Ac2UgOoMz8JVOXVhTvvPDYhthvNpefx8jWD8Np7Gv+2Sz0FlPWZk0nJV0z598Wn8Q== + +node-addon-api@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + node-fetch@^2.6.0, node-fetch@^2.6.1: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -9485,22 +9492,22 @@ postcss-value-parser@^4.0.2: picocolors "^0.2.1" source-map "^0.6.1" -prebuild-install@^6.0.0: - version "6.1.4" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.1.4.tgz#ae3c0142ad611d58570b89af4986088a4937e00f" - integrity sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ== +prebuild-install@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.0.1.tgz#c10075727c318efe72412f333e0ef625beaf3870" + integrity sha512-QBSab31WqkyxpnMWQxubYAHR5S9B2+r81ucocew34Fkl98FhvKIF50jIJnNOBmAZfyNV7vE5T6gd3hTVWgY6tg== dependencies: - detect-libc "^1.0.3" + detect-libc "^2.0.0" expand-template "^2.0.3" github-from-package "0.0.0" minimist "^1.2.3" mkdirp-classic "^0.5.3" napi-build-utils "^1.0.1" - node-abi "^2.21.0" + node-abi "^3.3.0" npmlog "^4.0.1" pump "^3.0.0" rc "^1.2.7" - simple-get "^3.0.3" + simple-get "^4.0.0" tar-fs "^2.0.0" tunnel-agent "^0.6.0" @@ -10381,12 +10388,12 @@ simple-concat@^1.0.0: resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== -simple-get@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" - integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== +simple-get@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== dependencies: - decompress-response "^4.2.0" + decompress-response "^6.0.0" once "^1.3.1" simple-concat "^1.0.0" @@ -10942,13 +10949,6 @@ strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -strip-outer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" - integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== - dependencies: - escape-string-regexp "^1.0.2" - style-loader@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.0.0.tgz#1d5296f9165e8e2c85d24eee0b7caf9ec8ca1f82" @@ -11377,13 +11377,6 @@ tree-kill@^1.2.2: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== -trim-repeated@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" - integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= - dependencies: - escape-string-regexp "^1.0.2" - ts-loader@^9.2.7: version "9.2.7" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.7.tgz#948654099ca96992b62ec47bd9cee5632006e101" From d7b5c1a10859d3c0ede85db0336209e620445d87 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 10 Mar 2022 17:17:19 +0100 Subject: [PATCH 106/175] Towards having multiple extension hosts of the same `ExtensionHostKind` --- .../browser/webWorkerExtensionHost.ts | 5 +- .../common/abstractExtensionService.ts | 88 ++++++++++--------- .../extensions/common/extensionHostManager.ts | 36 ++++---- .../services/extensions/common/extensions.ts | 6 ++ .../extensions/common/remoteExtensionHost.ts | 5 +- .../localProcessExtensionHost.ts | 5 +- 6 files changed, 86 insertions(+), 59 deletions(-) diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index 2503a9db881..e9a47781a81 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -30,6 +30,7 @@ import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { FileAccess } from 'vs/base/common/network'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { parentOriginHash } from 'vs/workbench/browser/webview'; +import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; export interface IWebWorkerExtensionHostInitData { readonly autoStart: boolean; @@ -45,6 +46,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost public readonly kind = ExtensionHostKind.LocalWebWorker; public readonly remoteAuthority = null; public readonly lazyStart: boolean; + public readonly extensions = new ExtensionDescriptionRegistry([]); private readonly _onDidExit = this._register(new Emitter<[number, string | null]>()); public readonly onExit: Event<[number, string | null]> = this._onDidExit.event; @@ -265,6 +267,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost private async _createExtHostInitData(): Promise { const [telemetryInfo, initData] = await Promise.all([this._telemetryService.getTelemetryInfo(), this._initDataProvider.getInitData()]); const workspace = this._contextService.getWorkspace(); + this.extensions.deltaExtensions(initData.extensions, []); return { commit: this._productService.commit, version: this._productService.version, @@ -288,7 +291,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost }, resolvedExtensions: [], hostExtensions: [], - extensions: initData.extensions, + extensions: this.extensions.getAllExtensionDescriptions(), telemetryInfo, logLevel: this._logService.getLevel(), logsLocation: this._extensionHostLogsLocation, diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 1a047e67240..09ac90c2fb2 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -15,7 +15,7 @@ import { IWebExtensionsScannerService, IWorkbenchExtensionEnablementService } fr import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { ActivationTimes, ExtensionPointContribution, IExtensionService, IExtensionsStatus, IMessage, IWillActivateEvent, IResponsiveStateChangeEvent, toExtension, IExtensionHost, ActivationKind, ExtensionHostKind, toExtensionDescription, ExtensionRunningLocation, extensionHostKindToString, ExtensionActivationReason, IInternalExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { ActivationTimes, ExtensionPointContribution, IExtensionService, IExtensionsStatus, IMessage, IWillActivateEvent, IResponsiveStateChangeEvent, toExtension, IExtensionHost, ActivationKind, ExtensionHostKind, toExtensionDescription, ExtensionRunningLocation, extensionHostKindToString, ExtensionActivationReason, IInternalExtensionService, RemoteRunningLocation, LocalProcessRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionMessageCollector, ExtensionPoint, ExtensionsRegistry, IExtensionPoint, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; import { ResponsiveState } from 'vs/workbench/services/extensions/common/rpcProtocol'; @@ -275,6 +275,15 @@ export abstract class AbstractExtensionService extends Disposable implements IEx return null; } + protected _getExtensionHostManagerByRunningLocation(runningLocation: ExtensionRunningLocation): IExtensionHostManager | null { + for (const extensionHostManager of this._extensionHostManagers) { + if (extensionHostManager.representsRunningLocation(runningLocation)) { + return extensionHostManager; + } + } + return null; + } + //#region deltaExtensions private async _handleDeltaExtensions(item: DeltaExtensionsQueueItem): Promise { @@ -374,47 +383,37 @@ export abstract class AbstractExtensionService extends Disposable implements IEx } private async _updateExtensionsOnExtHosts(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise { - const groupedToRemove: ExtensionIdentifier[][] = []; - const groupRemove = (extensionHostKind: ExtensionHostKind) => { - groupedToRemove[extensionHostKind] = _filterByRunningLocation(toRemove, extId => extId, this._runningLocation, extensionHostKind); - }; - groupRemove(ExtensionHostKind.LocalProcess); - groupRemove(ExtensionHostKind.LocalWebWorker); - groupRemove(ExtensionHostKind.Remote); + + // Remove old running location + const removedRunningLocation = new Map(); for (const extensionId of toRemove) { - this._runningLocation.delete(ExtensionIdentifier.toKey(extensionId)); + const extensionKey = ExtensionIdentifier.toKey(extensionId); + removedRunningLocation.set(extensionKey, this._runningLocation.get(extensionKey) || null); + this._runningLocation.delete(extensionKey); } - const groupedToAdd: IExtensionDescription[][] = []; - const groupAdd = (extensionHostKind: ExtensionHostKind) => { - groupedToAdd[extensionHostKind] = filterByRunningLocation(toAdd, this._runningLocation, extensionHostKind); - }; + // Determine new running location for (const extension of toAdd) { const extensionKind = this._getExtensionKind(extension); const isRemote = extension.extensionLocation.scheme === Schemas.vscodeRemote; const runningLocation = this._pickRunningLocation(extension.identifier, extensionKind, !isRemote, isRemote, ExtensionRunningPreference.None); this._runningLocation.set(ExtensionIdentifier.toKey(extension.identifier), runningLocation); } - groupAdd(ExtensionHostKind.LocalProcess); - groupAdd(ExtensionHostKind.LocalWebWorker); - groupAdd(ExtensionHostKind.Remote); - - const promises: Promise[] = []; - - for (const extensionHostKind of [ExtensionHostKind.LocalProcess, ExtensionHostKind.LocalWebWorker, ExtensionHostKind.Remote]) { - const toAdd = groupedToAdd[extensionHostKind]; - const toRemove = groupedToRemove[extensionHostKind]; - if (toAdd.length > 0 || toRemove.length > 0) { - const extensionHostManager = this._getExtensionHostManager(extensionHostKind); - if (extensionHostManager) { - promises.push(extensionHostManager.deltaExtensions(toAdd, toRemove)); - } - } - } + const promises = this._extensionHostManagers.map( + extHostManager => this._updateExtensionsOnExtHost(extHostManager, toAdd, toRemove, removedRunningLocation) + ); await Promise.all(promises); } + private async _updateExtensionsOnExtHost(extensionHostManager: IExtensionHostManager, toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[], removedRunningLocation: Map): Promise { + const localToAdd = filterByExtensionHostManager(toAdd, this._runningLocation, extensionHostManager); + const localToRemove = _filterByExtensionHostManager(toRemove, extId => extId, removedRunningLocation, extensionHostManager); + if (localToRemove.length > 0 || localToAdd.length > 0) { + await extensionHostManager.deltaExtensions(localToAdd, localToRemove); + } + } + public canAddExtension(extension: IExtensionDescription): boolean { const existing = this._registry.getExtensionDescription(extension.identifier); if (existing) { @@ -558,34 +557,31 @@ export abstract class AbstractExtensionService extends Disposable implements IEx this._onExtensionHostExit(exitCode); } - private findTestExtensionHost(testLocation: URI): IExtensionHostManager | undefined | null { - let extensionHostKind: ExtensionHostKind | undefined; + private findTestExtensionHost(testLocation: URI): IExtensionHostManager | null { + let runningLocation: ExtensionRunningLocation | null = null; for (const extension of this._registry.getAllExtensionDescriptions()) { if (isEqualOrParent(testLocation, extension.extensionLocation)) { - const runningLocation = this._runningLocation.get(ExtensionIdentifier.toKey(extension.identifier)); - if (runningLocation) { - extensionHostKind = runningLocation.type; - } + runningLocation = this._runningLocation.get(ExtensionIdentifier.toKey(extension.identifier)) || null; break; } } - if (extensionHostKind === undefined) { + if (runningLocation === null) { // not sure if we should support that, but it was possible to have an test outside an extension if (testLocation.scheme === Schemas.vscodeRemote) { - extensionHostKind = ExtensionHostKind.Remote; + runningLocation = new RemoteRunningLocation(); } else { // When a debugger attaches to the extension host, it will surface all console.log messages from the extension host, // but not necessarily from the window. So it would be best if any errors get printed to the console of the extension host. // That is why here we use the local process extension host even for non-file URIs - extensionHostKind = ExtensionHostKind.LocalProcess; + runningLocation = new LocalProcessRunningLocation(); } } - if (extensionHostKind !== undefined) { - return this._getExtensionHostManager(extensionHostKind); + if (runningLocation !== null) { + return this._getExtensionHostManagerByRunningLocation(runningLocation); } - return undefined; + return null; } private _releaseBarrier(): void { @@ -1250,3 +1246,13 @@ function _filterByRunningLocation(extensions: T[], extId: (item: T) => Extens return (extRunningLocation && extRunningLocation.type === desiredExtensionHostKind); }); } + +function filterByExtensionHostManager(extensions: IExtensionDescription[], runningLocation: Map, extensionHostManager: IExtensionHostManager): IExtensionDescription[] { + return _filterByExtensionHostManager(extensions, ext => ext.identifier, runningLocation, extensionHostManager); +} +function _filterByExtensionHostManager(extensions: T[], extId: (item: T) => ExtensionIdentifier, runningLocation: Map, extensionHostManager: IExtensionHostManager): T[] { + return extensions.filter((ext) => { + const extRunningLocation = runningLocation.get(ExtensionIdentifier.toKey(extId(ext))); + return (extRunningLocation && extensionHostManager.representsRunningLocation(extRunningLocation)); + }); +} diff --git a/src/vs/workbench/services/extensions/common/extensionHostManager.ts b/src/vs/workbench/services/extensions/common/extensionHostManager.ts index 72400588d16..ae7c07645ec 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostManager.ts @@ -19,7 +19,7 @@ import { registerAction2, Action2 } from 'vs/platform/actions/common/actions'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { StopWatch } from 'vs/base/common/stopwatch'; import { VSBuffer } from 'vs/base/common/buffer'; -import { IExtensionHost, ExtensionHostKind, ActivationKind, extensionHostKindToString, ExtensionActivationReason, IInternalExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionHost, ExtensionHostKind, ActivationKind, extensionHostKindToString, ExtensionActivationReason, IInternalExtensionService, ExtensionRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; import { CATEGORIES } from 'vs/workbench/common/actions'; import { Barrier, timeout } from 'vs/base/common/async'; import { URI } from 'vs/base/common/uri'; @@ -37,6 +37,7 @@ export interface IExtensionHostManager { readonly onDidChangeResponsiveState: Event; dispose(): void; ready(): Promise; + representsRunningLocation(runningLocation: ExtensionRunningLocation): boolean; deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise; activate(extension: ExtensionIdentifier, reason: ExtensionActivationReason): Promise; activateByEvent(activationEvent: string, activationKind: ActivationKind): Promise; @@ -190,7 +191,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { } private async measure(): Promise { - const proxy = await this._getProxy(); + const proxy = await this._proxy; if (!proxy) { return null; } @@ -205,12 +206,8 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { }; } - private async _getProxy(): Promise { - return this._proxy; - } - public async ready(): Promise { - await this._getProxy(); + await this._proxy; } private async _measureLatency(proxy: IExtensionHostProxy): Promise { @@ -310,7 +307,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { } public async activate(extension: ExtensionIdentifier, reason: ExtensionActivationReason): Promise { - const proxy = await this._getProxy(); + const proxy = await this._proxy; if (!proxy) { return false; } @@ -373,7 +370,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { } }); } - const proxy = await this._getProxy(); + const proxy = await this._proxy; if (!proxy) { throw new Error(`Cannot resolve authority`); } @@ -392,7 +389,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { // This authority does not use a resolver return uri; } - const proxy = await this._getProxy(); + const proxy = await this._proxy; if (!proxy) { throw new Error(`Cannot resolve canonical URI`); } @@ -401,15 +398,16 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { } public async start(enabledExtensionIds: ExtensionIdentifier[]): Promise { - const proxy = await this._getProxy(); + const proxy = await this._proxy; if (!proxy) { return; } + this._extensionHost.extensions.keepOnly(enabledExtensionIds); return proxy.startExtensionHost(enabledExtensionIds); } public async extensionTestsExecute(): Promise { - const proxy = await this._getProxy(); + const proxy = await this._proxy; if (!proxy) { throw new Error('Could not obtain Extension Host Proxy'); } @@ -417,7 +415,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { } public async extensionTestsSendExit(exitCode: number): Promise { - const proxy = await this._getProxy(); + const proxy = await this._proxy; if (!proxy) { return; } @@ -430,16 +428,21 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { } } + public representsRunningLocation(runningLocation: ExtensionRunningLocation): boolean { + return (this.kind === runningLocation.type); + } + public async deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise { - const proxy = await this._getProxy(); + const proxy = await this._proxy; if (!proxy) { return; } + this._extensionHost.extensions.deltaExtensions(toAdd, toRemove); return proxy.deltaExtensions(toAdd, toRemove); } public async setRemoteEnvironment(env: { [key: string]: string | null }): Promise { - const proxy = await this._getProxy(); + const proxy = await this._proxy; if (!proxy) { return; } @@ -498,6 +501,9 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost await this._actual.ready(); } } + public representsRunningLocation(runningLocation: ExtensionRunningLocation): boolean { + return (this.kind === runningLocation.type); + } public async deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise { await this._startCalled.wait(); const extensionHostAlreadyStarted = Boolean(this._actual); diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 1d57b5cbf5d..ac368d46f3a 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -13,6 +13,7 @@ import { getExtensionId, getGalleryExtensionId } from 'vs/platform/extensionMana import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import { ApiProposalName } from 'vs/workbench/services/extensions/common/extensionsApiProposals'; import { IV8Profile } from 'vs/platform/profiling/common/profiling'; +import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; export const nullExtensionDescription = Object.freeze({ identifier: new ExtensionIdentifier('nullExtensionDescription'), @@ -130,6 +131,11 @@ export interface IExtensionHost { readonly kind: ExtensionHostKind; readonly remoteAuthority: string | null; readonly lazyStart: boolean; + /** + * A collection of extensions that will execute or are executing on this extension host. + * **NOTE**: this will reflect extensions correctly only after `start()` resolves. + */ + readonly extensions: ExtensionDescriptionRegistry; readonly onExit: Event<[number, string | null]>; start(): Promise | null; diff --git a/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts b/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts index 91def9ac7da..9bf8f0850fc 100644 --- a/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts +++ b/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts @@ -25,6 +25,7 @@ import { ISignService } from 'vs/platform/sign/common/sign'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; import { parseExtensionDevOptions } from 'vs/workbench/services/extensions/common/extensionDevOptions'; import { createMessageOfType, isMessageOfType, MessageType, IExtensionHostInitData, UIKind } from 'vs/workbench/services/extensions/common/extensionHostProtocol'; import { ExtensionHostKind, ExtensionHostLogFileName, IExtensionHost } from 'vs/workbench/services/extensions/common/extensions'; @@ -52,6 +53,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost { public readonly kind = ExtensionHostKind.Remote; public readonly remoteAuthority: string; public readonly lazyStart = false; + public readonly extensions = new ExtensionDescriptionRegistry([]); private _onExit: Emitter<[number, string | null]> = this._register(new Emitter<[number, string | null]>()); public readonly onExit: Event<[number, string | null]> = this._onExit.event; @@ -222,6 +224,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost { .filter(extension => (extension.main || extension.browser) && extension.api === 'none').map(extension => extension.identifier) ); const workspace = this._contextService.getWorkspace(); + this.extensions.deltaExtensions(remoteInitData.extensions, []); return { commit: this._productService.commit, version: this._productService.version, @@ -251,7 +254,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost { }, resolvedExtensions: resolvedExtensions, hostExtensions: hostExtensions, - extensions: remoteInitData.extensions, + extensions: this.extensions.getAllExtensionDescriptions(), telemetryInfo, logLevel: this._logService.getLevel(), logsLocation: remoteInitData.extensionHostLogsPath, diff --git a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts index 79556450046..90d2fd0f374 100644 --- a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts @@ -44,6 +44,7 @@ import { IExtensionHostProcessOptions, IExtensionHostStarter } from 'vs/platform import { SerializedError } from 'vs/base/common/errors'; import { removeDangerousEnvVariables } from 'vs/base/node/processes'; import { StopWatch } from 'vs/base/common/stopwatch'; +import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; export interface ILocalProcessExtensionHostInitData { readonly autoStart: boolean; @@ -108,6 +109,7 @@ export class LocalProcessExtensionHost implements IExtensionHost { public readonly kind = ExtensionHostKind.LocalProcess; public readonly remoteAuthority = null; public readonly lazyStart = false; + public readonly extensions = new ExtensionDescriptionRegistry([]); private readonly _onExit: Emitter<[number, string]> = new Emitter<[number, string]>(); public readonly onExit: Event<[number, string]> = this._onExit.event; @@ -502,6 +504,7 @@ export class LocalProcessExtensionHost implements IExtensionHost { private async _createExtHostInitData(): Promise { const [telemetryInfo, initData] = await Promise.all([this._telemetryService.getTelemetryInfo(), this._initDataProvider.getInitData()]); const workspace = this._contextService.getWorkspace(); + this.extensions.deltaExtensions(initData.extensions, []); return { commit: this._productService.commit, version: this._productService.version, @@ -532,7 +535,7 @@ export class LocalProcessExtensionHost implements IExtensionHost { }, resolvedExtensions: [], hostExtensions: [], - extensions: initData.extensions, + extensions: this.extensions.getAllExtensionDescriptions(), telemetryInfo, logLevel: this._logService.getLevel(), logsLocation: this._environmentService.extHostLogsPath, From 23bb04dd73b8cf7068211b045a3f3c0e95c5cd8a Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 10 Mar 2022 21:37:04 +0100 Subject: [PATCH 107/175] Reduce assumptions that there is a single extension host of a certain kind --- .../common/abstractExtensionService.ts | 4 ++ .../extensions/common/extensionHostManager.ts | 63 ++++++++++--------- .../electron-browser/extensionService.ts | 55 ++++++++++++++-- 3 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 09ac90c2fb2..056e1533c3a 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -275,6 +275,10 @@ export abstract class AbstractExtensionService extends Disposable implements IEx return null; } + protected _getExtensionHostManagers(kind: ExtensionHostKind): IExtensionHostManager[] { + return this._extensionHostManagers.filter(extHostManager => extHostManager.kind === kind); + } + protected _getExtensionHostManagerByRunningLocation(runningLocation: ExtensionRunningLocation): IExtensionHostManager | null { for (const extensionHostManager of this._extensionHostManagers) { if (extensionHostManager.representsRunningLocation(runningLocation)) { diff --git a/src/vs/workbench/services/extensions/common/extensionHostManager.ts b/src/vs/workbench/services/extensions/common/extensionHostManager.ts index ae7c07645ec..17463bd24f2 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostManager.ts @@ -12,7 +12,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati import { ExtHostCustomersRegistry, IInternalExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers'; import { Proxied, ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier'; import { IRPCProtocolLogger, RPCProtocol, RequestInitiator, ResponsiveState } from 'vs/workbench/services/extensions/common/rpcProtocol'; -import { RemoteAuthorityResolverError, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver'; +import { RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import * as nls from 'vs/nls'; import { registerAction2, Action2 } from 'vs/platform/actions/common/actions'; @@ -25,7 +25,7 @@ import { Barrier, timeout } from 'vs/base/common/async'; import { URI } from 'vs/base/common/uri'; import { ILogService } from 'vs/platform/log/common/log'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IExtensionHostProxy } from 'vs/workbench/services/extensions/common/extensionHostProxy'; +import { IExtensionHostProxy, IResolveAuthorityResult } from 'vs/workbench/services/extensions/common/extensionHostProxy'; // Enable to see detailed message communication between window and extension host const LOG_EXTENSION_HOST_COMMUNICATION = false; @@ -43,7 +43,7 @@ export interface IExtensionHostManager { activateByEvent(activationEvent: string, activationKind: ActivationKind): Promise; activationEventIsDone(activationEvent: string): boolean; getInspectPort(tryEnableInspector: boolean): Promise; - resolveAuthority(remoteAuthority: string): Promise; + resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise; getCanonicalURI(remoteAuthority: string, uri: URI): Promise; start(enabledExtensionIds: ExtensionIdentifier[]): Promise; extensionTestsExecute(): Promise; @@ -93,7 +93,6 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { private readonly _customers: IDisposable[]; private readonly _extensionHost: IExtensionHost; private _proxy: Promise | null; - private _resolveAuthorityAttempt: number; private _hasStarted = false; constructor( @@ -167,7 +166,6 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { measure: () => this.measure() })); }); - this._resolveAuthorityAttempt = 0; } public override dispose(): void { @@ -356,30 +354,30 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { return 0; } - public async resolveAuthority(remoteAuthority: string): Promise { - const authorityPlusIndex = remoteAuthority.indexOf('+'); - if (authorityPlusIndex === -1) { - // This authority does not need to be resolved, simply parse the port number - const lastColon = remoteAuthority.lastIndexOf(':'); - return Promise.resolve({ - authority: { - authority: remoteAuthority, - host: remoteAuthority.substring(0, lastColon), - port: parseInt(remoteAuthority.substring(lastColon + 1), 10), - connectionToken: undefined - } - }); - } + public async resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise { const proxy = await this._proxy; if (!proxy) { - throw new Error(`Cannot resolve authority`); + return { + type: 'error', + error: { + message: `Cannot resolve authority`, + code: RemoteAuthorityResolverErrorCode.Unknown, + detail: undefined + } + }; } - this._resolveAuthorityAttempt++; - const result = await proxy.resolveAuthority(remoteAuthority, this._resolveAuthorityAttempt); - if (result.type === 'ok') { - return result.value; - } else { - throw new RemoteAuthorityResolverError(result.error.message, result.error.code, result.error.detail); + + try { + return proxy.resolveAuthority(remoteAuthority, resolveAttempt); + } catch (err) { + return { + type: 'error', + error: { + message: err.message, + code: RemoteAuthorityResolverErrorCode.Unknown, + detail: err + } + }; } } @@ -549,12 +547,19 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost } return 0; } - public async resolveAuthority(remoteAuthority: string): Promise { + public async resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise { await this._startCalled.wait(); if (this._actual) { - return this._actual.resolveAuthority(remoteAuthority); + return this._actual.resolveAuthority(remoteAuthority, resolveAttempt); } - throw new Error(`Cannot resolve authority`); + return { + type: 'error', + error: { + message: `Cannot resolve authority`, + code: RemoteAuthorityResolverErrorCode.Unknown, + detail: undefined + } + }; } public async getCanonicalURI(remoteAuthority: string, uri: URI): Promise { await this._startCalled.wait(); diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index fee743deec3..31d63bbb221 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -16,7 +16,7 @@ import { IWorkbenchExtensionEnablementService, EnablementState, IWebExtensionsSc import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IRemoteExtensionHostDataProvider, RemoteExtensionHost, IRemoteExtensionHostInitData } from 'vs/workbench/services/extensions/common/remoteExtensionHost'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -import { IRemoteAuthorityResolverService, RemoteAuthorityResolverError, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver'; +import { IRemoteAuthorityResolverService, RemoteAuthorityResolverError, RemoteAuthorityResolverErrorCode, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; @@ -48,6 +48,7 @@ import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/w import { CancellationToken } from 'vs/base/common/cancellation'; import { StopWatch } from 'vs/base/common/stopwatch'; import { isCI } from 'vs/base/common/platform'; +import { IResolveAuthorityErrorResult } from 'vs/workbench/services/extensions/common/extensionHostProxy'; export class ExtensionService extends AbstractExtensionService implements IExtensionService { @@ -56,6 +57,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten private readonly _remoteInitData: Map; private readonly _extensionScanner: CachedExtensionScanner; private readonly _crashTracker = new ExtensionHostCrashTracker(); + private _resolveAuthorityAttempt: number = 0; constructor( @IInstantiationService instantiationService: IInstantiationService, @@ -340,18 +342,62 @@ export class ExtensionService extends AbstractExtensionService implements IExten // --- impl + private async _resolveAuthority(remoteAuthority: string): Promise { + + const authorityPlusIndex = remoteAuthority.indexOf('+'); + if (authorityPlusIndex === -1) { + // This authority does not need to be resolved, simply parse the port number + const lastColon = remoteAuthority.lastIndexOf(':'); + return { + authority: { + authority: remoteAuthority, + host: remoteAuthority.substring(0, lastColon), + port: parseInt(remoteAuthority.substring(lastColon + 1), 10), + connectionToken: undefined + } + }; + } + + const localProcessExtensionHosts = this._getExtensionHostManagers(ExtensionHostKind.LocalProcess); + if (localProcessExtensionHosts.length === 0) { + // no local process extension hosts + throw new Error(`Cannot resolve authority`); + } + + this._resolveAuthorityAttempt++; + const results = await Promise.all(localProcessExtensionHosts.map(extHost => extHost.resolveAuthority(remoteAuthority, this._resolveAuthorityAttempt))); + + let bestErrorResult: IResolveAuthorityErrorResult | null = null; + for (const result of results) { + if (result.type === 'ok') { + return result.value; + } + if (!bestErrorResult) { + bestErrorResult = result; + continue; + } + const bestErrorIsUnknown = (bestErrorResult.error.code === RemoteAuthorityResolverErrorCode.Unknown); + const errorIsUnknown = (result.error.code === RemoteAuthorityResolverErrorCode.Unknown); + if (bestErrorIsUnknown && !errorIsUnknown) { + bestErrorResult = result; + } + } + + // we can only reach this if there is an error + throw new RemoteAuthorityResolverError(bestErrorResult!.error.message, bestErrorResult!.error.code, bestErrorResult!.error.detail); + } + private async _resolveAuthorityAgain(): Promise { const remoteAuthority = this._environmentService.remoteAuthority; if (!remoteAuthority) { return; } - const localProcessExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalProcess)!; this._remoteAuthorityResolverService._clearResolvedAuthority(remoteAuthority); const sw = StopWatch.create(false); this._logService.info(`Invoking resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)})`); try { - const result = await localProcessExtensionHost.resolveAuthority(remoteAuthority); + const result = await this._resolveAuthority(remoteAuthority); this._logService.info(`resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)}) returned '${result.authority.host}:${result.authority.port}' after ${sw.elapsed()} ms`); this._remoteAuthorityResolverService._setResolvedAuthority(result.authority, result.options); } catch (err) { @@ -364,7 +410,6 @@ export class ExtensionService extends AbstractExtensionService implements IExten this._extensionScanner.startScanningExtensions(this.createLogger()); const remoteAuthority = this._environmentService.remoteAuthority; - const localProcessExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalProcess)!; let remoteEnv: IRemoteAgentEnvironment | null = null; let remoteExtensions: IExtensionDescription[] = []; @@ -407,7 +452,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten const sw = StopWatch.create(false); this._logService.info(`Invoking resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)})`); try { - resolverResult = await localProcessExtensionHost.resolveAuthority(remoteAuthority); + resolverResult = await this._resolveAuthority(remoteAuthority); this._logService.info(`resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)}) returned '${resolverResult.authority.host}:${resolverResult.authority.port}' after ${sw.elapsed()} ms`); } catch (err) { this._logService.error(`resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)}) returned an error after ${sw.elapsed()} ms`, err); From 6b7453421201c888b81eae5c04ec822a6423608f Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Thu, 10 Mar 2022 16:20:23 -0800 Subject: [PATCH 108/175] rename side panel (#144862) * rename side panel * tweaks based on feedback --- .../browser/actions/layoutActions.ts | 54 ++++++++--------- src/vs/workbench/browser/layout.ts | 4 +- .../parts/activitybar/activitybarActions.ts | 4 +- .../parts/auxiliarybar/auxiliaryBarActions.ts | 20 +++---- .../parts/auxiliarybar/auxiliaryBarPart.ts | 6 +- .../browser/parts/panel/panelActions.ts | 59 ++++++++++++++----- .../browser/parts/panel/panelPart.ts | 5 +- .../browser/parts/sidebar/sidebarActions.ts | 2 +- .../browser/workbench.contribution.ts | 2 +- .../quickaccess/browser/viewQuickAccess.ts | 2 +- .../src/areas/preferences/preferences.test.ts | 2 +- 11 files changed, 92 insertions(+), 68 deletions(-) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 574310e986e..780d43b23b0 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -33,8 +33,8 @@ import { ICommandActionTitle } from 'vs/platform/action/common/action'; const menubarIcon = registerIcon('menuBar', Codicon.layoutMenubar, localize('menuBarIcon', "Represents the menu bar")); const activityBarLeftIcon = registerIcon('activity-bar-left', Codicon.layoutActivitybarLeft, localize('activityBarLeft', "Represents the activity bar in the left position")); const activityBarRightIcon = registerIcon('activity-bar-right', Codicon.layoutActivitybarRight, localize('activityBarRight', "Represents the activity bar in the right position")); -const panelLeftIcon = registerIcon('panel-left', Codicon.layoutSidebarLeft, localize('panelLeft', "Represents the side bar or side panel in the left position")); -const panelRightIcon = registerIcon('panel-right', Codicon.layoutSidebarRight, localize('panelRight', "Represents the side bar or side panel in the right position")); +const panelLeftIcon = registerIcon('panel-left', Codicon.layoutSidebarLeft, localize('panelLeft', "Represents a side bar in the left position")); +const panelRightIcon = registerIcon('panel-right', Codicon.layoutSidebarRight, localize('panelRight', "Represents side bar in the right position")); const panelIcon = registerIcon('panel-bottom', Codicon.layoutPanel, localize('panelBottom', "Represents the bottom panel")); const statusBarIcon = registerIcon('statusBar', Codicon.layoutStatusbar, localize('statusBarIcon', "Represents the status bar")); @@ -55,7 +55,7 @@ registerAction2(class extends Action2 { constructor() { super({ id: 'workbench.action.closeSidebar', - title: { value: localize('closeSidebar', "Close Side Bar"), original: 'Close Side Bar' }, + title: { value: localize('closeSidebar', "Close Primary Side Bar"), original: 'Close Primary Side Bar' }, category: CATEGORIES.View, f1: true }); @@ -164,8 +164,8 @@ class MoveSidebarRightAction extends MoveSidebarPositionAction { constructor() { super(MoveSidebarRightAction.ID, { - value: localize('moveSidebarRight', "Move Side Bar Right"), - original: 'Move Side Bar Right' + value: localize('moveSidebarRight', "Move Primary Side Bar Right"), + original: 'Move Primary Side Bar Right' }, Position.RIGHT); } } @@ -175,8 +175,8 @@ class MoveSidebarLeftAction extends MoveSidebarPositionAction { constructor() { super(MoveSidebarLeftAction.ID, { - value: localize('moveSidebarLeft', "Move Side Bar Left"), - original: 'Move Side Bar Left' + value: localize('moveSidebarLeft', "Move Primary Side Bar Left"), + original: 'Move Primary Side Bar Left' }, Position.LEFT); } } @@ -189,16 +189,16 @@ registerAction2(MoveSidebarLeftAction); export class ToggleSidebarPositionAction extends Action2 { static readonly ID = 'workbench.action.toggleSidebarPosition'; - static readonly LABEL = localize('toggleSidebarPosition', "Toggle Side Bar Position"); + static readonly LABEL = localize('toggleSidebarPosition', "Toggle Primary Side Bar Position"); static getLabel(layoutService: IWorkbenchLayoutService): string { - return layoutService.getSideBarPosition() === Position.LEFT ? localize('moveSidebarRight', "Move Side Bar Right") : localize('moveSidebarLeft', "Move Side Bar Left"); + return layoutService.getSideBarPosition() === Position.LEFT ? localize('moveSidebarRight', "Move Primary Side Bar Right") : localize('moveSidebarLeft', "Move Primary Side Bar Left"); } constructor() { super({ id: ToggleSidebarPositionAction.ID, - title: { value: localize('toggleSidebarPosition', "Toggle Side Bar Position"), original: 'Toggle Side Bar Position' }, + title: { value: localize('toggleSidebarPosition', "Toggle Primary Side Bar Position"), original: 'Toggle Primary Side Bar Position' }, category: CATEGORIES.View, f1: true }); @@ -233,7 +233,7 @@ MenuRegistry.appendMenuItems([{ group: '3_workbench_layout_move', command: { id: ToggleSidebarPositionAction.ID, - title: localize('move sidebar right', "Move Side Bar Right") + title: localize('move side bar right', "Move Primary Side Bar Right") }, when: ContextKeyExpr.and(ContextKeyExpr.notEquals('config.workbench.sideBar.location', 'right'), ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))), order: 1 @@ -244,7 +244,7 @@ MenuRegistry.appendMenuItems([{ group: '3_workbench_layout_move', command: { id: ToggleSidebarPositionAction.ID, - title: localize('move sidebar right', "Move Side Bar Right") + title: localize('move sidebar right', "Move Primary Side Bar Right") }, when: ContextKeyExpr.and(ContextKeyExpr.notEquals('config.workbench.sideBar.location', 'right'), ContextKeyExpr.equals('viewLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))), order: 1 @@ -255,7 +255,7 @@ MenuRegistry.appendMenuItems([{ group: '3_workbench_layout_move', command: { id: ToggleSidebarPositionAction.ID, - title: localize('move sidebar left', "Move Side Bar Left") + title: localize('move sidebar left', "Move Primary Side Bar Left") }, when: ContextKeyExpr.and(ContextKeyExpr.equals('config.workbench.sideBar.location', 'right'), ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))), order: 1 @@ -266,7 +266,7 @@ MenuRegistry.appendMenuItems([{ group: '3_workbench_layout_move', command: { id: ToggleSidebarPositionAction.ID, - title: localize('move sidebar left', "Move Side Bar Left") + title: localize('move sidebar left', "Move Primary Side Bar Left") }, when: ContextKeyExpr.and(ContextKeyExpr.equals('config.workbench.sideBar.location', 'right'), ContextKeyExpr.equals('viewLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))), order: 1 @@ -277,7 +277,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { group: '3_workbench_layout_move', command: { id: ToggleSidebarPositionAction.ID, - title: localize({ key: 'miMoveSidebarRight', comment: ['&& denotes a mnemonic'] }, "&&Move Side Bar Right") + title: localize({ key: 'miMoveSidebarRight', comment: ['&& denotes a mnemonic'] }, "&&Move Primary Side Bar Right") }, when: ContextKeyExpr.notEquals('config.workbench.sideBar.location', 'right'), order: 2 @@ -287,7 +287,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { group: '3_workbench_layout_move', command: { id: ToggleSidebarPositionAction.ID, - title: localize({ key: 'miMoveSidebarLeft', comment: ['&& denotes a mnemonic'] }, "&&Move Side Bar Left") + title: localize({ key: 'miMoveSidebarLeft', comment: ['&& denotes a mnemonic'] }, "&&Move Primary Side Bar Left") }, when: ContextKeyExpr.equals('config.workbench.sideBar.location', 'right'), order: 2 @@ -338,7 +338,7 @@ class ToggleSidebarVisibilityAction extends Action2 { constructor() { super({ id: ToggleSidebarVisibilityAction.ID, - title: { value: localize('toggleSidebar', "Toggle Side Bar Visibility"), original: 'Toggle Side Bar Visibility' }, + title: { value: localize('toggleSidebar', "Toggle Primary Side Bar Visibility"), original: 'Toggle Primary Side Bar Visibility' }, category: CATEGORIES.View, f1: true, keybinding: { @@ -386,7 +386,7 @@ MenuRegistry.appendMenuItems([ group: '2_workbench_layout', command: { id: ToggleSidebarVisibilityAction.ID, - title: localize({ key: 'miShowSidebar', comment: ['&& denotes a mnemonic'] }, "Show &&Side Bar"), + title: localize({ key: 'miShowSidebar', comment: ['&& denotes a mnemonic'] }, "Show &&Primary Side Bar"), toggled: SideBarVisibleContext }, order: 1 @@ -397,7 +397,7 @@ MenuRegistry.appendMenuItems([ group: '0_workbench_layout', command: { id: ToggleSidebarVisibilityAction.ID, - title: localize('miShowSidebarNoMnnemonic', "Show Side Bar"), + title: localize('miShowSidebarNoMnnemonic', "Show Primary Side Bar"), toggled: SideBarVisibleContext }, order: 0 @@ -408,7 +408,7 @@ MenuRegistry.appendMenuItems([ group: '0_workbench_toggles', command: { id: ToggleSidebarVisibilityAction.ID, - title: localize('toggleSideBar', "Toggle Side Bar"), + title: localize('toggleSideBar', "Toggle Primary Side Bar"), icon: panelLeftIcon, toggled: SideBarVisibleContext }, @@ -421,7 +421,7 @@ MenuRegistry.appendMenuItems([ group: '0_workbench_toggles', command: { id: ToggleSidebarVisibilityAction.ID, - title: localize('toggleSideBar', "Toggle Side Bar"), + title: localize('toggleSideBar', "Toggle Primary Side Bar"), icon: panelRightIcon, toggled: SideBarVisibleContext }, @@ -704,7 +704,7 @@ registerAction2(class extends Action2 { if (!hasAddedView) { results.push({ type: 'separator', - label: localize('sidePanelContainer', "Side Panel / {0}", containerModel.title) + label: localize('secondarySideBarContainer', "Secondary Side Bar / {0}", containerModel.title) }); hasAddedView = true; } @@ -809,7 +809,7 @@ class MoveFocusedViewAction extends Action2 { if (!(isViewSolo && currentLocation === ViewContainerLocation.AuxiliaryBar)) { items.push({ id: '_.auxiliarybar.newcontainer', - label: localize('moveFocusedView.newContainerInSidePanel', "New Side Panel Entry") + label: localize('moveFocusedView.newContainerInSidePanel', "New Secondary Side Bar Entry") }); } @@ -857,7 +857,7 @@ class MoveFocusedViewAction extends Action2 { items.push({ type: 'separator', - label: localize('sidePanel', "Side Panel") + label: localize('secondarySideBar', "Secondary Side Bar") }); const pinnedAuxPanels = paneCompositePartService.getPinnedPaneCompositeIds(ViewContainerLocation.AuxiliaryBar); @@ -1133,9 +1133,9 @@ if (!isMacintosh || !isNative) { ToggleVisibilityActions.push(...[ CreateToggleLayoutItem(ToggleActivityBarVisibilityAction.ID, ContextKeyExpr.equals('config.workbench.activityBar.visible', true), localize('activityBar', "Activity Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: activityBarLeftIcon, iconB: activityBarRightIcon }), - CreateToggleLayoutItem(ToggleSidebarVisibilityAction.ID, SideBarVisibleContext, localize('sideBar', "Side Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: panelLeftIcon, iconB: panelRightIcon }), + CreateToggleLayoutItem(ToggleSidebarVisibilityAction.ID, SideBarVisibleContext, localize('sideBar', "Primary Side Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: panelLeftIcon, iconB: panelRightIcon }), CreateToggleLayoutItem(TogglePanelAction.ID, PanelVisibleContext, localize('panel', "Panel"), panelIcon), - CreateToggleLayoutItem(ToggleAuxiliaryBarAction.ID, AuxiliaryBarVisibleContext, localize('sidePanel', "Side Panel"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: panelRightIcon, iconB: panelLeftIcon }), + CreateToggleLayoutItem(ToggleAuxiliaryBarAction.ID, AuxiliaryBarVisibleContext, localize('secondarySideBar', "Secondary Side Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: panelRightIcon, iconB: panelLeftIcon }), CreateToggleLayoutItem(ToggleStatusbarVisibilityAction.ID, ContextKeyExpr.equals('config.workbench.statusBar.visible', true), localize('statusBar', "Status Bar"), statusBarIcon), ]); @@ -1220,7 +1220,7 @@ registerAction2(class CustomizeLayoutAction extends Action2 { ...ToggleVisibilityActions.map(toQuickPickItem), { type: 'separator', - label: localize('sideBarPosition', "Side Bar Position") + label: localize('sideBarPosition', "Primary Side Bar Position") }, ...MoveSideBarActions.map(toQuickPickItem), { diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index f8b2205ca2a..1bf6c4750e2 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -379,7 +379,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi sideBar.updateStyles(); auxiliaryBar.updateStyles(); - // Move activity bar, side bar, and side panel + // Move activity bar and side bars this.adjustPartPositions(position, panelAlignment, panelPosition); } @@ -1484,7 +1484,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi private adjustPartPositions(sideBarPosition: Position, panelAlignment: PanelAlignment, panelPosition: Position): void { - // Move activity bar, side bar, and side panel + // Move activity bar and side bars const sideBarSiblingToEditor = panelPosition !== Position.BOTTOM || !(panelAlignment === 'center' || (sideBarPosition === Position.LEFT && panelAlignment === 'right') || (sideBarPosition === Position.RIGHT && panelAlignment === 'left')); const auxiliaryBarSiblingToEditor = panelPosition !== Position.BOTTOM || !(panelAlignment === 'center' || (sideBarPosition === Position.RIGHT && panelAlignment === 'right') || (sideBarPosition === Position.LEFT && panelAlignment === 'left')); const preMovePanelWidth = !this.isVisible(Parts.PANEL_PART) ? Sizing.Invisible(this.workbenchGrid.getViewCachedVisibleSize(this.panelPartView) ?? this.panelPartView.minimumWidth) : this.workbenchGrid.getViewSize(this.panelPartView).width; diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index e4a15b65c35..36647e6dcfe 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -371,7 +371,7 @@ registerAction2( constructor() { super({ id: 'workbench.action.previousSideBarView', - title: { value: localize('previousSideBarView', "Previous Side Bar View"), original: 'Previous Side Bar View' }, + title: { value: localize('previousSideBarView', "Previous Primary Side Bar View"), original: 'Previous Primary Side Bar View' }, category: CATEGORIES.View, f1: true }, -1); @@ -384,7 +384,7 @@ registerAction2( constructor() { super({ id: 'workbench.action.nextSideBarView', - title: { value: localize('nextSideBarView', "Next Side Bar View"), original: 'Next Side Bar View' }, + title: { value: localize('nextSideBarView', "Next Primary Side Bar View"), original: 'Next Primary Side Bar View' }, category: CATEGORIES.View, f1: true }, 1); diff --git a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts index 2bfd75de107..02f428254c7 100644 --- a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts +++ b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts @@ -23,7 +23,7 @@ const auxiliaryBarLeftIcon = registerIcon('auxiliarybar-left-layout-icon', Codic export class ToggleAuxiliaryBarAction extends Action { static readonly ID = 'workbench.action.toggleAuxiliaryBar'; - static readonly LABEL = localize('toggleAuxiliaryBar', "Toggle Side Panel"); + static readonly LABEL = localize('toggleAuxiliaryBar', "Toggle Secondary Side Bar"); constructor( id: string, @@ -41,7 +41,7 @@ export class ToggleAuxiliaryBarAction extends Action { class FocusAuxiliaryBarAction extends Action { static readonly ID = 'workbench.action.focusAuxiliaryBar'; - static readonly LABEL = localize('focusAuxiliaryBar', "Focus into Side Panel"); + static readonly LABEL = localize('focusAuxiliaryBar', "Focus into Secondary Side Bar"); constructor( id: string, @@ -74,7 +74,7 @@ MenuRegistry.appendMenuItems([ group: '0_workbench_layout', command: { id: ToggleAuxiliaryBarAction.ID, - title: localize('miShowAuxiliaryBarNoMnemonic', "Show Side Panel"), + title: localize('miShowAuxiliaryBarNoMnemonic', "Show Secondary Side Bar"), toggled: AuxiliaryBarVisibleContext }, order: 4 @@ -86,7 +86,7 @@ MenuRegistry.appendMenuItems([ group: '0_workbench_toggles', command: { id: ToggleAuxiliaryBarAction.ID, - title: localize('toggleSidePanel', "Toggle Side Panel"), + title: localize('toggleSecondarySideBar', "Toggle Secondary Side Bar"), toggled: AuxiliaryBarVisibleContext, icon: auxiliaryBarLeftIcon, }, @@ -100,7 +100,7 @@ MenuRegistry.appendMenuItems([ group: '0_workbench_toggles', command: { id: ToggleAuxiliaryBarAction.ID, - title: localize('toggleSidePanel', "Toggle Side Panel"), + title: localize('toggleSecondarySideBar', "Toggle Secondary Side Bar"), toggled: AuxiliaryBarVisibleContext, icon: auxiliaryBarRightIcon, }, @@ -114,10 +114,10 @@ MenuRegistry.appendMenuItems([ group: '2_workbench_layout', command: { id: ToggleAuxiliaryBarAction.ID, - title: localize({ key: 'miShowAuxiliaryBar', comment: ['&& denotes a mnemonic'] }, "Show Si&&de Panel"), + title: localize({ key: 'miShowAuxiliaryBar', comment: ['&& denotes a mnemonic'] }, "Show Secondary Si&&de Bar"), toggled: AuxiliaryBarVisibleContext }, - order: 5 + order: 2 } }, { id: MenuId.ViewTitleContext, @@ -125,7 +125,7 @@ MenuRegistry.appendMenuItems([ group: '3_workbench_layout_move', command: { id: ToggleAuxiliaryBarAction.ID, - title: { value: localize('hideAuxiliaryBar', "Hide Side Panel"), original: 'Hide Side Panel' }, + title: { value: localize('hideAuxiliaryBar', "Hide Secondary Side Bar"), original: 'Hide Secondary Side Bar' }, }, when: ContextKeyExpr.and(AuxiliaryBarVisibleContext, ContextKeyExpr.equals('viewLocation', ViewContainerLocationToString(ViewContainerLocation.AuxiliaryBar))), order: 2 @@ -134,5 +134,5 @@ MenuRegistry.appendMenuItems([ ]); const actionRegistry = Registry.as(WorkbenchExtensions.WorkbenchActions); -actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleAuxiliaryBarAction), 'View: Toggle Side Panel', CATEGORIES.View.value); -actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusAuxiliaryBarAction), 'View: Focus into Side Panel', CATEGORIES.View.value); +actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleAuxiliaryBarAction), 'View: Toggle Secondary Side Bar', CATEGORIES.View.value); +actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusAuxiliaryBarAction), 'View: Focus into Secondary Side Bar', CATEGORIES.View.value); diff --git a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts index e90911a75dc..7534ee7e9b4 100644 --- a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts +++ b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts @@ -23,10 +23,9 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten import { IWorkbenchLayoutService, Parts, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { IActivityHoverOptions } from 'vs/workbench/browser/parts/compositeBarActions'; import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget'; -import { IAction, Separator, toAction } from 'vs/base/common/actions'; +import { IAction, Separator } from 'vs/base/common/actions'; import { ToggleAuxiliaryBarAction } from 'vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions'; import { assertIsDefined } from 'vs/base/common/types'; -import { MoveSidePanelToPanelAction } from 'vs/workbench/browser/parts/panel/panelActions'; import { LayoutPriority } from 'vs/base/browser/ui/splitview/splitview'; export class AuxiliaryBarPart extends BasePanelPart { @@ -110,8 +109,7 @@ export class AuxiliaryBarPart extends BasePanelPart { protected fillExtraContextMenuActions(actions: IAction[]): void { actions.push(...[ new Separator(), - toAction({ id: MoveSidePanelToPanelAction.ID, label: localize('moveToPanel', "Move Views to Panel"), run: () => this.instantiationService.invokeFunction(accessor => new MoveSidePanelToPanelAction().run(accessor)) }), - this.instantiationService.createInstance(ToggleAuxiliaryBarAction, ToggleAuxiliaryBarAction.ID, localize('hideAuxiliaryBar', "Hide Side Panel")) + this.instantiationService.createInstance(ToggleAuxiliaryBarAction, ToggleAuxiliaryBarAction.ID, localize('hideAuxiliaryBar', "Hide Secondary Side Bar")) ]); } diff --git a/src/vs/workbench/browser/parts/panel/panelActions.ts b/src/vs/workbench/browser/parts/panel/panelActions.ts index 22142adcb3a..54685c13787 100644 --- a/src/vs/workbench/browser/parts/panel/panelActions.ts +++ b/src/vs/workbench/browser/parts/panel/panelActions.ts @@ -396,7 +396,7 @@ registerAction2(class extends Action2 { constructor() { super({ id: 'workbench.action.closeAuxiliaryBar', - title: { value: localize('closeSidePanel', "Close Side Panel"), original: 'Close Side Panel' }, + title: { value: localize('closeSecondarySideBar', "Close Secondary Side Bar"), original: 'Close Secondary Side Bar' }, category: CATEGORIES.View, icon: closeIcon, menu: [{ @@ -490,42 +490,68 @@ class MoveViewsBetweenPanelsAction extends Action2 { } } -// --- Move Panel Views To Side Panel +// --- Move Panel Views To Secondary Side Bar -export class MovePanelToSidePanelAction extends MoveViewsBetweenPanelsAction { +class MovePanelToSidePanelAction extends MoveViewsBetweenPanelsAction { static readonly ID = 'workbench.action.movePanelToSidePanel'; constructor() { super(ViewContainerLocation.Panel, ViewContainerLocation.AuxiliaryBar, { id: MovePanelToSidePanelAction.ID, title: { - value: localize('movePanelToSidePanel', "Move Panel Views To Side Panel"), - original: 'Move Panel Views To Side Panel' + value: localize('movePanelToSecondarySideBar', "Move Panel Views To Secondary Side Bar"), + original: 'Move Panel Views To Secondary Side Bar' }, category: CATEGORIES.View, - f1: true, - menu: [{ - id: MenuId.ViewContainerTitleContext, - group: '3_workbench_layout_move', - order: 0, - when: ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Panel)), - }] + f1: true + }); + } +} + +export class MovePanelToSecondarySideBarAction extends MoveViewsBetweenPanelsAction { + static readonly ID = 'workbench.action.movePanelToSecondarySideBar'; + constructor() { + super(ViewContainerLocation.Panel, ViewContainerLocation.AuxiliaryBar, { + id: MovePanelToSecondarySideBarAction.ID, + title: { + value: localize('movePanelToSecondarySideBar', "Move Panel Views To Secondary Side Bar"), + original: 'Move Panel Views To Secondary Side Bar' + }, + category: CATEGORIES.View, + f1: true }); } } registerAction2(MovePanelToSidePanelAction); +registerAction2(MovePanelToSecondarySideBarAction); -// --- Move Panel Views To Side Panel +// --- Move Secondary Side Bar Views To Panel -export class MoveSidePanelToPanelAction extends MoveViewsBetweenPanelsAction { +class MoveSidePanelToPanelAction extends MoveViewsBetweenPanelsAction { static readonly ID = 'workbench.action.moveSidePanelToPanel'; constructor() { super(ViewContainerLocation.AuxiliaryBar, ViewContainerLocation.Panel, { id: MoveSidePanelToPanelAction.ID, title: { - value: localize('moveSidePanelToPanel', "Move Side Panel Views To Panel"), - original: 'Move Side Panel Views To Panel' + value: localize('moveSidePanelToPanel', "Move Secondary Side Bar Views To Panel"), + original: 'Move Secondary Side Bar Views To Panel' + }, + category: CATEGORIES.View, + f1: true + }); + } +} + +export class MoveSecondarySideBarToPanelAction extends MoveViewsBetweenPanelsAction { + static readonly ID = 'workbench.action.moveSecondarySideBarToPanel'; + + constructor() { + super(ViewContainerLocation.AuxiliaryBar, ViewContainerLocation.Panel, { + id: MoveSecondarySideBarToPanelAction.ID, + title: { + value: localize('moveSidePanelToPanel', "Move Secondary Side Bar Views To Panel"), + original: 'Move Secondary Side Bar Views To Panel' }, category: CATEGORIES.View, f1: true @@ -533,3 +559,4 @@ export class MoveSidePanelToPanelAction extends MoveViewsBetweenPanelsAction { } } registerAction2(MoveSidePanelToPanelAction); +registerAction2(MoveSecondarySideBarToPanelAction); diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index e671cd4b144..3e87cd1f5fd 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -18,7 +18,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { PanelActivityAction, TogglePanelAction, PlaceHolderPanelActivityAction, PlaceHolderToggleCompositePinnedAction, PositionPanelActionConfigs, SetPanelPositionAction, MovePanelToSidePanelAction } from 'vs/workbench/browser/parts/panel/panelActions'; +import { PanelActivityAction, TogglePanelAction, PlaceHolderPanelActivityAction, PlaceHolderToggleCompositePinnedAction, PositionPanelActionConfigs, SetPanelPositionAction } from 'vs/workbench/browser/parts/panel/panelActions'; import { IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_INPUT_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, PANEL_DRAG_AND_DROP_BORDER } from 'vs/workbench/common/theme'; import { activeContrastBorder, focusBorder, contrastBorder, editorBackground, badgeBackground, badgeForeground } from 'vs/platform/theme/common/colorRegistry'; @@ -493,7 +493,7 @@ export abstract class BasePanelPart extends CompositePart impleme const messageElement = document.createElement('div'); messageElement.classList.add('empty-panel-message'); - messageElement.innerText = localize('panel.emptyMessage', "Drag a view into the panel to display."); + messageElement.innerText = localize('panel.emptyMessage', "Drag a view here to display."); this.emptyPanelMessageElement.appendChild(messageElement); contentArea.appendChild(this.emptyPanelMessageElement); @@ -965,7 +965,6 @@ export class PanelPart extends BasePanelPart { actions.push(...[ new Separator(), - toAction({ id: MovePanelToSidePanelAction.ID, label: localize('moveToSidePanel', "Move Views to Side Panel"), run: () => this.instantiationService.invokeFunction(accessor => new MovePanelToSidePanelAction().run(accessor)) }), ...PositionPanelActionConfigs // show the contextual menu item if it is not in that position .filter(({ when }) => this.contextKeyService.contextMatchesRules(when)) diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts b/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts index e2d436c64f2..f1ab76ec17b 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts @@ -19,7 +19,7 @@ export class FocusSideBarAction extends Action2 { constructor() { super({ id: 'workbench.action.focusSideBar', - title: { value: localize('focusSideBar', "Focus into Side Bar"), original: 'Focus into Side Bar' }, + title: { value: localize('focusSideBar', "Focus into Primary Side Bar"), original: 'Focus into Primary Side Bar' }, category: CATEGORIES.View, f1: true, keybinding: { diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index 865b54ffca7..d16406e9026 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -296,7 +296,7 @@ const registry = Registry.as(ConfigurationExtensions.Con 'type': 'string', 'enum': ['left', 'right'], 'default': 'left', - 'description': localize('sideBarLocation', "Controls the location of the sidebar and activity bar. They can either show on the left or right of the workbench.") + 'description': localize('sideBarLocation', "Controls the location of the primary sidebar and activity bar. They can either show on the left or right of the workbench. The secondary side bar will show on the opposite side of the workbench.") }, 'workbench.panel.defaultLocation': { 'type': 'string', diff --git a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts index 1cad625e6ae..d1a3d7680d5 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts @@ -149,7 +149,7 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider { const paneComposites = this.paneCompositeService.getPaneComposites(location); diff --git a/test/smoke/src/areas/preferences/preferences.test.ts b/test/smoke/src/areas/preferences/preferences.test.ts index 1d8e6984a98..68a6dffdd10 100644 --- a/test/smoke/src/areas/preferences/preferences.test.ts +++ b/test/smoke/src/areas/preferences/preferences.test.ts @@ -27,7 +27,7 @@ export function setup(logger: Logger) { await app.workbench.activitybar.waitForActivityBar(ActivityBarPosition.LEFT); - await app.workbench.keybindingsEditor.updateKeybinding('workbench.action.toggleSidebarPosition', 'View: Toggle Side Bar Position', 'ctrl+u', 'Control+U'); + await app.workbench.keybindingsEditor.updateKeybinding('workbench.action.toggleSidebarPosition', 'View: Toggle Primary Side Bar Position', 'ctrl+u', 'Control+U'); await app.code.dispatchKeybinding('ctrl+u'); await app.workbench.activitybar.waitForActivityBar(ActivityBarPosition.RIGHT); From 7ba42f10fb2f84e8f8a350ec53606ba23c183429 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Mar 2022 09:03:06 +0100 Subject: [PATCH 109/175] More removing of assumptions that there is a single extension host of a certain kind --- .../extensions/browser/extensionService.ts | 16 ++++---- .../common/abstractExtensionService.ts | 40 ++++++++++-------- .../services/extensions/common/extensions.ts | 9 ++++ .../electron-browser/extensionService.ts | 41 +++++++++++-------- 4 files changed, 63 insertions(+), 43 deletions(-) diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts index 755dbba42bc..1734df26581 100644 --- a/src/vs/workbench/services/extensions/browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/browser/extensionService.ts @@ -13,10 +13,10 @@ import { IExtensionService, IExtensionHost, toExtensionDescription, ExtensionRun import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { IProductService } from 'vs/platform/product/common/productService'; -import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString, filterByRunningLocation } from 'vs/workbench/services/extensions/common/abstractExtensionService'; +import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString, filterByExtensionHostKind, filterByRunningLocation } from 'vs/workbench/services/extensions/common/abstractExtensionService'; import { RemoteExtensionHost, IRemoteExtensionHostDataProvider, IRemoteExtensionHostInitData } from 'vs/workbench/services/extensions/common/remoteExtensionHost'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -import { WebWorkerExtensionHost } from 'vs/workbench/services/extensions/browser/webWorkerExtensionHost'; +import { IWebWorkerExtensionHostDataProvider, WebWorkerExtensionHost } from 'vs/workbench/services/extensions/browser/webWorkerExtensionHost'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ExtensionIdentifier, IExtensionDescription, IExtension, ExtensionType } from 'vs/platform/extensions/common/extensions'; import { ExtensionKind } from 'vs/platform/environment/common/environment'; @@ -107,11 +107,11 @@ export class ExtensionService extends AbstractExtensionService implements IExten this._disposables.add(this._fileService.registerProvider(Schemas.https, provider)); } - private _createLocalExtensionHostDataProvider() { + private _createLocalExtensionHostDataProvider(desiredRunningLocation: ExtensionRunningLocation): IWebWorkerExtensionHostDataProvider { return { getInitData: async () => { const allExtensions = await this.getExtensions(); - const localWebWorkerExtensions = filterByRunningLocation(allExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); + const localWebWorkerExtensions = filterByRunningLocation(allExtensions, this._runningLocation, desiredRunningLocation); return { autoStart: true, extensions: localWebWorkerExtensions @@ -174,7 +174,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten protected _createExtensionHosts(_isInitialStart: boolean): IExtensionHost[] { const result: IExtensionHost[] = []; - const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, false, this._createLocalExtensionHostDataProvider()); + const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, false, this._createLocalExtensionHostDataProvider(new LocalWebWorkerRunningLocation())); result.push(webWorkerExtHost); const remoteAgentConnection = this._remoteAgentService.getConnection(); @@ -202,9 +202,9 @@ export class ExtensionService extends AbstractExtensionService implements IExten this._runningLocation = this._runningLocationClassifier.determineRunningLocation(localExtensions, remoteExtensions); // Some remote extensions could run locally in the web worker, so store them - const remoteExtensionsThatNeedToRunLocally = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); - localExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); - remoteExtensions = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionHostKind.Remote); + const remoteExtensionsThatNeedToRunLocally = filterByExtensionHostKind(remoteExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); + localExtensions = filterByExtensionHostKind(localExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); + remoteExtensions = filterByExtensionHostKind(remoteExtensions, this._runningLocation, ExtensionHostKind.Remote); // Add locally the remote extensions that need to run locally in the web worker for (const ext of remoteExtensionsThatNeedToRunLocally) { diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 056e1533c3a..9b4c8861d12 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -410,11 +410,11 @@ export abstract class AbstractExtensionService extends Disposable implements IEx await Promise.all(promises); } - private async _updateExtensionsOnExtHost(extensionHostManager: IExtensionHostManager, toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[], removedRunningLocation: Map): Promise { - const localToAdd = filterByExtensionHostManager(toAdd, this._runningLocation, extensionHostManager); - const localToRemove = _filterByExtensionHostManager(toRemove, extId => extId, removedRunningLocation, extensionHostManager); - if (localToRemove.length > 0 || localToAdd.length > 0) { - await extensionHostManager.deltaExtensions(localToAdd, localToRemove); + private async _updateExtensionsOnExtHost(extensionHostManager: IExtensionHostManager, _toAdd: IExtensionDescription[], _toRemove: ExtensionIdentifier[], removedRunningLocation: Map): Promise { + const toAdd = filterByExtensionHostManager(_toAdd, this._runningLocation, extensionHostManager); + const toRemove = _filterByExtensionHostManager(_toRemove, extId => extId, removedRunningLocation, extensionHostManager); + if (toRemove.length > 0 || toAdd.length > 0) { + await extensionHostManager.deltaExtensions(toAdd, toRemove); } } @@ -658,10 +658,8 @@ export abstract class AbstractExtensionService extends Disposable implements IEx try { this._startExtensionHosts(false, Array.from(this._allRequestedActivateEvents.keys())); - const localProcessExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalProcess); - if (localProcessExtensionHost) { - await localProcessExtensionHost.ready(); - } + const localProcessExtensionHosts = this._getExtensionHostManagers(ExtensionHostKind.LocalProcess); + await Promise.all(localProcessExtensionHosts.map(extHost => extHost.ready())); } finally { lock.dispose(); } @@ -1240,23 +1238,29 @@ class ProposedApiController { } } -export function filterByRunningLocation(extensions: IExtensionDescription[], runningLocation: Map, desiredExtensionHostKind: ExtensionHostKind): IExtensionDescription[] { - return _filterByRunningLocation(extensions, ext => ext.identifier, runningLocation, desiredExtensionHostKind); +export function filterByRunningLocation(extensions: IExtensionDescription[], runningLocation: Map, desiredRunningLocation: ExtensionRunningLocation): IExtensionDescription[] { + return _filterByRunningLocation(extensions, ext => ext.identifier, runningLocation, desiredRunningLocation); } -function _filterByRunningLocation(extensions: T[], extId: (item: T) => ExtensionIdentifier, runningLocation: Map, desiredExtensionHostKind: ExtensionHostKind): T[] { - return extensions.filter((ext) => { - const extRunningLocation = runningLocation.get(ExtensionIdentifier.toKey(extId(ext))); - return (extRunningLocation && extRunningLocation.type === desiredExtensionHostKind); - }); +function _filterByRunningLocation(extensions: T[], extId: (item: T) => ExtensionIdentifier, runningLocation: Map, desiredRunningLocation: ExtensionRunningLocation): T[] { + return _filterExtensions(extensions, extId, runningLocation, extRunningLocation => desiredRunningLocation.equals(extRunningLocation)); } -function filterByExtensionHostManager(extensions: IExtensionDescription[], runningLocation: Map, extensionHostManager: IExtensionHostManager): IExtensionDescription[] { +export function filterByExtensionHostKind(extensions: IExtensionDescription[], runningLocation: Map, desiredExtensionHostKind: ExtensionHostKind): IExtensionDescription[] { + return _filterExtensions(extensions, ext => ext.identifier, runningLocation, extRunningLocation => extRunningLocation.type === desiredExtensionHostKind); +} + +export function filterByExtensionHostManager(extensions: IExtensionDescription[], runningLocation: Map, extensionHostManager: IExtensionHostManager): IExtensionDescription[] { return _filterByExtensionHostManager(extensions, ext => ext.identifier, runningLocation, extensionHostManager); } + function _filterByExtensionHostManager(extensions: T[], extId: (item: T) => ExtensionIdentifier, runningLocation: Map, extensionHostManager: IExtensionHostManager): T[] { + return _filterExtensions(extensions, extId, runningLocation, extRunningLocation => extensionHostManager.representsRunningLocation(extRunningLocation)); +} + +function _filterExtensions(extensions: T[], extId: (item: T) => ExtensionIdentifier, runningLocation: Map, predicate: (extRunningLocation: ExtensionRunningLocation) => boolean): T[] { return extensions.filter((ext) => { const extRunningLocation = runningLocation.get(ExtensionIdentifier.toKey(extId(ext))); - return (extRunningLocation && extensionHostManager.representsRunningLocation(extRunningLocation)); + return extRunningLocation && predicate(extRunningLocation); }); } diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index ac368d46f3a..73a0d1aa29d 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -39,12 +39,21 @@ export interface IMessage { export class LocalProcessRunningLocation { public readonly type = ExtensionHostKind.LocalProcess; + public equals(other: ExtensionRunningLocation) { + return this.type === other.type; + } } export class LocalWebWorkerRunningLocation { public readonly type = ExtensionHostKind.LocalWebWorker; + public equals(other: ExtensionRunningLocation) { + return this.type === other.type; + } } export class RemoteRunningLocation { public readonly type = ExtensionHostKind.Remote; + public equals(other: ExtensionRunningLocation) { + return this.type === other.type; + } } export type ExtensionRunningLocation = LocalProcessRunningLocation | LocalWebWorkerRunningLocation | RemoteRunningLocation; diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 31d63bbb221..5a9a2c4706b 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { LocalProcessExtensionHost } from 'vs/workbench/services/extensions/electron-browser/localProcessExtensionHost'; +import { ILocalProcessExtensionHostDataProvider, LocalProcessExtensionHost } from 'vs/workbench/services/extensions/electron-browser/localProcessExtensionHost'; import { CachedExtensionScanner } from 'vs/workbench/services/extensions/electron-sandbox/cachedExtensionScanner'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString, filterByRunningLocation } from 'vs/workbench/services/extensions/common/abstractExtensionService'; +import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString, filterByExtensionHostManager, filterByExtensionHostKind, filterByRunningLocation } from 'vs/workbench/services/extensions/common/abstractExtensionService'; import * as nls from 'vs/nls'; import { runWhenIdle } from 'vs/base/common/async'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -35,7 +35,7 @@ import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remo import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { getRemoteName } from 'vs/platform/remote/common/remoteHosts'; import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment'; -import { WebWorkerExtensionHost } from 'vs/workbench/services/extensions/browser/webWorkerExtensionHost'; +import { IWebWorkerExtensionHostDataProvider, WebWorkerExtensionHost } from 'vs/workbench/services/extensions/browser/webWorkerExtensionHost'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ILogService } from 'vs/platform/log/common/log'; import { CATEGORIES } from 'vs/workbench/common/actions'; @@ -153,14 +153,14 @@ export class ExtensionService extends AbstractExtensionService implements IExten ])); } - private _createLocalExtensionHostDataProvider(isInitialStart: boolean, desiredExtensionHostKind: ExtensionHostKind) { + private _createLocalExtensionHostDataProvider(isInitialStart: boolean, desiredRunningLocation: ExtensionRunningLocation): ILocalProcessExtensionHostDataProvider & IWebWorkerExtensionHostDataProvider { return { getInitData: async () => { if (isInitialStart) { // Here we load even extensions that would be disabled by workspace trust const localExtensions = this._checkEnabledAndProposedAPI(await this._scanAllLocalExtensions(), /* ignore workspace trust */true); const runningLocation = this._runningLocationClassifier.determineRunningLocation(localExtensions, []); - const localProcessExtensions = filterByRunningLocation(localExtensions, runningLocation, desiredExtensionHostKind); + const localProcessExtensions = filterByRunningLocation(localExtensions, runningLocation, desiredRunningLocation); return { autoStart: false, extensions: localProcessExtensions @@ -168,7 +168,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten } else { // restart case const allExtensions = await this.getExtensions(); - const localProcessExtensions = filterByRunningLocation(allExtensions, this._runningLocation, desiredExtensionHostKind); + const localProcessExtensions = filterByRunningLocation(allExtensions, this._runningLocation, desiredRunningLocation); return { autoStart: true, extensions: localProcessExtensions @@ -236,11 +236,11 @@ export class ExtensionService extends AbstractExtensionService implements IExten protected _createExtensionHosts(isInitialStart: boolean): IExtensionHost[] { const result: IExtensionHost[] = []; - const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionHostKind.LocalProcess)); + const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, this._createLocalExtensionHostDataProvider(isInitialStart, new LocalProcessRunningLocation())); result.push(localProcessExtHost); if (this._enableLocalWebWorker) { - const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, this._lazyLocalWebWorker, this._createLocalExtensionHostDataProvider(isInitialStart, ExtensionHostKind.LocalWebWorker)); + const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, this._lazyLocalWebWorker, this._createLocalExtensionHostDataProvider(isInitialStart, new LocalWebWorkerRunningLocation())); result.push(webWorkerExtHost); } @@ -519,9 +519,9 @@ export class ExtensionService extends AbstractExtensionService implements IExten this._runningLocation = this._runningLocationClassifier.determineRunningLocation(localExtensions, remoteExtensions); // remove non-UI extensions from the local extensions - const localProcessExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionHostKind.LocalProcess); - const localWebWorkerExtensions = filterByRunningLocation(localExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); - remoteExtensions = filterByRunningLocation(remoteExtensions, this._runningLocation, ExtensionHostKind.Remote); + const localProcessExtensions = filterByExtensionHostKind(localExtensions, this._runningLocation, ExtensionHostKind.LocalProcess); + const localWebWorkerExtensions = filterByExtensionHostKind(localExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); + remoteExtensions = filterByExtensionHostKind(remoteExtensions, this._runningLocation, ExtensionHostKind.Remote); const result = this._registry.deltaExtensions(remoteExtensions.concat(localProcessExtensions).concat(localWebWorkerExtensions), []); if (result.removedDueToLooping.length > 0) { @@ -543,17 +543,24 @@ export class ExtensionService extends AbstractExtensionService implements IExten this._doHandleExtensionPoints(this._registry.getAllExtensionDescriptions()); - const localProcessExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalProcess); - if (localProcessExtensionHost) { - localProcessExtensionHost.start(localProcessExtensions.map(extension => extension.identifier).filter(id => this._registry.containsExtension(id))); + const localProcessExtensionHosts = this._getExtensionHostManagers(ExtensionHostKind.LocalProcess); + const filteredLocalProcessExtensions = localProcessExtensions.filter(extension => this._registry.containsExtension(extension.identifier)); + for (const extHost of localProcessExtensionHosts) { + this._startExtensionHost(extHost, filteredLocalProcessExtensions); } - const localWebWorkerExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalWebWorker); - if (localWebWorkerExtensionHost) { - localWebWorkerExtensionHost.start(localWebWorkerExtensions.map(extension => extension.identifier).filter(id => this._registry.containsExtension(id))); + const localWebWorkerExtensionHosts = this._getExtensionHostManagers(ExtensionHostKind.LocalWebWorker); + const filteredLocalWebWorkerExtensions = localWebWorkerExtensions.filter(extension => this._registry.containsExtension(extension.identifier)); + for (const extHost of localWebWorkerExtensionHosts) { + this._startExtensionHost(extHost, filteredLocalWebWorkerExtensions); } } + private _startExtensionHost(extensionHostManager: IExtensionHostManager, _extensions: IExtensionDescription[]): void { + const extensions = filterByExtensionHostManager(_extensions, this._runningLocation, extensionHostManager); + extensionHostManager.start(extensions.map(extension => extension.identifier)); + } + public override async getInspectPort(tryEnableInspector: boolean): Promise { const localProcessExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalProcess); if (localProcessExtensionHost) { From ea72a76e7b0cb342e57a80895573ddba280d7e1e Mon Sep 17 00:00:00 2001 From: Johannes Date: Fri, 11 Mar 2022 09:04:24 +0100 Subject: [PATCH 110/175] add `CURSOR_INDEX` and `CURSOR_NUMBER` snippet variables, https://github.com/microsoft/vscode/issues/144856 --- src/vs/editor/contrib/snippet/browser/snippetVariables.ts | 8 ++++++++ .../contrib/snippet/test/browser/snippetVariables.test.ts | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/vs/editor/contrib/snippet/browser/snippetVariables.ts b/src/vs/editor/contrib/snippet/browser/snippetVariables.ts index 09c08f4b026..96aebfb834d 100644 --- a/src/vs/editor/contrib/snippet/browser/snippetVariables.ts +++ b/src/vs/editor/contrib/snippet/browser/snippetVariables.ts @@ -41,6 +41,8 @@ export const KnownSnippetVariableNames: { [key: string]: true } = Object.freeze( 'TM_FILENAME_BASE': true, 'TM_DIRECTORY': true, 'TM_FILEPATH': true, + 'CURSOR_INDEX': true, // 0-offset + 'CURSOR_NUMBER': true, // 1-offset 'RELATIVE_FILEPATH': true, 'BLOCK_COMMENT_START': true, 'BLOCK_COMMENT_END': true, @@ -140,6 +142,12 @@ export class SelectionBasedVariableResolver implements VariableResolver { } else if (name === 'TM_LINE_NUMBER') { return String(this._selection.positionLineNumber); + + } else if (name === 'CURSOR_INDEX') { + return String(this._selectionIdx); + + } else if (name === 'CURSOR_NUMBER') { + return String(this._selectionIdx + 1); } return undefined; } diff --git a/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts b/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts index cfee631930b..fc53766a32e 100644 --- a/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts +++ b/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts @@ -118,6 +118,12 @@ suite('Snippet Variables Resolver', function () { assertVariableResolve(resolver, 'TM_CURRENT_LINE', 'this is line two'); assertVariableResolve(resolver, 'TM_LINE_INDEX', '1'); assertVariableResolve(resolver, 'TM_LINE_NUMBER', '2'); + assertVariableResolve(resolver, 'CURSOR_INDEX', '0'); + assertVariableResolve(resolver, 'CURSOR_NUMBER', '1'); + + resolver = new SelectionBasedVariableResolver(model, new Selection(1, 2, 2, 3), 4, undefined); + assertVariableResolve(resolver, 'CURSOR_INDEX', '4'); + assertVariableResolve(resolver, 'CURSOR_NUMBER', '5'); resolver = new SelectionBasedVariableResolver(model, new Selection(2, 3, 1, 2), 0, undefined); assertVariableResolve(resolver, 'TM_SELECTED_TEXT', 'his is line one\nth'); From 1799e12d7ba8d94a5fa661d2ea2f2d6968e0b7a9 Mon Sep 17 00:00:00 2001 From: Johannes Date: Fri, 11 Mar 2022 09:21:15 +0100 Subject: [PATCH 111/175] for now, don't deepFreeze the onDidChangeNotebook event, https://github.com/microsoft/vscode/pull/144868, https://github.com/microsoft/vscode-jupyter/issues/9327 --- src/vs/workbench/api/common/extHostNotebookDocuments.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/api/common/extHostNotebookDocuments.ts b/src/vs/workbench/api/common/extHostNotebookDocuments.ts index 50995c9f93f..fbb400ec64d 100644 --- a/src/vs/workbench/api/common/extHostNotebookDocuments.ts +++ b/src/vs/workbench/api/common/extHostNotebookDocuments.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter } from 'vs/base/common/event'; -import { deepFreeze } from 'vs/base/common/objects'; import { URI, UriComponents } from 'vs/base/common/uri'; import { ILogService } from 'vs/platform/log/common/log'; import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol'; @@ -32,7 +31,7 @@ export class ExtHostNotebookDocuments implements extHostProtocol.ExtHostNotebook $acceptModelChanged(uri: UriComponents, event: SerializableObjectWithBuffers, isDirty: boolean, newMetadata?: NotebookDocumentMetadata): void { const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri)); const e = document.acceptModelChanged(event.value, isDirty, newMetadata); - this._onDidChangeNotebookDocument.fire(deepFreeze(e)); + this._onDidChangeNotebookDocument.fire(e); } $acceptDirtyStateChanged(uri: UriComponents, isDirty: boolean): void { From d09791e6aef9101f44eb57dc6a08010bdd3b2f86 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Mar 2022 09:49:57 +0100 Subject: [PATCH 112/175] Reflect in `IExtensionService` methods that there might be multiple local process extension hosts available for inspection --- .../debugExtensionHostAction.ts | 13 ++++++--- .../extensionProfileService.ts | 14 ++++++--- .../extensionsAutoProfiler.ts | 7 +++-- .../common/abstractExtensionService.ts | 29 ++++++++++++++++--- .../extensions/common/extensionHostManager.ts | 11 ++++--- .../services/extensions/common/extensions.ts | 16 +++++++--- .../electron-browser/extensionService.ts | 8 ----- 7 files changed, 68 insertions(+), 30 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/debugExtensionHostAction.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/debugExtensionHostAction.ts index 6787e95d718..b411342d32e 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/debugExtensionHostAction.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/debugExtensionHostAction.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { IProductService } from 'vs/platform/product/common/productService'; import { Action } from 'vs/base/common/actions'; -import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { ExtensionHostKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { IDebugService } from 'vs/workbench/contrib/debug/common/debug'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; @@ -29,8 +29,8 @@ export class DebugExtensionHostAction extends Action { override async run(): Promise { - const inspectPort = await this._extensionService.getInspectPort(false); - if (!inspectPort) { + const inspectPorts = await this._extensionService.getInspectPorts(ExtensionHostKind.LocalProcess, false); + if (inspectPorts.length === 0) { const res = await this._dialogService.confirm({ type: 'info', message: nls.localize('restart1', "Profile Extensions"), @@ -45,11 +45,16 @@ export class DebugExtensionHostAction extends Action { return; } + if (inspectPorts.length > 1) { + // TODO + console.warn(`There are multiple extension hosts available for debugging. Picking the first one...`); + } + return this._debugService.startDebugging(undefined, { type: 'node', name: nls.localize('debugExtensionHost.launch.name', "Attach Extension Host"), request: 'attach', - port: inspectPort + port: inspectPorts[0] }); } } diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts index c6efc4ff567..44295a6868b 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { Event, Emitter } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IExtensionHostProfile, ProfileSession, IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionHostProfile, ProfileSession, IExtensionService, ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; import { Disposable, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { onUnexpectedError } from 'vs/base/common/errors'; import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/workbench/services/statusbar/browser/statusbar'; @@ -116,8 +116,9 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio return null; } - const inspectPort = await this._extensionService.getInspectPort(true); - if (!inspectPort) { + const inspectPorts = await this._extensionService.getInspectPorts(ExtensionHostKind.LocalProcess, true); + + if (inspectPorts.length === 0) { return this._dialogService.confirm({ type: 'info', message: nls.localize('restart1', "Profile Extensions"), @@ -131,9 +132,14 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio }); } + if (inspectPorts.length > 1) { + // TODO + console.warn(`There are multiple extension hosts available for profiling. Picking the first one...`); + } + this._setState(ProfileSessionState.Starting); - return this._instantiationService.createInstance(ExtensionHostProfiler, inspectPort).start().then((value) => { + return this._instantiationService.createInstance(ExtensionHostProfiler, inspectPorts[0]).start().then((value) => { this._profileSession = value; this._setState(ProfileSessionState.Running); }, (err) => { diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsAutoProfiler.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsAutoProfiler.ts index e967b931728..ba9f426ab94 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsAutoProfiler.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsAutoProfiler.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IExtensionService, IResponsiveStateChangeEvent, IExtensionHostProfile, ProfileSession } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionService, IResponsiveStateChangeEvent, IExtensionHostProfile, ProfileSession, ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Disposable } from 'vs/base/common/lifecycle'; import { ILogService } from 'vs/platform/log/common/log'; @@ -46,8 +46,11 @@ export class ExtensionsAutoProfiler extends Disposable implements IWorkbenchCont } private async _onDidChangeResponsiveChange(event: IResponsiveStateChangeEvent): Promise { + if (event.extensionHostKind !== ExtensionHostKind.LocalProcess) { + return; + } - const port = await this._extensionService.getInspectPort(true); + const port = await this._extensionService.getInspectPort(event.extensionHostId, true); if (!port) { return; diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 9b4c8861d12..8888f363a01 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -163,6 +163,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx private _inHandleDeltaExtensions: boolean; protected _runningLocation: Map; + private _lastExtensionHostId: number = 0; // --- Members used per extension host process protected _extensionHostManagers: IExtensionHostManager[]; @@ -618,9 +619,16 @@ export abstract class AbstractExtensionService extends Disposable implements IEx private _startExtensionHosts(isInitialStart: boolean, initialActivationEvents: string[]): void { const extensionHosts = this._createExtensionHosts(isInitialStart); extensionHosts.forEach((extensionHost) => { - const processManager: IExtensionHostManager = createExtensionHostManager(this._instantiationService, extensionHost, isInitialStart, initialActivationEvents, this._acquireInternalAPI()); + const extensionHostId = String(++this._lastExtensionHostId); + const processManager: IExtensionHostManager = createExtensionHostManager(this._instantiationService, extensionHostId, extensionHost, isInitialStart, initialActivationEvents, this._acquireInternalAPI()); processManager.onDidExit(([code, signal]) => this._onExtensionHostCrashOrExit(processManager, code, signal)); - processManager.onDidChangeResponsiveState((responsiveState) => { this._onDidChangeResponsiveChange.fire({ isResponsive: responsiveState === ResponsiveState.Responsive }); }); + processManager.onDidChangeResponsiveState((responsiveState) => { + this._onDidChangeResponsiveChange.fire({ + extensionHostId: extensionHostId, + extensionHostKind: processManager.kind, + isResponsive: responsiveState === ResponsiveState.Responsive + }); + }); this._extensionHostManagers.push(processManager); }); } @@ -772,8 +780,21 @@ export abstract class AbstractExtensionService extends Disposable implements IEx return result; } - public getInspectPort(_tryEnableInspector: boolean): Promise { - return Promise.resolve(0); + public async getInspectPort(extensionHostId: string, tryEnableInspector: boolean): Promise { + for (const extHostManager of this._extensionHostManagers) { + if (extHostManager.extensionHostId === extensionHostId) { + return extHostManager.getInspectPort(tryEnableInspector); + } + } + return 0; + } + + public async getInspectPorts(extensionHostKind: ExtensionHostKind, tryEnableInspector: boolean): Promise { + const result = await Promise.all( + this._getExtensionHostManagers(extensionHostKind).map(extHost => extHost.getInspectPort(tryEnableInspector)) + ); + // remove 0s: + return result.filter(element => Boolean(element)); } public async setRemoteEnvironment(env: { [key: string]: string | null }): Promise { diff --git a/src/vs/workbench/services/extensions/common/extensionHostManager.ts b/src/vs/workbench/services/extensions/common/extensionHostManager.ts index 17463bd24f2..1d041ff9057 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostManager.ts @@ -32,6 +32,7 @@ const LOG_EXTENSION_HOST_COMMUNICATION = false; const LOG_USE_COLORS = true; export interface IExtensionHostManager { + readonly extensionHostId: string; readonly kind: ExtensionHostKind; readonly onDidExit: Event<[number, string | null]>; readonly onDidChangeResponsiveState: Event; @@ -51,11 +52,11 @@ export interface IExtensionHostManager { setRemoteEnvironment(env: { [key: string]: string | null }): Promise; } -export function createExtensionHostManager(instantiationService: IInstantiationService, extensionHost: IExtensionHost, isInitialStart: boolean, initialActivationEvents: string[], internalExtensionService: IInternalExtensionService): IExtensionHostManager { +export function createExtensionHostManager(instantiationService: IInstantiationService, extensionHostId: string, extensionHost: IExtensionHost, isInitialStart: boolean, initialActivationEvents: string[], internalExtensionService: IInternalExtensionService): IExtensionHostManager { if (extensionHost.lazyStart && isInitialStart && initialActivationEvents.length === 0) { - return instantiationService.createInstance(LazyStartExtensionHostManager, extensionHost, internalExtensionService); + return instantiationService.createInstance(LazyStartExtensionHostManager, extensionHostId, extensionHost, internalExtensionService); } - return instantiationService.createInstance(ExtensionHostManager, extensionHost, initialActivationEvents, internalExtensionService); + return instantiationService.createInstance(ExtensionHostManager, extensionHostId, extensionHost, initialActivationEvents, internalExtensionService); } export type ExtensionHostStartupClassification = { @@ -96,6 +97,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { private _hasStarted = false; constructor( + public readonly extensionHostId: string, extensionHost: IExtensionHost, initialActivationEvents: string[], private readonly _internalExtensionService: IInternalExtensionService, @@ -463,6 +465,7 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost private _actual: ExtensionHostManager | null; constructor( + public readonly extensionHostId: string, extensionHost: IExtensionHost, private readonly _internalExtensionService: IInternalExtensionService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @@ -478,7 +481,7 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost private _createActual(reason: string): ExtensionHostManager { this._logService.info(`Creating lazy extension host: ${reason}`); - this._actual = this._register(this._instantiationService.createInstance(ExtensionHostManager, this._extensionHost, [], this._internalExtensionService)); + this._actual = this._register(this._instantiationService.createInstance(ExtensionHostManager, this.extensionHostId, this._extensionHost, [], this._internalExtensionService)); this._register(this._actual.onDidChangeResponsiveState((e) => this._onDidChangeResponsiveState.fire(e))); return this._actual; } diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 73a0d1aa29d..56b505624d6 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -206,6 +206,8 @@ export interface IWillActivateEvent { } export interface IResponsiveStateChangeEvent { + extensionHostId: string; + extensionHostKind: ExtensionHostKind; isResponsive: boolean; } @@ -308,10 +310,15 @@ export interface IExtensionService { getExtensionsStatus(): { [id: string]: IExtensionsStatus }; /** - * Return the inspect port or `0`, the latter means inspection - * is not possible. + * Return the inspect port or `0` for a certain extension host. + * `0` means inspection is not possible. */ - getInspectPort(tryEnableInspector: boolean): Promise; + getInspectPort(extensionHostId: string, tryEnableInspector: boolean): Promise; + + /** + * Return the inspect ports (if inspection is possible) for extension hosts of kind `extensionHostKind`. + */ + getInspectPorts(extensionHostKind: ExtensionHostKind, tryEnableInspector: boolean): Promise; /** * Stops the extension hosts. @@ -390,7 +397,8 @@ export class NullExtensionService implements IExtensionService { getExtension() { return Promise.resolve(undefined); } readExtensionPointContributions(_extPoint: IExtensionPoint): Promise[]> { return Promise.resolve(Object.create(null)); } getExtensionsStatus(): { [id: string]: IExtensionsStatus } { return Object.create(null); } - getInspectPort(_tryEnableInspector: boolean): Promise { return Promise.resolve(0); } + getInspectPort(_extensionHostId: string, _tryEnableInspector: boolean): Promise { return Promise.resolve(0); } + getInspectPorts(_extensionHostKind: ExtensionHostKind, _tryEnableInspector: boolean): Promise { return Promise.resolve([]); } stopExtensionHosts(): void { } async restartExtensionHost(): Promise { } async startExtensionHosts(): Promise { } diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 5a9a2c4706b..d5adedbc811 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -561,14 +561,6 @@ export class ExtensionService extends AbstractExtensionService implements IExten extensionHostManager.start(extensions.map(extension => extension.identifier)); } - public override async getInspectPort(tryEnableInspector: boolean): Promise { - const localProcessExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalProcess); - if (localProcessExtensionHost) { - return localProcessExtensionHost.getInspectPort(tryEnableInspector); - } - return 0; - } - public _onExtensionHostExit(code: number): void { // Dispose everything associated with the extension host this.stopExtensionHosts(); From f6ad20b09a32bfcf964db7c2d43d33140547cbd7 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Mar 2022 10:04:00 +0100 Subject: [PATCH 113/175] Ask all local extension hosts to resolve canonical URIs --- .../api/browser/mainThreadExtensionService.ts | 4 +-- .../workbench/api/common/extHost.protocol.ts | 5 +++- .../api/common/extHostExtensionService.ts | 7 +++-- .../common/abstractExtensionService.ts | 9 ------ .../extensions/common/extensionHostManager.ts | 17 +++++------ .../extensions/common/extensionHostProxy.ts | 5 +++- .../electron-browser/extensionService.ts | 30 +++++++++++++++++-- 7 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadExtensionService.ts b/src/vs/workbench/api/browser/mainThreadExtensionService.ts index a77cf0e46e6..95d3b69e79d 100644 --- a/src/vs/workbench/api/browser/mainThreadExtensionService.ts +++ b/src/vs/workbench/api/browser/mainThreadExtensionService.ts @@ -197,9 +197,9 @@ class ExtensionHostProxy implements IExtensionHostProxy { resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise { return this._actual.$resolveAuthority(remoteAuthority, resolveAttempt); } - async getCanonicalURI(remoteAuthority: string, uri: URI): Promise { + async getCanonicalURI(remoteAuthority: string, uri: URI): Promise { const uriComponents = await this._actual.$getCanonicalURI(remoteAuthority, uri); - return URI.revive(uriComponents); + return (uriComponents ? URI.revive(uriComponents) : uriComponents); } startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise { return this._actual.$startExtensionHost(enabledExtensionIds); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 64f9f7de22a..73db462b209 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1339,7 +1339,10 @@ export interface ExtHostSearchShape { export interface ExtHostExtensionServiceShape { $resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise; - $getCanonicalURI(remoteAuthority: string, uri: UriComponents): Promise; + /** + * Returns `null` if no resolver for `remoteAuthority` is found. + */ + $getCanonicalURI(remoteAuthority: string, uri: UriComponents): Promise; $startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise; $extensionTestsExecute(): Promise; $extensionTestsExit(code: number): Promise; diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index 7d9e044afcc..3042ed465c3 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -753,12 +753,13 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme } } - public async $getCanonicalURI(remoteAuthority: string, uriComponents: UriComponents): Promise { + public async $getCanonicalURI(remoteAuthority: string, uriComponents: UriComponents): Promise { this._logService.info(`$getCanonicalURI invoked for authority (${getRemoteAuthorityPrefix(remoteAuthority)})`); - const { authorityPrefix, resolver } = await this._activateAndGetResolver(remoteAuthority); + const { resolver } = await this._activateAndGetResolver(remoteAuthority); if (!resolver) { - throw new Error(`Cannot get canonical URI because no remote extension is installed to resolve ${authorityPrefix}`); + // Return `null` if no resolver for `remoteAuthority` is found. + return null; } const uri = URI.revive(uriComponents); diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 8888f363a01..e8cfe6e0f61 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -267,15 +267,6 @@ export abstract class AbstractExtensionService extends Disposable implements IEx protected abstract _pickRunningLocation(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation | null; - protected _getExtensionHostManager(kind: ExtensionHostKind): IExtensionHostManager | null { - for (const extensionHostManager of this._extensionHostManagers) { - if (extensionHostManager.kind === kind) { - return extensionHostManager; - } - } - return null; - } - protected _getExtensionHostManagers(kind: ExtensionHostKind): IExtensionHostManager[] { return this._extensionHostManagers.filter(extHostManager => extHostManager.kind === kind); } diff --git a/src/vs/workbench/services/extensions/common/extensionHostManager.ts b/src/vs/workbench/services/extensions/common/extensionHostManager.ts index 1d041ff9057..911d5829102 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostManager.ts @@ -45,7 +45,10 @@ export interface IExtensionHostManager { activationEventIsDone(activationEvent: string): boolean; getInspectPort(tryEnableInspector: boolean): Promise; resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise; - getCanonicalURI(remoteAuthority: string, uri: URI): Promise; + /** + * Returns `null` if no resolver for `remoteAuthority` is found. + */ + getCanonicalURI(remoteAuthority: string, uri: URI): Promise; start(enabledExtensionIds: ExtensionIdentifier[]): Promise; extensionTestsExecute(): Promise; extensionTestsSendExit(exitCode: number): Promise; @@ -383,18 +386,12 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { } } - public async getCanonicalURI(remoteAuthority: string, uri: URI): Promise { - const authorityPlusIndex = remoteAuthority.indexOf('+'); - if (authorityPlusIndex === -1) { - // This authority does not use a resolver - return uri; - } + public async getCanonicalURI(remoteAuthority: string, uri: URI): Promise { const proxy = await this._proxy; if (!proxy) { throw new Error(`Cannot resolve canonical URI`); } - const result = await proxy.getCanonicalURI(remoteAuthority, uri); - return URI.revive(result); + return proxy.getCanonicalURI(remoteAuthority, uri); } public async start(enabledExtensionIds: ExtensionIdentifier[]): Promise { @@ -564,7 +561,7 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost } }; } - public async getCanonicalURI(remoteAuthority: string, uri: URI): Promise { + public async getCanonicalURI(remoteAuthority: string, uri: URI): Promise { await this._startCalled.wait(); if (this._actual) { return this._actual.getCanonicalURI(remoteAuthority, uri); diff --git a/src/vs/workbench/services/extensions/common/extensionHostProxy.ts b/src/vs/workbench/services/extensions/common/extensionHostProxy.ts index f3acf4420a0..d021dda0f0d 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostProxy.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostProxy.ts @@ -27,7 +27,10 @@ export type IResolveAuthorityResult = IResolveAuthorityErrorResult | IResolveAut export interface IExtensionHostProxy { resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise; - getCanonicalURI(remoteAuthority: string, uri: URI): Promise; + /** + * Returns `null` if no resolver for `remoteAuthority` is found. + */ + getCanonicalURI(remoteAuthority: string, uri: URI): Promise; startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise; extensionTestsExecute(): Promise; extensionTestsExit(code: number): Promise; diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index d5adedbc811..9e6b93c9fa0 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -49,6 +49,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { StopWatch } from 'vs/base/common/stopwatch'; import { isCI } from 'vs/base/common/platform'; import { IResolveAuthorityErrorResult } from 'vs/workbench/services/extensions/common/extensionHostProxy'; +import { URI } from 'vs/base/common/uri'; export class ExtensionService extends AbstractExtensionService implements IExtensionService { @@ -387,6 +388,32 @@ export class ExtensionService extends AbstractExtensionService implements IExten throw new RemoteAuthorityResolverError(bestErrorResult!.error.message, bestErrorResult!.error.code, bestErrorResult!.error.detail); } + private async _getCanonicalURI(remoteAuthority: string, uri: URI): Promise { + + const authorityPlusIndex = remoteAuthority.indexOf('+'); + if (authorityPlusIndex === -1) { + // This authority does not use a resolver + return uri; + } + + const localProcessExtensionHosts = this._getExtensionHostManagers(ExtensionHostKind.LocalProcess); + if (localProcessExtensionHosts.length === 0) { + // no local process extension hosts + throw new Error(`Cannot resolve canonical URI`); + } + + const results = await Promise.all(localProcessExtensionHosts.map(extHost => extHost.getCanonicalURI(remoteAuthority, uri))); + + for (const result of results) { + if (result) { + return result; + } + } + + // we can only reach this if there was no resolver extension that can return the cannonical uri + throw new Error(`Cannot get canonical URI because no extension is installed to resolve ${getRemoteAuthorityPrefix(remoteAuthority)}`); + } + private async _resolveAuthorityAgain(): Promise { const remoteAuthority = this._environmentService.remoteAuthority; if (!remoteAuthority) { @@ -421,12 +448,11 @@ export class ExtensionService extends AbstractExtensionService implements IExten // The current remote authority resolver cannot give the canonical URI for this URI return uri; } - const localProcessExtensionHost = this._getExtensionHostManager(ExtensionHostKind.LocalProcess)!; if (isCI) { this._logService.info(`Invoking getCanonicalURI for authority ${getRemoteAuthorityPrefix(remoteAuthority)}...`); } try { - return localProcessExtensionHost.getCanonicalURI(remoteAuthority, uri); + return this._getCanonicalURI(remoteAuthority, uri); } finally { if (isCI) { this._logService.info(`getCanonicalURI returned for authority ${getRemoteAuthorityPrefix(remoteAuthority)}.`); From 42dd8b0f7c1713128d6154f64c1fae95bed96b7c Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Mar 2022 10:24:50 +0100 Subject: [PATCH 114/175] Reduce usage of `ExtensionHostKind` to establish the running location --- .../abstractRuntimeExtensionsEditor.ts | 4 +- .../extensions/browser/extensionService.ts | 6 +- .../browser/webWorkerExtensionHost.ts | 4 +- .../common/abstractExtensionService.ts | 2 +- .../extensions/common/extensionHostManager.ts | 17 ++-- .../services/extensions/common/extensions.ts | 32 ++++---- .../extensions/common/remoteExtensionHost.ts | 4 +- .../electron-browser/extensionService.ts | 9 +- .../localProcessExtensionHost.ts | 4 +- .../test/browser/extensionService.test.ts | 82 +++++++++---------- 10 files changed, 88 insertions(+), 76 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts index a570f894674..03cd181a377 100644 --- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts @@ -11,7 +11,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionsWorkbenchService, IExtension } from 'vs/workbench/contrib/extensions/common/extensions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IExtensionService, IExtensionsStatus, IExtensionHostProfile, ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionService, IExtensionsStatus, IExtensionHostProfile, LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; import { IListVirtualDelegate, IListRenderer } from 'vs/base/browser/ui/list/list'; import { WorkbenchList } from 'vs/platform/list/browser/listService'; import { append, $, Dimension, clearNode, addDisposableListener } from 'vs/base/browser/dom'; @@ -370,7 +370,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { } let extraLabel: string | null = null; - if (element.status.runningLocation && element.status.runningLocation.type === ExtensionHostKind.LocalWebWorker) { + if (element.status.runningLocation && element.status.runningLocation.equals(new LocalWebWorkerRunningLocation())) { extraLabel = `$(globe) web worker`; } else if (element.description.extensionLocation.scheme === Schemas.vscodeRemote) { const hostLabel = this._labelService.getHostLabel(Schemas.vscodeRemote, this._environmentService.remoteAuthority); diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts index 1734df26581..0d0bbeb172e 100644 --- a/src/vs/workbench/services/extensions/browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/browser/extensionService.ts @@ -174,12 +174,14 @@ export class ExtensionService extends AbstractExtensionService implements IExten protected _createExtensionHosts(_isInitialStart: boolean): IExtensionHost[] { const result: IExtensionHost[] = []; - const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, false, this._createLocalExtensionHostDataProvider(new LocalWebWorkerRunningLocation())); + const localWebWorkerRunningLocation = new LocalWebWorkerRunningLocation(); + const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, localWebWorkerRunningLocation, false, this._createLocalExtensionHostDataProvider(localWebWorkerRunningLocation)); result.push(webWorkerExtHost); const remoteAgentConnection = this._remoteAgentService.getConnection(); if (remoteAgentConnection) { - const remoteExtHost = this._instantiationService.createInstance(RemoteExtensionHost, this._createRemoteExtensionHostDataProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory); + const remoteRunningLocation = new RemoteRunningLocation(); + const remoteExtHost = this._instantiationService.createInstance(RemoteExtensionHost, remoteRunningLocation, this._createRemoteExtensionHostDataProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory); result.push(remoteExtHost); } diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index e9a47781a81..85bff25d857 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -16,7 +16,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions' import * as platform from 'vs/base/common/platform'; import * as dom from 'vs/base/browser/dom'; import { URI } from 'vs/base/common/uri'; -import { IExtensionHost, ExtensionHostLogFileName, ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionHost, ExtensionHostLogFileName, LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; import { IProductService } from 'vs/platform/product/common/productService'; import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; import { joinPath } from 'vs/base/common/resources'; @@ -43,7 +43,6 @@ export interface IWebWorkerExtensionHostDataProvider { export class WebWorkerExtensionHost extends Disposable implements IExtensionHost { - public readonly kind = ExtensionHostKind.LocalWebWorker; public readonly remoteAuthority = null; public readonly lazyStart: boolean; public readonly extensions = new ExtensionDescriptionRegistry([]); @@ -59,6 +58,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost private readonly _extensionHostLogFile: URI; constructor( + public readonly runningLocation: LocalWebWorkerRunningLocation, lazyStart: boolean, private readonly _initDataProvider: IWebWorkerExtensionHostDataProvider, @ITelemetryService private readonly _telemetryService: ITelemetryService, diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index e8cfe6e0f61..29a82d3aab8 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -1259,7 +1259,7 @@ function _filterByRunningLocation(extensions: T[], extId: (item: T) => Extens } export function filterByExtensionHostKind(extensions: IExtensionDescription[], runningLocation: Map, desiredExtensionHostKind: ExtensionHostKind): IExtensionDescription[] { - return _filterExtensions(extensions, ext => ext.identifier, runningLocation, extRunningLocation => extRunningLocation.type === desiredExtensionHostKind); + return _filterExtensions(extensions, ext => ext.identifier, runningLocation, extRunningLocation => extRunningLocation.kind === desiredExtensionHostKind); } export function filterByExtensionHostManager(extensions: IExtensionDescription[], runningLocation: Map, extensionHostManager: IExtensionHostManager): IExtensionDescription[] { diff --git a/src/vs/workbench/services/extensions/common/extensionHostManager.ts b/src/vs/workbench/services/extensions/common/extensionHostManager.ts index 911d5829102..c809d5a4b5a 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostManager.ts @@ -82,7 +82,6 @@ export type ExtensionHostStartupEvent = { class ExtensionHostManager extends Disposable implements IExtensionHostManager { - public readonly kind: ExtensionHostKind; public readonly onDidExit: Event<[number, string | null]>; private readonly _onDidChangeResponsiveState: Emitter = this._register(new Emitter()); @@ -99,6 +98,10 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { private _proxy: Promise | null; private _hasStarted = false; + public get kind(): ExtensionHostKind { + return this._extensionHost.runningLocation.kind; + } + constructor( public readonly extensionHostId: string, extensionHost: IExtensionHost, @@ -116,7 +119,6 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { this._customers = []; this._extensionHost = extensionHost; - this.kind = this._extensionHost.kind; this.onDidExit = this._extensionHost.onExit; const startingTelemetryEvent: ExtensionHostStartupEvent = { @@ -426,7 +428,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { } public representsRunningLocation(runningLocation: ExtensionRunningLocation): boolean { - return (this.kind === runningLocation.type); + return this._extensionHost.runningLocation.equals(runningLocation); } public async deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise { @@ -452,7 +454,7 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager { * Waits until `start()` and only if it has extensions proceeds to really start. */ class LazyStartExtensionHostManager extends Disposable implements IExtensionHostManager { - public readonly kind: ExtensionHostKind; + public readonly onDidExit: Event<[number, string | null]>; private readonly _onDidChangeResponsiveState: Emitter = this._register(new Emitter()); public readonly onDidChangeResponsiveState: Event = this._onDidChangeResponsiveState.event; @@ -461,6 +463,10 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost private _startCalled: Barrier; private _actual: ExtensionHostManager | null; + public get kind(): ExtensionHostKind { + return this._extensionHost.runningLocation.kind; + } + constructor( public readonly extensionHostId: string, extensionHost: IExtensionHost, @@ -470,7 +476,6 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost ) { super(); this._extensionHost = extensionHost; - this.kind = extensionHost.kind; this.onDidExit = extensionHost.onExit; this._startCalled = new Barrier(); this._actual = null; @@ -500,7 +505,7 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost } } public representsRunningLocation(runningLocation: ExtensionRunningLocation): boolean { - return (this.kind === runningLocation.type); + return this._extensionHost.runningLocation.equals(runningLocation); } public async deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise { await this._startCalled.wait(); diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 56b505624d6..10914bc42e3 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -38,21 +38,30 @@ export interface IMessage { } export class LocalProcessRunningLocation { - public readonly type = ExtensionHostKind.LocalProcess; + public readonly kind = ExtensionHostKind.LocalProcess; public equals(other: ExtensionRunningLocation) { - return this.type === other.type; + return this.kind === other.kind; + } + public asString(): string { + return 'LocalProcess'; } } export class LocalWebWorkerRunningLocation { - public readonly type = ExtensionHostKind.LocalWebWorker; + public readonly kind = ExtensionHostKind.LocalWebWorker; public equals(other: ExtensionRunningLocation) { - return this.type === other.type; + return this.kind === other.kind; + } + public asString(): string { + return 'LocalWebWorker'; } } export class RemoteRunningLocation { - public readonly type = ExtensionHostKind.Remote; + public readonly kind = ExtensionHostKind.Remote; public equals(other: ExtensionRunningLocation) { - return this.type === other.type; + return this.kind === other.kind; + } + public asString(): string { + return 'Remote'; } } export type ExtensionRunningLocation = LocalProcessRunningLocation | LocalWebWorkerRunningLocation | RemoteRunningLocation; @@ -61,14 +70,7 @@ export function extensionRunningLocationToString(location: ExtensionRunningLocat if (!location) { return 'None'; } - switch (location.type) { - case ExtensionHostKind.LocalProcess: - return 'LocalProcess'; - case ExtensionHostKind.LocalWebWorker: - return 'LocalWebWorker'; - case ExtensionHostKind.Remote: - return 'Remote'; - } + return location.asString(); } export interface IExtensionsStatus { @@ -137,7 +139,7 @@ export function extensionHostKindToString(kind: ExtensionHostKind): string { } export interface IExtensionHost { - readonly kind: ExtensionHostKind; + readonly runningLocation: ExtensionRunningLocation; readonly remoteAuthority: string | null; readonly lazyStart: boolean; /** diff --git a/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts b/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts index 9bf8f0850fc..ba239efb719 100644 --- a/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts +++ b/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts @@ -28,7 +28,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; import { parseExtensionDevOptions } from 'vs/workbench/services/extensions/common/extensionDevOptions'; import { createMessageOfType, isMessageOfType, MessageType, IExtensionHostInitData, UIKind } from 'vs/workbench/services/extensions/common/extensionHostProtocol'; -import { ExtensionHostKind, ExtensionHostLogFileName, IExtensionHost } from 'vs/workbench/services/extensions/common/extensions'; +import { ExtensionHostLogFileName, IExtensionHost, RemoteRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { Extensions, IOutputChannelRegistry } from 'vs/workbench/services/output/common/output'; @@ -50,7 +50,6 @@ export interface IRemoteExtensionHostDataProvider { export class RemoteExtensionHost extends Disposable implements IExtensionHost { - public readonly kind = ExtensionHostKind.Remote; public readonly remoteAuthority: string; public readonly lazyStart = false; public readonly extensions = new ExtensionDescriptionRegistry([]); @@ -64,6 +63,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost { private readonly _isExtensionDevHost: boolean; constructor( + public readonly runningLocation: RemoteRunningLocation, private readonly _initDataProvider: IRemoteExtensionHostDataProvider, private readonly _socketFactory: ISocketFactory, @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService, diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 9e6b93c9fa0..183624a670c 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -237,17 +237,20 @@ export class ExtensionService extends AbstractExtensionService implements IExten protected _createExtensionHosts(isInitialStart: boolean): IExtensionHost[] { const result: IExtensionHost[] = []; - const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, this._createLocalExtensionHostDataProvider(isInitialStart, new LocalProcessRunningLocation())); + const localProcessRunningLocation = new LocalProcessRunningLocation(); + const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, localProcessRunningLocation, this._createLocalExtensionHostDataProvider(isInitialStart, localProcessRunningLocation)); result.push(localProcessExtHost); if (this._enableLocalWebWorker) { - const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, this._lazyLocalWebWorker, this._createLocalExtensionHostDataProvider(isInitialStart, new LocalWebWorkerRunningLocation())); + const localWebWorkerRunningLocation = new LocalWebWorkerRunningLocation(); + const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, localWebWorkerRunningLocation, this._lazyLocalWebWorker, this._createLocalExtensionHostDataProvider(isInitialStart, localWebWorkerRunningLocation)); result.push(webWorkerExtHost); } const remoteAgentConnection = this._remoteAgentService.getConnection(); if (remoteAgentConnection) { - const remoteExtHost = this._instantiationService.createInstance(RemoteExtensionHost, this._createRemoteExtensionHostDataProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory); + const remoteRunningLocation = new RemoteRunningLocation(); + const remoteExtHost = this._instantiationService.createInstance(RemoteExtensionHost, remoteRunningLocation, this._createRemoteExtensionHostDataProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory); result.push(remoteExtHost); } diff --git a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts index 90d2fd0f374..2f7e9b944f6 100644 --- a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts @@ -34,7 +34,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions' import { parseExtensionDevOptions } from '../common/extensionDevOptions'; import { VSBuffer } from 'vs/base/common/buffer'; import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug'; -import { IExtensionHost, ExtensionHostLogFileName, ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionHost, ExtensionHostLogFileName, LocalProcessRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { joinPath } from 'vs/base/common/resources'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -106,7 +106,6 @@ class ExtensionHostProcess { export class LocalProcessExtensionHost implements IExtensionHost { - public readonly kind = ExtensionHostKind.LocalProcess; public readonly remoteAuthority = null; public readonly lazyStart = false; public readonly extensions = new ExtensionDescriptionRegistry([]); @@ -137,6 +136,7 @@ export class LocalProcessExtensionHost implements IExtensionHost { private readonly _extensionHostLogFile: URI; constructor( + public readonly runningLocation: LocalProcessRunningLocation, private readonly _initDataProvider: ILocalProcessExtensionHostDataProvider, @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService, @INotificationService private readonly _notificationService: INotificationService, diff --git a/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts b/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts index 95c7347a8c0..7eb7f277e77 100644 --- a/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts +++ b/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts @@ -16,74 +16,74 @@ suite('BrowserExtensionService', () => { assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], true, true, ExtensionRunningPreference.None), null); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, false, ExtensionRunningPreference.None)!.type, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, true, ExtensionRunningPreference.None)!.type, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); }); }); From 38daf83216351f2fc2188190bd84b522872701e1 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Mar 2022 15:40:07 +0100 Subject: [PATCH 115/175] Delay picking a running location until all desired extension host kinds have been computed --- .../extensions/browser/extensionService.ts | 24 ++--- .../common/abstractExtensionService.ts | 100 ++++++++++++------ .../services/extensions/common/extensions.ts | 18 ++-- .../electron-browser/extensionService.ts | 32 +++--- .../test/browser/extensionService.test.ts | 82 +++++++------- 5 files changed, 146 insertions(+), 110 deletions(-) diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts index 0d0bbeb172e..7e9a24b23e5 100644 --- a/src/vs/workbench/services/extensions/browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/browser/extensionService.ts @@ -9,7 +9,7 @@ import { IWorkbenchExtensionEnablementService, IWebExtensionsScannerService } fr import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IExtensionService, IExtensionHost, toExtensionDescription, ExtensionRunningLocation, extensionRunningLocationToString, ExtensionHostKind, RemoteRunningLocation, LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionService, IExtensionHost, toExtensionDescription, ExtensionRunningLocation, ExtensionHostKind, RemoteRunningLocation, LocalWebWorkerRunningLocation, extensionHostKindToString } from 'vs/workbench/services/extensions/common/extensions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { IProductService } from 'vs/platform/product/common/productService'; @@ -130,20 +130,20 @@ export class ExtensionService extends AbstractExtensionService implements IExten }; } - protected _pickRunningLocation(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation | null { + protected _pickExtensionHostKind(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionHostKind | null { const result = ExtensionService.pickRunningLocation(extensionKinds, isInstalledLocally, isInstalledRemotely, preference); - this._logService.trace(`pickRunningLocation for ${extensionId.value}, extension kinds: [${extensionKinds.join(', ')}], isInstalledLocally: ${isInstalledLocally}, isInstalledRemotely: ${isInstalledRemotely}, preference: ${extensionRunningPreferenceToString(preference)} => ${extensionRunningLocationToString(result)}`); + this._logService.trace(`pickRunningLocation for ${extensionId.value}, extension kinds: [${extensionKinds.join(', ')}], isInstalledLocally: ${isInstalledLocally}, isInstalledRemotely: ${isInstalledRemotely}, preference: ${extensionRunningPreferenceToString(preference)} => ${extensionHostKindToString(result)}`); return result; } - public static pickRunningLocation(extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation | null { - const result: ExtensionRunningLocation[] = []; + public static pickRunningLocation(extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionHostKind | null { + const result: ExtensionHostKind[] = []; let canRunRemotely = false; for (const extensionKind of extensionKinds) { if (extensionKind === 'ui' && isInstalledRemotely) { // ui extensions run remotely if possible (but only as a last resort) if (preference === ExtensionRunningPreference.Remote) { - return new RemoteRunningLocation(); + return ExtensionHostKind.Remote; } else { canRunRemotely = true; } @@ -151,22 +151,22 @@ export class ExtensionService extends AbstractExtensionService implements IExten if (extensionKind === 'workspace' && isInstalledRemotely) { // workspace extensions run remotely if possible if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Remote) { - return new RemoteRunningLocation(); + return ExtensionHostKind.Remote; } else { - result.push(new RemoteRunningLocation()); + result.push(ExtensionHostKind.Remote); } } if (extensionKind === 'web' && (isInstalledLocally || isInstalledRemotely)) { // web worker extensions run in the local web worker if possible if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Local) { - return new LocalWebWorkerRunningLocation(); + return ExtensionHostKind.LocalWebWorker; } else { - result.push(new LocalWebWorkerRunningLocation()); + result.push(ExtensionHostKind.LocalWebWorker); } } } if (canRunRemotely) { - result.push(new RemoteRunningLocation()); + result.push(ExtensionHostKind.Remote); } return (result.length > 0 ? result[0] : null); } @@ -201,7 +201,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten const remoteAgentConnection = this._remoteAgentService.getConnection(); // `determineRunningLocation` will look at the complete picture (e.g. an extension installed on both sides), // takes care of duplicates and picks a running location for each extension - this._runningLocation = this._runningLocationClassifier.determineRunningLocation(localExtensions, remoteExtensions); + this._runningLocation = this._computeInitialRunningLocation(localExtensions, remoteExtensions); // Some remote extensions could run locally in the web worker, so store them const remoteExtensionsThatNeedToRunLocally = filterByExtensionHostKind(remoteExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 29a82d3aab8..000454328c4 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -15,7 +15,7 @@ import { IWebExtensionsScannerService, IWorkbenchExtensionEnablementService } fr import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { ActivationTimes, ExtensionPointContribution, IExtensionService, IExtensionsStatus, IMessage, IWillActivateEvent, IResponsiveStateChangeEvent, toExtension, IExtensionHost, ActivationKind, ExtensionHostKind, toExtensionDescription, ExtensionRunningLocation, extensionHostKindToString, ExtensionActivationReason, IInternalExtensionService, RemoteRunningLocation, LocalProcessRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; +import { ActivationTimes, ExtensionPointContribution, IExtensionService, IExtensionsStatus, IMessage, IWillActivateEvent, IResponsiveStateChangeEvent, toExtension, IExtensionHost, ActivationKind, ExtensionHostKind, toExtensionDescription, ExtensionRunningLocation, extensionHostKindToString, ExtensionActivationReason, IInternalExtensionService, RemoteRunningLocation, LocalProcessRunningLocation, LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionMessageCollector, ExtensionPoint, ExtensionsRegistry, IExtensionPoint, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; import { ResponsiveState } from 'vs/workbench/services/extensions/common/rpcProtocol'; @@ -147,7 +147,6 @@ export abstract class AbstractExtensionService extends Disposable implements IEx protected readonly _onDidChangeResponsiveChange = this._register(new Emitter()); public readonly onDidChangeResponsiveChange: Event = this._onDidChangeResponsiveChange.event; - protected readonly _runningLocationClassifier: ExtensionRunningLocationClassifier; protected readonly _registry: ExtensionDescriptionRegistry; private readonly _registryLock: Lock; @@ -188,11 +187,6 @@ export abstract class AbstractExtensionService extends Disposable implements IEx ) { super(); - this._runningLocationClassifier = new ExtensionRunningLocationClassifier( - (extension) => this._getExtensionKind(extension), - (extensionId, extensionKinds, isInstalledLocally, isInstalledRemotely, preference) => this._pickRunningLocation(extensionId, extensionKinds, isInstalledLocally, isInstalledRemotely, preference) - ); - // help the file service to activate providers by activating extensions by file system event this._register(this._fileService.onWillActivateFileSystemProvider(e => { if (e.scheme !== Schemas.vscodeRemote) { @@ -265,7 +259,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx return this._extensionManifestPropertiesService.getExtensionKind(extensionDescription); } - protected abstract _pickRunningLocation(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation | null; + protected abstract _pickExtensionHostKind(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionHostKind | null; protected _getExtensionHostManagers(kind: ExtensionHostKind): IExtensionHostManager[] { return this._extensionHostManagers.filter(extHostManager => extHostManager.kind === kind); @@ -280,6 +274,54 @@ export abstract class AbstractExtensionService extends Disposable implements IEx return null; } + //#region running location + + protected _computeInitialRunningLocation(localExtensions: IExtensionDescription[], remoteExtensions: IExtensionDescription[]): Map { + const extensionHostKinds = ExtensionHostKindClassifier.determineExtensionHostKinds( + localExtensions, + remoteExtensions, + (extension) => this._getExtensionKind(extension), + (extensionId, extensionKinds, isInstalledLocally, isInstalledRemotely, preference) => this._pickExtensionHostKind(extensionId, extensionKinds, isInstalledLocally, isInstalledRemotely, preference) + ); + + const result = new Map(); + for (const [extensionIdKey, extensionHostKind] of extensionHostKinds) { + let runningLocation: ExtensionRunningLocation | null = null; + if (extensionHostKind === ExtensionHostKind.LocalProcess) { + runningLocation = new LocalProcessRunningLocation(); + } else if (extensionHostKind === ExtensionHostKind.LocalWebWorker) { + runningLocation = new LocalWebWorkerRunningLocation(); + } else if (extensionHostKind === ExtensionHostKind.Remote) { + runningLocation = new RemoteRunningLocation(); + } + result.set(extensionIdKey, runningLocation); + } + return result; + } + + /** + * Update `this._runningLocation` with running locations for newly enabled/installed extensions. + */ + private _updateRunningLocationForAddedExtensions(toAdd: IExtensionDescription[]): void { + // Determine new running location + for (const extension of toAdd) { + const extensionKind = this._getExtensionKind(extension); + const isRemote = extension.extensionLocation.scheme === Schemas.vscodeRemote; + const extensionHostKind = this._pickExtensionHostKind(extension.identifier, extensionKind, !isRemote, isRemote, ExtensionRunningPreference.None); + let runningLocation: ExtensionRunningLocation | null = null; + if (extensionHostKind === ExtensionHostKind.LocalProcess) { + runningLocation = new LocalProcessRunningLocation(); + } else if (extensionHostKind === ExtensionHostKind.LocalWebWorker) { + runningLocation = new LocalWebWorkerRunningLocation(); + } else if (extensionHostKind === ExtensionHostKind.Remote) { + runningLocation = new RemoteRunningLocation(); + } + this._runningLocation.set(ExtensionIdentifier.toKey(extension.identifier), runningLocation); + } + } + + //#endregion + //#region deltaExtensions private async _handleDeltaExtensions(item: DeltaExtensionsQueueItem): Promise { @@ -389,12 +431,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx } // Determine new running location - for (const extension of toAdd) { - const extensionKind = this._getExtensionKind(extension); - const isRemote = extension.extensionLocation.scheme === Schemas.vscodeRemote; - const runningLocation = this._pickRunningLocation(extension.identifier, extensionKind, !isRemote, isRemote, ExtensionRunningPreference.None); - this._runningLocation.set(ExtensionIdentifier.toKey(extension.identifier), runningLocation); - } + this._updateRunningLocationForAddedExtensions(toAdd); const promises = this._extensionHostManagers.map( extHostManager => this._updateExtensionsOnExtHost(extHostManager, toAdd, toRemove, removedRunningLocation) @@ -424,8 +461,8 @@ export abstract class AbstractExtensionService extends Disposable implements IEx const extensionKind = this._getExtensionKind(extension); const isRemote = extension.extensionLocation.scheme === Schemas.vscodeRemote; - const runningLocation = this._pickRunningLocation(extension.identifier, extensionKind, !isRemote, isRemote, ExtensionRunningPreference.None); - if (!runningLocation) { + const extensionHostKind = this._pickExtensionHostKind(extension.identifier, extensionKind, !isRemote, isRemote, ExtensionRunningPreference.None); + if (extensionHostKind === null) { return false; } @@ -1100,25 +1137,28 @@ class ExtensionInfo { } } -class ExtensionRunningLocationClassifier { - constructor( - private readonly getExtensionKind: (extensionDescription: IExtensionDescription) => ExtensionKind[], - private readonly pickRunningLocation: (extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference) => ExtensionRunningLocation | null, - ) { - } +class ExtensionHostKindClassifier { - private _toExtensionWithKind(extensions: IExtensionDescription[]): Map { + private static _toExtensionWithKind( + extensions: IExtensionDescription[], + getExtensionKind: (extensionDescription: IExtensionDescription) => ExtensionKind[] + ): Map { const result = new Map(); extensions.forEach((desc) => { - const ext = new ExtensionWithKind(desc, this.getExtensionKind(desc)); + const ext = new ExtensionWithKind(desc, getExtensionKind(desc)); result.set(ext.key, ext); }); return result; } - public determineRunningLocation(_localExtensions: IExtensionDescription[], _remoteExtensions: IExtensionDescription[]): Map { - const localExtensions = this._toExtensionWithKind(_localExtensions); - const remoteExtensions = this._toExtensionWithKind(_remoteExtensions); + public static determineExtensionHostKinds( + _localExtensions: IExtensionDescription[], + _remoteExtensions: IExtensionDescription[], + getExtensionKind: (extensionDescription: IExtensionDescription) => ExtensionKind[], + pickExtensionHostKind: (extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference) => ExtensionHostKind | null + ): Map { + const localExtensions = this._toExtensionWithKind(_localExtensions, getExtensionKind); + const remoteExtensions = this._toExtensionWithKind(_remoteExtensions, getExtensionKind); const allExtensions = new Map(); const collectExtension = (ext: ExtensionWithKind) => { @@ -1133,7 +1173,7 @@ class ExtensionRunningLocationClassifier { localExtensions.forEach((ext) => collectExtension(ext)); remoteExtensions.forEach((ext) => collectExtension(ext)); - const runningLocation = new Map(); + const extensionHostKinds = new Map(); allExtensions.forEach((ext) => { const isInstalledLocally = Boolean(ext.local); const isInstalledRemotely = Boolean(ext.remote); @@ -1148,10 +1188,10 @@ class ExtensionRunningLocationClassifier { preference = ExtensionRunningPreference.Remote; } - runningLocation.set(ext.key, this.pickRunningLocation(ext.identifier, ext.kind, isInstalledLocally, isInstalledRemotely, preference)); + extensionHostKinds.set(ext.key, pickExtensionHostKind(ext.identifier, ext.kind, isInstalledLocally, isInstalledRemotely, preference)); }); - return runningLocation; + return extensionHostKinds; } } diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 10914bc42e3..f549c009a7b 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -66,13 +66,6 @@ export class RemoteRunningLocation { } export type ExtensionRunningLocation = LocalProcessRunningLocation | LocalWebWorkerRunningLocation | RemoteRunningLocation; -export function extensionRunningLocationToString(location: ExtensionRunningLocation | null) { - if (!location) { - return 'None'; - } - return location.asString(); -} - export interface IExtensionsStatus { messages: IMessage[]; activationTimes: ActivationTimes | undefined; @@ -125,12 +118,15 @@ export interface IExtensionHostProfile { } export const enum ExtensionHostKind { - LocalProcess, - LocalWebWorker, - Remote + LocalProcess = 1, + LocalWebWorker = 2, + Remote = 3 } -export function extensionHostKindToString(kind: ExtensionHostKind): string { +export function extensionHostKindToString(kind: ExtensionHostKind | null): string { + if (kind === null) { + return 'None'; + } switch (kind) { case ExtensionHostKind.LocalProcess: return 'LocalProcess'; case ExtensionHostKind.LocalWebWorker: return 'LocalWebWorker'; diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 183624a670c..edad11cc75b 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -22,7 +22,7 @@ import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecyc import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { IExtensionService, toExtension, ExtensionHostKind, IExtensionHost, webWorkerExtHostConfig, ExtensionRunningLocation, WebWorkerExtHostConfigValue, extensionRunningLocationToString, extensionHostKindToString, LocalProcessRunningLocation, RemoteRunningLocation, LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionService, toExtension, ExtensionHostKind, IExtensionHost, webWorkerExtHostConfig, ExtensionRunningLocation, WebWorkerExtHostConfigValue, extensionHostKindToString, LocalProcessRunningLocation, RemoteRunningLocation, LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; import { IExtensionHostManager } from 'vs/workbench/services/extensions/common/extensionHostManager'; import { ExtensionIdentifier, IExtension, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { ExtensionKind } from 'vs/platform/environment/common/environment'; @@ -160,7 +160,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten if (isInitialStart) { // Here we load even extensions that would be disabled by workspace trust const localExtensions = this._checkEnabledAndProposedAPI(await this._scanAllLocalExtensions(), /* ignore workspace trust */true); - const runningLocation = this._runningLocationClassifier.determineRunningLocation(localExtensions, []); + const runningLocation = this._computeInitialRunningLocation(localExtensions, []); const localProcessExtensions = filterByRunningLocation(localExtensions, runningLocation, desiredRunningLocation); return { autoStart: false, @@ -189,45 +189,45 @@ export class ExtensionService extends AbstractExtensionService implements IExten }; } - protected _pickRunningLocation(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionRunningLocation | null { - const result = ExtensionService.pickRunningLocation(extensionKinds, isInstalledLocally, isInstalledRemotely, preference, Boolean(this._environmentService.remoteAuthority), this._enableLocalWebWorker); - this._logService.trace(`pickRunningLocation for ${extensionId.value}, extension kinds: [${extensionKinds.join(', ')}], isInstalledLocally: ${isInstalledLocally}, isInstalledRemotely: ${isInstalledRemotely}, preference: ${extensionRunningPreferenceToString(preference)} => ${extensionRunningLocationToString(result)}`); + protected _pickExtensionHostKind(extensionId: ExtensionIdentifier, extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference): ExtensionHostKind | null { + const result = ExtensionService.pickExtensionHostKind(extensionKinds, isInstalledLocally, isInstalledRemotely, preference, Boolean(this._environmentService.remoteAuthority), this._enableLocalWebWorker); + this._logService.trace(`pickRunningLocation for ${extensionId.value}, extension kinds: [${extensionKinds.join(', ')}], isInstalledLocally: ${isInstalledLocally}, isInstalledRemotely: ${isInstalledRemotely}, preference: ${extensionRunningPreferenceToString(preference)} => ${extensionHostKindToString(result)}`); return result; } - public static pickRunningLocation(extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference, hasRemoteExtHost: boolean, hasWebWorkerExtHost: boolean): ExtensionRunningLocation | null { - const result: ExtensionRunningLocation[] = []; + public static pickExtensionHostKind(extensionKinds: ExtensionKind[], isInstalledLocally: boolean, isInstalledRemotely: boolean, preference: ExtensionRunningPreference, hasRemoteExtHost: boolean, hasWebWorkerExtHost: boolean): ExtensionHostKind | null { + const result: ExtensionHostKind[] = []; for (const extensionKind of extensionKinds) { if (extensionKind === 'ui' && isInstalledLocally) { // ui extensions run locally if possible if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Local) { - return new LocalProcessRunningLocation(); + return ExtensionHostKind.LocalProcess; } else { - result.push(new LocalProcessRunningLocation()); + result.push(ExtensionHostKind.LocalProcess); } } if (extensionKind === 'workspace' && isInstalledRemotely) { // workspace extensions run remotely if possible if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Remote) { - return new RemoteRunningLocation(); + return ExtensionHostKind.Remote; } else { - result.push(new RemoteRunningLocation()); + result.push(ExtensionHostKind.Remote); } } if (extensionKind === 'workspace' && !hasRemoteExtHost) { // workspace extensions also run locally if there is no remote if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Local) { - return new LocalProcessRunningLocation(); + return ExtensionHostKind.LocalProcess; } else { - result.push(new LocalProcessRunningLocation()); + result.push(ExtensionHostKind.LocalProcess); } } if (extensionKind === 'web' && isInstalledLocally && hasWebWorkerExtHost) { // web worker extensions run in the local web worker if possible if (preference === ExtensionRunningPreference.None || preference === ExtensionRunningPreference.Local) { - return new LocalWebWorkerRunningLocation(); + return ExtensionHostKind.LocalWebWorker; } else { - result.push(new LocalWebWorkerRunningLocation()); + result.push(ExtensionHostKind.LocalWebWorker); } } } @@ -545,7 +545,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten remoteExtensions = this._checkEnabledAndProposedAPI(remoteExtensions, false); const localExtensions = this._checkEnabledAndProposedAPI(await this._scanAllLocalExtensions(), false); - this._runningLocation = this._runningLocationClassifier.determineRunningLocation(localExtensions, remoteExtensions); + this._runningLocation = this._computeInitialRunningLocation(localExtensions, remoteExtensions); // remove non-UI extensions from the local extensions const localProcessExtensions = filterByExtensionHostKind(localExtensions, this._runningLocation, ExtensionHostKind.LocalProcess); diff --git a/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts b/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts index 7eb7f277e77..ecc2877518c 100644 --- a/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts +++ b/src/vs/workbench/services/extensions/test/browser/extensionService.test.ts @@ -16,74 +16,74 @@ suite('BrowserExtensionService', () => { assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation([], true, true, ExtensionRunningPreference.None), null); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'web', 'workspace'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['ui', 'workspace', 'web'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'ui', 'workspace'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['web', 'workspace', 'ui'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'ui', 'web'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, false, ExtensionRunningPreference.None), null); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, false, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.LocalWebWorker); - assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, true, ExtensionRunningPreference.None)!.kind, ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], false, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, false, ExtensionRunningPreference.None), ExtensionHostKind.LocalWebWorker); + assert.deepStrictEqual(BrowserExtensionService.pickRunningLocation(['workspace', 'web', 'ui'], true, true, ExtensionRunningPreference.None), ExtensionHostKind.Remote); }); }); From e03ebfef62b3def503f69a2e0fc76695afcc9b2f Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 11 Mar 2022 15:53:29 +0100 Subject: [PATCH 116/175] Be a better user of deltaDecorations --- .../browser/commentsEditorContribution.ts | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index aadf040bcb4..a5d5d56e14e 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -16,7 +16,7 @@ import { EditorAction, registerEditorAction, registerEditorContribution } from ' import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { IRange, Range } from 'vs/editor/common/core/range'; import { IEditorContribution, IModelChangedEvent } from 'vs/editor/common/editorCommon'; -import { IModelDecorationOptions } from 'vs/editor/common/model'; +import { IModelDecorationOptions, IModelDeltaDecoration } from 'vs/editor/common/model'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import * as languages from 'vs/editor/common/languages'; import { peekViewResultsBackground, peekViewResultsSelectionBackground, peekViewTitleBackground } from 'vs/editor/contrib/peekView/browser/peekView'; @@ -61,25 +61,29 @@ export class ReviewViewZone implements IViewZone { } } -class CommentingRangeDecoration { - private _decorationId: string; +class CommentingRangeDecoration implements IModelDeltaDecoration { + private _decorationId: string | undefined; + private _startLineNumber: number; + private _endLineNumber: number; - public get id(): string { + public get id(): string | undefined { return this._decorationId; } - constructor(private _editor: ICodeEditor, private _ownerId: string, private _extensionId: string | undefined, private _label: string | undefined, private _range: IRange, commentingOptions: ModelDecorationOptions, private commentingRangesInfo: languages.CommentingRanges, public readonly isHover: boolean = false) { - const startLineNumber = _range.startLineNumber; - const endLineNumber = _range.endLineNumber; - let commentingRangeDecorations = [{ - range: { - startLineNumber: startLineNumber, startColumn: 1, - endLineNumber: endLineNumber, endColumn: 1 - }, - options: commentingOptions - }]; + public set id(id: string | undefined) { + this._decorationId = id; + } - this._decorationId = this._editor.deltaDecorations([], commentingRangeDecorations)[0]; + public get range(): IRange { + return { + startLineNumber: this._startLineNumber, startColumn: 1, + endLineNumber: this._endLineNumber, endColumn: 1 + }; + } + + constructor(private _editor: ICodeEditor, private _ownerId: string, private _extensionId: string | undefined, private _label: string | undefined, private _range: IRange, public readonly options: ModelDecorationOptions, private commentingRangesInfo: languages.CommentingRanges, public readonly isHover: boolean = false) { + this._startLineNumber = _range.startLineNumber; + this._endLineNumber = _range.endLineNumber; } public getCommentAction(): { ownerId: string; extensionId: string | undefined; label: string | undefined; commentingRangesInfo: languages.CommentingRanges } { @@ -96,7 +100,7 @@ class CommentingRangeDecoration { } public getActiveRange() { - return this._editor.getModel()!.getDecorationRange(this._decorationId); + return this.id ? this._editor.getModel()!.getDecorationRange(this.id) : undefined; } } class CommentingRangeDecorator { @@ -104,6 +108,7 @@ class CommentingRangeDecorator { private decorationOptions!: ModelDecorationOptions; private hoverDecorationOptions!: ModelDecorationOptions; private commentingRangeDecorations: CommentingRangeDecoration[] = []; + private decorationIds: string[] = []; private _editor: ICodeEditor | undefined; private _infos: ICommentInfo[] | undefined; private _lastHover: number = -1; @@ -163,8 +168,8 @@ class CommentingRangeDecorator { }); } - let oldDecorations = this.commentingRangeDecorations.map(decoration => decoration.id); - editor.deltaDecorations(oldDecorations, []); + this.decorationIds = editor.deltaDecorations(this.decorationIds, commentingRangeDecorations); + commentingRangeDecorations.forEach((decoration, index) => decoration.id = this.decorationIds[index]); const rangesDifference = this.commentingRangeDecorations.length - commentingRangeDecorations.length; this.commentingRangeDecorations = commentingRangeDecorations; From 878ce865f6051431c600d8a4b5f2058aab0fbd1c Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 11 Mar 2022 07:23:27 -0800 Subject: [PATCH 117/175] Run shell integration addon on pty host Part of #142669 --- src/vs/platform/terminal/node/ptyService.ts | 8 ++++++-- .../terminal/browser/xterm/xtermTerminal.ts | 2 +- .../common/capabilities/capabilities.ts | 20 +++++++++++++++---- .../commandDetectionCapability.ts | 4 +++- .../capabilities/cwdDetectionCapability.ts | 4 ++-- .../naiveCwdDetectionCapability.ts | 4 ++-- .../partialCommandDetectionCapability.ts | 10 ++++++---- .../xterm/shellIntegrationAddon.ts | 18 +++++++++-------- .../commandDetectionCapability.test.ts | 2 +- .../partialCommandDetectionCapability.test.ts | 2 +- .../browser/links/terminalLinkOpeners.test.ts | 2 +- .../browser/terminalCommandTracker.test.ts | 2 +- .../browser/xterm/decorationAddon.test.ts | 2 +- .../xterm/shellIntegrationAddon.test.ts | 2 +- 14 files changed, 52 insertions(+), 30 deletions(-) rename src/vs/workbench/contrib/terminal/{browser => common}/capabilities/commandDetectionCapability.ts (98%) rename src/vs/workbench/contrib/terminal/{browser => common}/capabilities/partialCommandDetectionCapability.ts (86%) rename src/vs/workbench/contrib/terminal/{browser => common}/xterm/shellIntegrationAddon.ts (90%) diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 71eb14985eb..73a65305ee1 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -25,6 +25,7 @@ import { localize } from 'vs/nls'; import { ignoreProcessNames } from 'vs/platform/terminal/node/childProcessMonitor'; import { TerminalAutoResponder } from 'vs/platform/terminal/common/terminalAutoResponder'; import { ErrorNoTelemetry } from 'vs/base/common/errors'; +import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon'; type WorkspaceId = string; @@ -500,7 +501,8 @@ export class PersistentTerminalProcess extends Disposable { rows, reconnectConstants.scrollback, unicodeVersion, - reviveBuffer + reviveBuffer, + this._logService ); this._fixedDimensions = fixedDimensions; this._orphanQuestionBarrier = null; @@ -732,7 +734,8 @@ class XtermSerializer implements ITerminalSerializer { rows: number, scrollback: number, unicodeVersion: '6' | '11', - reviveBuffer: string | undefined + reviveBuffer: string | undefined, + logService: ILogService ) { this._xterm = new XtermTerminal({ cols, rows, scrollback }); if (reviveBuffer) { @@ -743,6 +746,7 @@ class XtermSerializer implements ITerminalSerializer { } this._xterm.parser.registerOscHandler(133, (data => this._handleShellIntegration(data))); this.setUnicodeVersion(unicodeVersion); + this._xterm.loadAddon(new ShellIntegrationAddon(logService)); } private _handleShellIntegration(data: string): boolean { diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts index feec88f47ac..cd19013821b 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts @@ -28,7 +28,7 @@ import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { TERMINAL_FOREGROUND_COLOR, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, ansiColorIdentifiers, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { Color } from 'vs/base/common/color'; -import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon'; +import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { DecorationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/decorationAddon'; import { ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.ts b/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.ts index 1f462a9032b..e95ca2b32c0 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.ts @@ -4,8 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { Event } from 'vs/base/common/event'; -import { CwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability'; -import { NaiveCwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability'; /** * Primarily driven by the shell integration feature, a terminal capability is the mechanism for @@ -69,12 +67,20 @@ export interface ITerminalCapabilityStore { * implementations. */ export interface ITerminalCapabilityImplMap { - [TerminalCapability.CwdDetection]: InstanceType; + [TerminalCapability.CwdDetection]: ICwdDetectionCapability; [TerminalCapability.CommandDetection]: ICommandDetectionCapability; - [TerminalCapability.NaiveCwdDetection]: InstanceType; + [TerminalCapability.NaiveCwdDetection]: INaiveCwdDetectionCapability; [TerminalCapability.PartialCommandDetection]: IPartialCommandDetectionCapability; } +export interface ICwdDetectionCapability { + readonly type: TerminalCapability.CwdDetection; + readonly onDidChangeCwd: Event; + readonly cwds: string[]; + getCwd(): string; + updateCwd(cwd: string): void; +} + export interface ICommandDetectionCapability { readonly type: TerminalCapability.CommandDetection; readonly commands: readonly ITerminalCommand[]; @@ -99,6 +105,12 @@ export interface ICommandDetectionCapability { setCommandLine(commandLine: string): void; } +export interface INaiveCwdDetectionCapability { + readonly type: TerminalCapability.NaiveCwdDetection; + readonly onDidChangeCwd: Event; + getCwd(): Promise; +} + export interface IPartialCommandDetectionCapability { readonly type: TerminalCapability.PartialCommandDetection; readonly commands: readonly IXtermMarker[]; diff --git a/src/vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts similarity index 98% rename from src/vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability.ts rename to src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts index ff0d189d347..fa352bd0813 100644 --- a/src/vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts @@ -7,7 +7,9 @@ import { timeout } from 'vs/base/common/async'; import { Emitter } from 'vs/base/common/event'; import { ILogService } from 'vs/platform/log/common/log'; import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; -import { IBuffer, IDisposable, IMarker, Terminal } from 'xterm'; +// Importing types is safe in any layer +// eslint-disable-next-line code-import-patterns +import type { IBuffer, IDisposable, IMarker, Terminal } from 'xterm-headless'; export interface ICurrentPartialCommand { previousCommandMarker?: IMarker; diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts index 4c312135f42..6f2a1456d08 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter } from 'vs/base/common/event'; -import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ICwdDetectionCapability, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; -export class CwdDetectionCapability { +export class CwdDetectionCapability implements ICwdDetectionCapability { readonly type = TerminalCapability.CwdDetection; private _cwd = ''; private _cwds = new Map(); diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts index ca40c5ef2d1..563f181ca29 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts @@ -5,9 +5,9 @@ import { Emitter } from 'vs/base/common/event'; import { ITerminalChildProcess } from 'vs/platform/terminal/common/terminal'; -import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { TerminalCapability, INaiveCwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; -export class NaiveCwdDetectionCapability { +export class NaiveCwdDetectionCapability implements INaiveCwdDetectionCapability { constructor(private readonly _process: ITerminalChildProcess) { } readonly type = TerminalCapability.NaiveCwdDetection; private _cwd = ''; diff --git a/src/vs/workbench/contrib/terminal/browser/capabilities/partialCommandDetectionCapability.ts b/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts similarity index 86% rename from src/vs/workbench/contrib/terminal/browser/capabilities/partialCommandDetectionCapability.ts rename to src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts index e349ac103c5..6eeaae09723 100644 --- a/src/vs/workbench/contrib/terminal/browser/capabilities/partialCommandDetectionCapability.ts +++ b/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts @@ -5,7 +5,9 @@ import { Emitter } from 'vs/base/common/event'; import { IPartialCommandDetectionCapability, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; -import { IMarker, Terminal } from 'xterm'; +// Importing types is safe in any layer +// eslint-disable-next-line code-import-patterns +import { IMarker, Terminal } from 'xterm-headless'; const enum Constants { /** @@ -31,11 +33,11 @@ export class PartialCommandDetectionCapability implements IPartialCommandDetecti constructor( private readonly _terminal: Terminal, ) { - this._terminal.onKey(e => this._onKey(e.key)); + this._terminal.onData(e => this._onData(e)); } - private _onKey(key: string): void { - if (key === '\x0d') { + private _onData(data: string): void { + if (data === '\x0d') { this._onEnter(); } } diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon.ts b/src/vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon.ts similarity index 90% rename from src/vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon.ts rename to src/vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon.ts index bbc240954cd..087920ffa35 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon.ts +++ b/src/vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon.ts @@ -3,15 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITerminalAddon, Terminal } from 'xterm'; import { IShellIntegration } from 'vs/workbench/contrib/terminal/common/terminal'; import { Disposable } from 'vs/base/common/lifecycle'; import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; -import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability'; import { CwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability'; -import { ICommandDetectionCapability, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; -import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/partialCommandDetectionCapability'; +import { ICommandDetectionCapability, ICwdDetectionCapability, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability'; +import { ILogService } from 'vs/platform/log/common/log'; +// Importing types is safe in any layer +// eslint-disable-next-line code-import-patterns +import type { ITerminalAddon, Terminal } from 'xterm'; /** * Shell integration is a feature that enhances the terminal's understanding of what's happening @@ -112,7 +114,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati readonly capabilities = new TerminalCapabilityStore(); constructor( - @IInstantiationService private readonly _instantiationService: IInstantiationService + @ILogService private readonly _logService: ILogService ) { super(); } @@ -188,7 +190,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati return false; } - protected _createOrGetCwdDetection(): CwdDetectionCapability { + protected _createOrGetCwdDetection(): ICwdDetectionCapability { let cwdDetection = this.capabilities.get(TerminalCapability.CwdDetection); if (!cwdDetection) { cwdDetection = new CwdDetectionCapability(); @@ -200,7 +202,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati protected _createOrGetCommandDetection(terminal: Terminal): ICommandDetectionCapability { let commandDetection = this.capabilities.get(TerminalCapability.CommandDetection); if (!commandDetection) { - commandDetection = this._instantiationService.createInstance(CommandDetectionCapability, terminal); + commandDetection = new CommandDetectionCapability(terminal, this._logService); this.capabilities.add(TerminalCapability.CommandDetection, commandDetection); } return commandDetection; diff --git a/src/vs/workbench/contrib/terminal/test/browser/capabilities/commandDetectionCapability.test.ts b/src/vs/workbench/contrib/terminal/test/browser/capabilities/commandDetectionCapability.test.ts index f43dcb9c6f1..5419dbdad17 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/capabilities/commandDetectionCapability.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/capabilities/commandDetectionCapability.test.ts @@ -6,7 +6,7 @@ import { deepStrictEqual, ok } from 'assert'; import { timeout } from 'vs/base/common/async'; import { Terminal } from 'xterm'; -import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability'; +import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability'; import { NullLogService } from 'vs/platform/log/common/log'; import { ITerminalCommand } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts b/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts index 05ae39dd9fe..2e923003ed4 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts @@ -5,7 +5,7 @@ import { deepStrictEqual } from 'assert'; import { timeout } from 'vs/base/common/async'; -import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/partialCommandDetectionCapability'; +import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability'; import { IMarker, Terminal } from 'xterm'; import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkOpeners.test.ts b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkOpeners.test.ts index 7b31b104f2f..7be19f540ba 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkOpeners.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkOpeners.test.ts @@ -14,7 +14,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/ import { ILogService, NullLogService } from 'vs/platform/log/common/log'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability'; +import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability'; import { TerminalBuiltinLinkType } from 'vs/workbench/contrib/terminal/browser/links/links'; import { TerminalLocalFileLinkOpener, TerminalLocalFolderInWorkspaceLinkOpener, TerminalSearchLinkOpener } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkOpeners'; import { TerminalCapability, ITerminalCommand, IXtermMarker } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts index bcf23f57aeb..930241e98bd 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts @@ -10,7 +10,7 @@ import { isWindows } from 'vs/base/common/platform'; import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; import { timeout } from 'vs/base/common/async'; import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; -import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/partialCommandDetectionCapability'; +import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability'; import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; interface TestTerminal extends Terminal { diff --git a/src/vs/workbench/contrib/terminal/test/browser/xterm/decorationAddon.test.ts b/src/vs/workbench/contrib/terminal/test/browser/xterm/decorationAddon.test.ts index f6b8fbc3eb9..be76ac2b67a 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/xterm/decorationAddon.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/xterm/decorationAddon.test.ts @@ -13,7 +13,7 @@ import { ITerminalCommand } from 'vs/workbench/contrib/terminal/common/terminal' import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IDecoration, IDecorationOptions, Terminal } from 'xterm'; import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; -import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/browser/capabilities/commandDetectionCapability'; +import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ContextMenuService } from 'vs/platform/contextview/browser/contextMenuService'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts b/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts index 7aefd01be53..be4cf94552b 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts @@ -7,7 +7,7 @@ import { Terminal } from 'xterm'; import { strictEqual } from 'assert'; import { timeout } from 'vs/base/common/async'; import * as sinon from 'sinon'; -import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/shellIntegrationAddon'; +import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon'; import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ILogService, NullLogService } from 'vs/platform/log/common/log'; From 1a93d4f70ea0e0cd5e821dbcf8b6f20d9a7187e3 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 11 Mar 2022 07:26:05 -0800 Subject: [PATCH 118/175] Move capabilities to platform --- .../terminal/common/capabilities/capabilities.ts | 0 .../common/capabilities/commandDetectionCapability.ts | 2 +- .../common/capabilities/cwdDetectionCapability.ts | 2 +- .../common/capabilities/naiveCwdDetectionCapability.ts | 2 +- .../capabilities/partialCommandDetectionCapability.ts | 2 +- .../common/capabilities/terminalCapabilityStore.ts | 2 +- .../terminal/browser/links/terminalLinkHelpers.ts | 2 +- .../terminal/browser/links/terminalLinkManager.ts | 2 +- .../terminal/browser/links/terminalLinkOpeners.ts | 2 +- .../browser/links/terminalLocalLinkDetector.ts | 2 +- src/vs/workbench/contrib/terminal/browser/terminal.ts | 2 +- .../contrib/terminal/browser/terminalInstance.ts | 2 +- .../contrib/terminal/browser/terminalProcessManager.ts | 2 +- .../contrib/terminal/browser/terminalTooltip.ts | 2 +- .../terminal/browser/xterm/commandTrackerAddon.ts | 2 +- .../contrib/terminal/browser/xterm/decorationAddon.ts | 2 +- .../contrib/terminal/browser/xterm/xtermTerminal.ts | 2 +- src/vs/workbench/contrib/terminal/common/terminal.ts | 2 +- .../terminal/common/xterm/shellIntegrationAddon.ts | 10 +++++----- .../capabilities/commandDetectionCapability.test.ts | 4 ++-- .../partialCommandDetectionCapability.test.ts | 2 +- .../capabilities/terminalCapabilityStore.test.ts | 4 ++-- .../test/browser/links/terminalLinkManager.test.ts | 2 +- .../test/browser/links/terminalLinkOpeners.test.ts | 6 +++--- .../test/browser/terminalCommandTracker.test.ts | 6 +++--- .../terminal/test/browser/terminalInstance.test.ts | 4 ++-- .../test/browser/xterm/decorationAddon.test.ts | 6 +++--- .../test/browser/xterm/shellIntegrationAddon.test.ts | 2 +- 28 files changed, 40 insertions(+), 40 deletions(-) rename src/vs/{workbench/contrib => platform}/terminal/common/capabilities/capabilities.ts (100%) rename src/vs/{workbench/contrib => platform}/terminal/common/capabilities/commandDetectionCapability.ts (99%) rename src/vs/{workbench/contrib => platform}/terminal/common/capabilities/cwdDetectionCapability.ts (95%) rename src/vs/{workbench/contrib => platform}/terminal/common/capabilities/naiveCwdDetectionCapability.ts (94%) rename src/vs/{workbench/contrib => platform}/terminal/common/capabilities/partialCommandDetectionCapability.ts (96%) rename src/vs/{workbench/contrib => platform}/terminal/common/capabilities/terminalCapabilityStore.ts (97%) diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/capabilities.ts b/src/vs/platform/terminal/common/capabilities/capabilities.ts similarity index 100% rename from src/vs/workbench/contrib/terminal/common/capabilities/capabilities.ts rename to src/vs/platform/terminal/common/capabilities/capabilities.ts diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts similarity index 99% rename from src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts rename to src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts index fa352bd0813..822b5354230 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability.ts +++ b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts @@ -6,7 +6,7 @@ import { timeout } from 'vs/base/common/async'; import { Emitter } from 'vs/base/common/event'; import { ILogService } from 'vs/platform/log/common/log'; -import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand } from 'vs/platform/terminal/common/capabilities/capabilities'; // Importing types is safe in any layer // eslint-disable-next-line code-import-patterns import type { IBuffer, IDisposable, IMarker, Terminal } from 'xterm-headless'; diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/cwdDetectionCapability.ts similarity index 95% rename from src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts rename to src/vs/platform/terminal/common/capabilities/cwdDetectionCapability.ts index 6f2a1456d08..7e3fcfa4a5d 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability.ts +++ b/src/vs/platform/terminal/common/capabilities/cwdDetectionCapability.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter } from 'vs/base/common/event'; -import { ICwdDetectionCapability, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ICwdDetectionCapability, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; export class CwdDetectionCapability implements ICwdDetectionCapability { readonly type = TerminalCapability.CwdDetection; diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/naiveCwdDetectionCapability.ts similarity index 94% rename from src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts rename to src/vs/platform/terminal/common/capabilities/naiveCwdDetectionCapability.ts index 563f181ca29..daab3687d42 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability.ts +++ b/src/vs/platform/terminal/common/capabilities/naiveCwdDetectionCapability.ts @@ -5,7 +5,7 @@ import { Emitter } from 'vs/base/common/event'; import { ITerminalChildProcess } from 'vs/platform/terminal/common/terminal'; -import { TerminalCapability, INaiveCwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { TerminalCapability, INaiveCwdDetectionCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; export class NaiveCwdDetectionCapability implements INaiveCwdDetectionCapability { constructor(private readonly _process: ITerminalChildProcess) { } diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/partialCommandDetectionCapability.ts similarity index 96% rename from src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts rename to src/vs/platform/terminal/common/capabilities/partialCommandDetectionCapability.ts index 6eeaae09723..1a722cd14da 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability.ts +++ b/src/vs/platform/terminal/common/capabilities/partialCommandDetectionCapability.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter } from 'vs/base/common/event'; -import { IPartialCommandDetectionCapability, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { IPartialCommandDetectionCapability, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; // Importing types is safe in any layer // eslint-disable-next-line code-import-patterns import { IMarker, Terminal } from 'xterm-headless'; diff --git a/src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts b/src/vs/platform/terminal/common/capabilities/terminalCapabilityStore.ts similarity index 97% rename from src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts rename to src/vs/platform/terminal/common/capabilities/terminalCapabilityStore.ts index 155efd60f9c..69d51539258 100644 --- a/src/vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore.ts +++ b/src/vs/platform/terminal/common/capabilities/terminalCapabilityStore.ts @@ -5,7 +5,7 @@ import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { ITerminalCapabilityImplMap, ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityImplMap, ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; export class TerminalCapabilityStore extends Disposable implements ITerminalCapabilityStore { private _map: Map = new Map(); diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers.ts index 1a8b6eae8b4..202ba173cc0 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers.ts @@ -7,7 +7,7 @@ import type { IViewportRange, IBufferRange, IBufferLine, IBuffer, IBufferCellPos import { IRange } from 'vs/editor/common/core/range'; import { OperatingSystem } from 'vs/base/common/platform'; import { IPath, posix, win32 } from 'vs/base/common/path'; -import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; /** * Converts a possibly wrapped link's range (comprised of string indices) into a buffer range that plays nicely with xterm.js diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts index 3b5c7735895..f25e7d2cb72 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts @@ -29,7 +29,7 @@ import { ITerminalExternalLinkProvider, TerminalLinkQuickPickEvent } from 'vs/wo import { ILinkHoverTargetOptions, TerminalHover } from 'vs/workbench/contrib/terminal/browser/widgets/terminalHoverWidget'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; -import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { ITerminalConfiguration, ITerminalProcessManager, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal'; import { IHoverAction } from 'vs/workbench/services/hover/browser/hover'; import type { ILink, ILinkProvider, IViewportRange, Terminal } from 'xterm'; diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkOpeners.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkOpeners.ts index 2792911d0ef..22598d4aba7 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkOpeners.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkOpeners.ts @@ -17,7 +17,7 @@ import { ITerminalLinkOpener, ITerminalSimpleLink } from 'vs/workbench/contrib/t import { osPathModule, updateLinkWithRelativeCwd } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers'; import { ILineColumnInfo } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager'; import { getLocalLinkRegex, lineAndColumnClause, lineAndColumnClauseGroupCount, unixLineAndColumnMatchIndex, winLineAndColumnMatchIndex } from 'vs/workbench/contrib/terminal/browser/links/terminalLocalLinkDetector'; -import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IHostService } from 'vs/workbench/services/host/browser/host'; diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLocalLinkDetector.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLocalLinkDetector.ts index 7406f47eb55..936af397072 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLocalLinkDetector.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLocalLinkDetector.ts @@ -9,7 +9,7 @@ import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity' import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ITerminalLinkDetector, ITerminalSimpleLink, ResolvedLink, TerminalBuiltinLinkType } from 'vs/workbench/contrib/terminal/browser/links/links'; import { convertLinkRangeToBuffer, getXtermLineContent, osPathModule, updateLinkWithRelativeCwd } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers'; -import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { IBufferLine, Terminal } from 'xterm'; const enum Constants { diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index cfc20e347b5..b5027247bf4 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -15,7 +15,7 @@ import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; import { IEditableData } from 'vs/workbench/common/views'; import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn'; import { IKeyMods } from 'vs/platform/quickinput/common/quickInput'; -import { ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/capabilities'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index c4b868836cb..e04c9ce15f9 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -66,7 +66,7 @@ import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/wid import { LineDataEventAddon } from 'vs/workbench/contrib/terminal/browser/xterm/lineDataEventAddon'; import { NavigationModeAddon } from 'vs/workbench/contrib/terminal/browser/xterm/navigationModeAddon'; import { XtermTerminal } from 'vs/workbench/contrib/terminal/browser/xterm/xtermTerminal'; -import { ITerminalCommand, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { TerminalCapabilityStoreMultiplexer } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { getCommandHistory, getDirectoryHistory } from 'vs/workbench/contrib/terminal/common/history'; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index c6b220c457f..5bb86604934 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -30,7 +30,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; import { NaiveCwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability'; -import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { URI } from 'vs/base/common/uri'; /** The amount of time to consider terminal errors to be related to the launch */ diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTooltip.ts b/src/vs/workbench/contrib/terminal/browser/terminalTooltip.ts index e57c8613a99..ee021996cb1 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTooltip.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTooltip.ts @@ -5,7 +5,7 @@ import { localize } from 'vs/nls'; import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; function getCapabilityName(capability: TerminalCapability): string | undefined { switch (capability) { diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/commandTrackerAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/commandTrackerAddon.ts index f99ade0c8cc..e64b9f82176 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/commandTrackerAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/commandTrackerAddon.ts @@ -6,7 +6,7 @@ import { coalesce } from 'vs/base/common/arrays'; import { Disposable } from 'vs/base/common/lifecycle'; import { ICommandTracker } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { ICommandDetectionCapability, IPartialCommandDetectionCapability, ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ICommandDetectionCapability, IPartialCommandDetectionCapability, ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import type { Terminal, IMarker, ITerminalAddon } from 'xterm'; enum Boundary { diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts index 3687abaf524..a1b54a1272a 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts @@ -8,7 +8,7 @@ import { ITerminalCommand } from 'vs/workbench/contrib/terminal/common/terminal' import { IDecoration, ITerminalAddon, Terminal } from 'xterm'; import * as dom from 'vs/base/browser/dom'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { IColorTheme, ICssStyleCollector, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IHoverService } from 'vs/workbench/services/hover/browser/hover'; diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts index cd19013821b..7d5c24fc5d0 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts @@ -31,7 +31,7 @@ import { Color } from 'vs/base/common/color'; import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { DecorationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/decorationAddon'; -import { ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/capabilities'; import { Emitter } from 'vs/base/common/event'; // How long in milliseconds should an average frame take to render for a notification to appear diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 3178608dd07..3d2be39861c 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -14,7 +14,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' import { URI } from 'vs/base/common/uri'; import { IProcessDetails } from 'vs/platform/terminal/common/terminalProcess'; import { Registry } from 'vs/platform/registry/common/platform'; -import { ITerminalCapabilityStore, IXtermMarker } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityStore, IXtermMarker } from 'vs/platform/terminal/common/capabilities/capabilities'; export const TERMINAL_VIEW_ID = 'terminal'; diff --git a/src/vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon.ts b/src/vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon.ts index 087920ffa35..b3133cb2c08 100644 --- a/src/vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon.ts +++ b/src/vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon.ts @@ -5,11 +5,11 @@ import { IShellIntegration } from 'vs/workbench/contrib/terminal/common/terminal'; import { Disposable } from 'vs/base/common/lifecycle'; -import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; -import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability'; -import { CwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/cwdDetectionCapability'; -import { ICommandDetectionCapability, ICwdDetectionCapability, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; -import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability'; +import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; +import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability'; +import { CwdDetectionCapability } from 'vs/platform/terminal/common/capabilities/cwdDetectionCapability'; +import { ICommandDetectionCapability, ICwdDetectionCapability, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; +import { PartialCommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/partialCommandDetectionCapability'; import { ILogService } from 'vs/platform/log/common/log'; // Importing types is safe in any layer // eslint-disable-next-line code-import-patterns diff --git a/src/vs/workbench/contrib/terminal/test/browser/capabilities/commandDetectionCapability.test.ts b/src/vs/workbench/contrib/terminal/test/browser/capabilities/commandDetectionCapability.test.ts index 5419dbdad17..c2e7d77cfa9 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/capabilities/commandDetectionCapability.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/capabilities/commandDetectionCapability.test.ts @@ -6,9 +6,9 @@ import { deepStrictEqual, ok } from 'assert'; import { timeout } from 'vs/base/common/async'; import { Terminal } from 'xterm'; -import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability'; +import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability'; import { NullLogService } from 'vs/platform/log/common/log'; -import { ITerminalCommand } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCommand } from 'vs/platform/terminal/common/capabilities/capabilities'; async function writeP(terminal: Terminal, data: string): Promise { return new Promise((resolve, reject) => { diff --git a/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts b/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts index 2e923003ed4..f584ffc13da 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts @@ -5,7 +5,7 @@ import { deepStrictEqual } from 'assert'; import { timeout } from 'vs/base/common/async'; -import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability'; +import { PartialCommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/partialCommandDetectionCapability'; import { IMarker, Terminal } from 'xterm'; import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/capabilities/terminalCapabilityStore.test.ts b/src/vs/workbench/contrib/terminal/test/browser/capabilities/terminalCapabilityStore.test.ts index 5c3d859db1d..deb033af52f 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/capabilities/terminalCapabilityStore.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/capabilities/terminalCapabilityStore.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { deepStrictEqual } from 'assert'; -import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; -import { TerminalCapabilityStore, TerminalCapabilityStoreMultiplexer } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; +import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; +import { TerminalCapabilityStore, TerminalCapabilityStoreMultiplexer } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; suite('TerminalCapabilityStore', () => { let store: TerminalCapabilityStore; diff --git a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts index 903d737f2e6..e37c554e6ef 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts @@ -17,7 +17,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IDetectedLinks, TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager'; -import { ITerminalCapabilityImplMap, ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityImplMap, ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { ITerminalConfiguration, ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal'; import { TestViewDescriptorService } from 'vs/workbench/contrib/terminal/test/browser/xterm/xtermTerminal.test'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkOpeners.test.ts b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkOpeners.test.ts index 7be19f540ba..b6efab0951f 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkOpeners.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkOpeners.test.ts @@ -14,11 +14,11 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/ import { ILogService, NullLogService } from 'vs/platform/log/common/log'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability'; +import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability'; import { TerminalBuiltinLinkType } from 'vs/workbench/contrib/terminal/browser/links/links'; import { TerminalLocalFileLinkOpener, TerminalLocalFolderInWorkspaceLinkOpener, TerminalSearchLinkOpener } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkOpeners'; -import { TerminalCapability, ITerminalCommand, IXtermMarker } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; -import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; +import { TerminalCapability, ITerminalCommand, IXtermMarker } from 'vs/platform/terminal/common/capabilities/capabilities'; +import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts index 930241e98bd..ab12adaf02e 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts @@ -9,9 +9,9 @@ import { CommandTrackerAddon } from 'vs/workbench/contrib/terminal/browser/xterm import { isWindows } from 'vs/base/common/platform'; import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; import { timeout } from 'vs/base/common/async'; -import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; -import { PartialCommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/partialCommandDetectionCapability'; -import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; +import { PartialCommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/partialCommandDetectionCapability'; +import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; interface TestTerminal extends Terminal { _core: IXtermCore; diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts index c8b9d09eef0..9d89281d10d 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts @@ -17,8 +17,8 @@ import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/termina import { ProcessState } from 'vs/workbench/contrib/terminal/common/terminal'; import { basename } from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; -import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; -import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; +import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { Schemas } from 'vs/base/common/network'; function createInstance(partial?: Partial): Pick { diff --git a/src/vs/workbench/contrib/terminal/test/browser/xterm/decorationAddon.test.ts b/src/vs/workbench/contrib/terminal/test/browser/xterm/decorationAddon.test.ts index be76ac2b67a..025db75439a 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/xterm/decorationAddon.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/xterm/decorationAddon.test.ts @@ -8,12 +8,12 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ILogService, NullLogService } from 'vs/platform/log/common/log'; import { DecorationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/decorationAddon'; -import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; +import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; import { ITerminalCommand } from 'vs/workbench/contrib/terminal/common/terminal'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IDecoration, IDecorationOptions, Terminal } from 'xterm'; -import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; -import { CommandDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/commandDetectionCapability'; +import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; +import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ContextMenuService } from 'vs/platform/contextview/browser/contextMenuService'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts b/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts index be4cf94552b..6179d768bc3 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts @@ -8,7 +8,7 @@ import { strictEqual } from 'assert'; import { timeout } from 'vs/base/common/async'; import * as sinon from 'sinon'; import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon'; -import { ITerminalCapabilityStore, TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities'; +import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ILogService, NullLogService } from 'vs/platform/log/common/log'; From f98798a40a17ef781a210f3691e791bb359279b2 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 11 Mar 2022 07:27:49 -0800 Subject: [PATCH 119/175] Move shell integration addon to platform --- src/vs/platform/terminal/common/terminal.ts | 5 +++++ .../terminal/common/xterm/shellIntegrationAddon.ts | 4 ++-- src/vs/platform/terminal/node/ptyService.ts | 2 +- src/vs/workbench/contrib/terminal/common/terminal.ts | 4 ---- .../test/browser/xterm/shellIntegrationAddon.test.ts | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) rename src/vs/{workbench/contrib => platform}/terminal/common/xterm/shellIntegrationAddon.ts (98%) diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 3ff4e70ca4c..e8e415726ed 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -7,6 +7,7 @@ import { Event } from 'vs/base/common/event'; import { IProcessEnvironment, OperatingSystem } from 'vs/base/common/platform'; import { URI, UriComponents } from 'vs/base/common/uri'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { ITerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/capabilities'; import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; @@ -768,3 +769,7 @@ export interface IExtensionTerminalProfile extends ITerminalProfileContribution export type ITerminalProfileObject = ITerminalExecutable | ITerminalProfileSource | IExtensionTerminalProfile | null; export type ITerminalProfileType = ITerminalProfile | IExtensionTerminalProfile; + +export interface IShellIntegration { + capabilities: ITerminalCapabilityStore; +} diff --git a/src/vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon.ts b/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts similarity index 98% rename from src/vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon.ts rename to src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts index b3133cb2c08..f7372d44ff5 100644 --- a/src/vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon.ts +++ b/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IShellIntegration } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IShellIntegration } from 'vs/platform/terminal/common/terminal'; import { Disposable } from 'vs/base/common/lifecycle'; import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability'; @@ -13,7 +13,7 @@ import { PartialCommandDetectionCapability } from 'vs/platform/terminal/common/c import { ILogService } from 'vs/platform/log/common/log'; // Importing types is safe in any layer // eslint-disable-next-line code-import-patterns -import type { ITerminalAddon, Terminal } from 'xterm'; +import type { ITerminalAddon, Terminal } from 'xterm-headless'; /** * Shell integration is a feature that enhances the terminal's understanding of what's happening diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 73a65305ee1..d92281146f8 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -25,7 +25,7 @@ import { localize } from 'vs/nls'; import { ignoreProcessNames } from 'vs/platform/terminal/node/childProcessMonitor'; import { TerminalAutoResponder } from 'vs/platform/terminal/common/terminalAutoResponder'; import { ErrorNoTelemetry } from 'vs/base/common/errors'; -import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon'; +import { ShellIntegrationAddon } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon'; type WorkspaceId = string; diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 3d2be39861c..fc8caf18454 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -328,10 +328,6 @@ export interface IRemoteTerminalAttachTarget { fixedDimensions: IFixedTerminalDimensions | undefined; } -export interface IShellIntegration { - capabilities: ITerminalCapabilityStore; -} - export interface ITerminalCommand { command: string; timestamp: number; diff --git a/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts b/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts index 6179d768bc3..8e8740ea388 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.test.ts @@ -7,7 +7,7 @@ import { Terminal } from 'xterm'; import { strictEqual } from 'assert'; import { timeout } from 'vs/base/common/async'; import * as sinon from 'sinon'; -import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon'; +import { ShellIntegrationAddon } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon'; import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ILogService, NullLogService } from 'vs/platform/log/common/log'; From ae839f6cd7c3334b143db6b43143ee923f3ad7aa Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 11 Mar 2022 07:30:57 -0800 Subject: [PATCH 120/175] Correct imports --- src/vs/workbench/contrib/terminal/browser/terminal.ts | 4 ++-- .../workbench/contrib/terminal/browser/terminalInstance.ts | 2 +- .../contrib/terminal/browser/terminalProcessManager.ts | 4 ++-- .../contrib/terminal/browser/xterm/xtermTerminal.ts | 6 +++--- .../test/browser/links/terminalLocalLinkDetector.test.ts | 2 +- .../terminal/test/browser/xterm/xtermTerminal.test.ts | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index b5027247bf4..3d8f09616e0 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -8,8 +8,8 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { FindReplaceState } from 'vs/editor/contrib/find/browser/findState'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IShellLaunchConfig, ITerminalDimensions, ITerminalLaunchError, ITerminalProfile, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource, TerminalShellType, IExtensionTerminalProfile, TerminalLocation, ProcessPropertyType, IProcessPropertyMap } from 'vs/platform/terminal/common/terminal'; -import { INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalFont, ITerminalBackend, ITerminalProcessExtHostProxy, IRegisterContributedProfileArgs, IShellIntegration } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IShellLaunchConfig, ITerminalDimensions, ITerminalLaunchError, ITerminalProfile, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource, TerminalShellType, IExtensionTerminalProfile, TerminalLocation, ProcessPropertyType, IProcessPropertyMap, IShellIntegration } from 'vs/platform/terminal/common/terminal'; +import { INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalFont, ITerminalBackend, ITerminalProcessExtHostProxy, IRegisterContributedProfileArgs } from 'vs/workbench/contrib/terminal/common/terminal'; import { ITerminalStatusList } from 'vs/workbench/contrib/terminal/browser/terminalStatusList'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; import { IEditableData } from 'vs/workbench/common/views'; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index e04c9ce15f9..2299f73799c 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -67,7 +67,7 @@ import { LineDataEventAddon } from 'vs/workbench/contrib/terminal/browser/xterm/ import { NavigationModeAddon } from 'vs/workbench/contrib/terminal/browser/xterm/navigationModeAddon'; import { XtermTerminal } from 'vs/workbench/contrib/terminal/browser/xterm/xtermTerminal'; import { ITerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; -import { TerminalCapabilityStoreMultiplexer } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; +import { TerminalCapabilityStoreMultiplexer } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { getCommandHistory, getDirectoryHistory } from 'vs/workbench/contrib/terminal/common/history'; import { DEFAULT_COMMANDS_TO_SKIP_SHELL, INavigationMode, ITerminalBackend, ITerminalProcessManager, ITerminalProfileResolverService, ProcessState, ShellIntegrationExitCode, TerminalCommandId, TERMINAL_CREATION_COMMANDS, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 5bb86604934..3df2ed9b85c 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -28,8 +28,8 @@ import { formatMessageForTerminal } from 'vs/workbench/contrib/terminal/common/t import { IProcessEnvironment, isMacintosh, isWindows, OperatingSystem, OS } from 'vs/base/common/platform'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; -import { NaiveCwdDetectionCapability } from 'vs/workbench/contrib/terminal/common/capabilities/naiveCwdDetectionCapability'; +import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; +import { NaiveCwdDetectionCapability } from 'vs/platform/terminal/common/capabilities/naiveCwdDetectionCapability'; import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { URI } from 'vs/base/common/uri'; diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts index 7d5c24fc5d0..c6021d71407 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts @@ -12,8 +12,8 @@ import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configur import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; -import { TerminalLocation, TerminalSettingId } from 'vs/platform/terminal/common/terminal'; -import { IShellIntegration, ITerminalFont, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IShellIntegration, TerminalLocation, TerminalSettingId } from 'vs/platform/terminal/common/terminal'; +import { ITerminalFont, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { isSafari } from 'vs/base/browser/browser'; import { ICommandTracker, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import { ILogService } from 'vs/platform/log/common/log'; @@ -28,7 +28,7 @@ import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { TERMINAL_FOREGROUND_COLOR, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, ansiColorIdentifiers, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { Color } from 'vs/base/common/color'; -import { ShellIntegrationAddon } from 'vs/workbench/contrib/terminal/common/xterm/shellIntegrationAddon'; +import { ShellIntegrationAddon } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { DecorationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/decorationAddon'; import { ITerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/capabilities'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLocalLinkDetector.test.ts b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLocalLinkDetector.test.ts index a39e7867016..8ac3607d6e8 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLocalLinkDetector.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLocalLinkDetector.test.ts @@ -10,7 +10,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { ITerminalSimpleLink, TerminalBuiltinLinkType } from 'vs/workbench/contrib/terminal/browser/links/links'; import { TerminalLocalLinkDetector } from 'vs/workbench/contrib/terminal/browser/links/terminalLocalLinkDetector'; -import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; +import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; import { assertLinkHelper, resolveLinkForTest } from 'vs/workbench/contrib/terminal/test/browser/links/linkTestUtils'; import { Terminal } from 'xterm'; diff --git a/src/vs/workbench/contrib/terminal/test/browser/xterm/xtermTerminal.test.ts b/src/vs/workbench/contrib/terminal/test/browser/xterm/xtermTerminal.test.ts index 1313c2cccf0..c9bbe8dedaf 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/xterm/xtermTerminal.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/xterm/xtermTerminal.test.ts @@ -24,7 +24,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; import { isSafari } from 'vs/base/browser/browser'; import { TerminalLocation } from 'vs/platform/terminal/common/terminal'; -import { TerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore'; +import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ContextMenuService } from 'vs/platform/contextview/browser/contextMenuService'; From 0e95041cc560a5522a0cd7f73ec27822cc3c17ac Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Fri, 11 Mar 2022 07:46:16 -0800 Subject: [PATCH 121/175] Add workspace trust to the web (disabled by default) and server distro (enabled by default) (#144852) * server trust * change to opt in model for trust in embedder api * add fallback host label --- src/vs/server/node/serverEnvironmentService.ts | 3 +++ src/vs/server/node/webClientServer.ts | 1 + src/vs/workbench/browser/web.api.ts | 5 +++++ .../workspace/browser/workspace.contribution.ts | 13 +++---------- .../workspace/browser/workspaceTrustEditor.ts | 7 ++++++- .../environment/browser/environmentService.ts | 2 +- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/vs/server/node/serverEnvironmentService.ts b/src/vs/server/node/serverEnvironmentService.ts index efcec94e030..e003143e7aa 100644 --- a/src/vs/server/node/serverEnvironmentService.ts +++ b/src/vs/server/node/serverEnvironmentService.ts @@ -33,6 +33,7 @@ export const serverOptions: OptionDescriptions = { 'user-data-dir': OPTIONS['user-data-dir'], 'driver': OPTIONS['driver'], 'disable-telemetry': OPTIONS['disable-telemetry'], + 'disable-workspace-trust': OPTIONS['disable-workspace-trust'], 'file-watcher-polling': { type: 'string', deprecates: ['fileWatcherPolling'] }, 'log': OPTIONS['log'], 'logsPath': OPTIONS['logsPath'], @@ -130,6 +131,8 @@ export interface ServerParsedArgs { 'telemetry-level'?: string; + 'disable-workspace-trust'?: boolean; + /* ----- vs code options ----- */ 'user-data-dir'?: string; diff --git a/src/vs/server/node/webClientServer.ts b/src/vs/server/node/webClientServer.ts index 7ccdc3da56d..b8f7da16eea 100644 --- a/src/vs/server/node/webClientServer.ts +++ b/src/vs/server/node/webClientServer.ts @@ -278,6 +278,7 @@ export class WebClientServer { _wrapWebWorkerExtHostInIframe, developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined }, settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined, + enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'], productConfiguration: >{ embedderIdentifier: 'server-distro', extensionsGallery: this._webExtensionResourceUrlTemplate ? { diff --git a/src/vs/workbench/browser/web.api.ts b/src/vs/workbench/browser/web.api.ts index 44593e92807..0dab22ecd12 100644 --- a/src/vs/workbench/browser/web.api.ts +++ b/src/vs/workbench/browser/web.api.ts @@ -170,6 +170,11 @@ export interface IWorkbenchConstructionOptions { */ readonly additionalTrustedDomains?: string[]; + /** + * Enable workspace trust feature for the current window + */ + readonly enableWorkspaceTrust?: boolean; + /** * Urls that will be opened externally that are allowed access * to the opener window. This is primarily used to allow diff --git a/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts b/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts index 7aca0b78959..714d83dc166 100644 --- a/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts +++ b/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts @@ -29,8 +29,6 @@ import { IEditorSerializer, IEditorFactoryRegistry, EditorExtensions } from 'vs/ import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceContextService, IWorkspaceFoldersWillChangeEvent, toWorkspaceIdentifier, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { isWeb } from 'vs/base/common/platform'; -import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; import { dirname, resolve } from 'vs/base/common/path'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent'; @@ -630,7 +628,7 @@ registerAction2(class extends Action2 { super({ id: CONFIGURE_TRUST_COMMAND_ID, title: { original: 'Configure Workspace Trust', value: localize('configureWorkspaceTrust', "Configure Workspace Trust") }, - precondition: ContextKeyExpr.and(WorkspaceTrustContext.IsEnabled, IsWebContext.negate(), ContextKeyExpr.equals(`config.${WORKSPACE_TRUST_ENABLED}`, true)), + precondition: ContextKeyExpr.and(WorkspaceTrustContext.IsEnabled, ContextKeyExpr.equals(`config.${WORKSPACE_TRUST_ENABLED}`, true)), category: localize('workspacesCategory', "Workspaces"), f1: true }); @@ -648,14 +646,14 @@ registerAction2(class extends Action2 { super({ id: MANAGE_TRUST_COMMAND_ID, title: { original: 'Manage Workspace Trust', value: localize('manageWorkspaceTrust', "Manage Workspace Trust") }, - precondition: ContextKeyExpr.and(WorkspaceTrustContext.IsEnabled, IsWebContext.negate(), ContextKeyExpr.equals(`config.${WORKSPACE_TRUST_ENABLED}`, true)), + precondition: ContextKeyExpr.and(WorkspaceTrustContext.IsEnabled, ContextKeyExpr.equals(`config.${WORKSPACE_TRUST_ENABLED}`, true)), category: localize('workspacesCategory', "Workspaces"), f1: true, menu: { id: MenuId.GlobalActivity, group: '6_workspace_trust', order: 40, - when: ContextKeyExpr.and(WorkspaceTrustContext.IsEnabled, IsWebContext.negate(), ContextKeyExpr.equals(`config.${WORKSPACE_TRUST_ENABLED}`, true)) + when: ContextKeyExpr.and(WorkspaceTrustContext.IsEnabled, ContextKeyExpr.equals(`config.${WORKSPACE_TRUST_ENABLED}`, true)) }, }); } @@ -686,7 +684,6 @@ Registry.as(ConfigurationExtensions.Configuration) [WORKSPACE_TRUST_ENABLED]: { type: 'boolean', default: true, - included: !isWeb, description: localize('workspace.trust.description', "Controls whether or not workspace trust is enabled within VS Code."), tags: [WORKSPACE_TRUST_SETTING_TAG], scope: ConfigurationScope.APPLICATION, @@ -694,7 +691,6 @@ Registry.as(ConfigurationExtensions.Configuration) [WORKSPACE_TRUST_STARTUP_PROMPT]: { type: 'string', default: 'once', - included: !isWeb, description: localize('workspace.trust.startupPrompt.description', "Controls when the startup prompt to trust a workspace is shown."), tags: [WORKSPACE_TRUST_SETTING_TAG], scope: ConfigurationScope.APPLICATION, @@ -708,7 +704,6 @@ Registry.as(ConfigurationExtensions.Configuration) [WORKSPACE_TRUST_BANNER]: { type: 'string', default: 'untilDismissed', - included: !isWeb, description: localize('workspace.trust.banner.description', "Controls when the restricted mode banner is shown."), tags: [WORKSPACE_TRUST_SETTING_TAG], scope: ConfigurationScope.APPLICATION, @@ -722,7 +717,6 @@ Registry.as(ConfigurationExtensions.Configuration) [WORKSPACE_TRUST_UNTRUSTED_FILES]: { type: 'string', default: 'prompt', - included: !isWeb, markdownDescription: localize('workspace.trust.untrustedFiles.description', "Controls how to handle opening untrusted files in a trusted workspace. This setting also applies to opening files in an empty window which is trusted via `#{0}#`.", WORKSPACE_TRUST_EMPTY_WINDOW), tags: [WORKSPACE_TRUST_SETTING_TAG], scope: ConfigurationScope.APPLICATION, @@ -736,7 +730,6 @@ Registry.as(ConfigurationExtensions.Configuration) [WORKSPACE_TRUST_EMPTY_WINDOW]: { type: 'boolean', default: true, - included: !isWeb, markdownDescription: localize('workspace.trust.emptyWindow.description', "Controls whether or not the empty window is trusted by default within VS Code. When used with `#{0}#`, you can enable the full functionality of VS Code without prompting in an empty window.", WORKSPACE_TRUST_UNTRUSTED_FILES), tags: [WORKSPACE_TRUST_SETTING_TAG], scope: ConfigurationScope.APPLICATION diff --git a/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts b/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts index 5aae1567d83..b5e76bd06f4 100644 --- a/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts +++ b/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts @@ -588,7 +588,12 @@ interface ITrustedUriHostColumnTemplateData { } function getHostLabel(labelService: ILabelService, item: ITrustedUriItem): string { - return item.uri.authority ? labelService.getHostLabel(item.uri.scheme, item.uri.authority) : localize('localAuthority', "Local"); + const hostLabel = item.uri.authority ? labelService.getHostLabel(item.uri.scheme, item.uri.authority) : localize('localAuthority', "Local"); + if (hostLabel === undefined || hostLabel.length === 0) { + return item.uri.authority; + } + + return hostLabel; } class TrustedUriHostColumnRenderer implements ITableRenderer { diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 838100ee020..8a74415c8a8 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -205,7 +205,7 @@ export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvi get skipWelcome(): boolean { return this.payload?.get('skipWelcome') === 'true'; } @memoize - get disableWorkspaceTrust(): boolean { return true; } + get disableWorkspaceTrust(): boolean { return !this.options.enableWorkspaceTrust; } private payload: Map | undefined; From 24d49c0f84ddc588da63d82ec4bad9e0c34d73c7 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Fri, 11 Mar 2022 08:52:55 -0800 Subject: [PATCH 122/175] disable workspace trust in web integration tests --- test/integration/browser/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/browser/src/index.ts b/test/integration/browser/src/index.ts index ab92cbb28c4..0510fc4f54d 100644 --- a/test/integration/browser/src/index.ts +++ b/test/integration/browser/src/index.ts @@ -125,7 +125,7 @@ async function launchServer(browserType: BrowserType): Promise<{ endpoint: url.U const root = path.join(__dirname, '..', '..', '..', '..'); const logsPath = path.join(root, '.build', 'logs', 'integration-tests-browser'); - const serverArgs = ['--driver', 'web', '--enable-proposed-api', '--disable-telemetry', '--server-data-dir', userDataDir, '--accept-server-license-terms']; + const serverArgs = ['--driver', 'web', '--enable-proposed-api', '--disable-telemetry', '--server-data-dir', userDataDir, '--accept-server-license-terms', '--disable-workspace-trust']; let serverLocation: string; if (process.env.VSCODE_REMOTE_SERVER_PATH) { From 07793ae9c49b6e17550d40921c159637c5407e82 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Fri, 11 Mar 2022 09:01:02 -0800 Subject: [PATCH 123/175] move secondary next to primary --- src/vs/workbench/browser/actions/layoutActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 780d43b23b0..16793767636 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -1134,8 +1134,8 @@ if (!isMacintosh || !isNative) { ToggleVisibilityActions.push(...[ CreateToggleLayoutItem(ToggleActivityBarVisibilityAction.ID, ContextKeyExpr.equals('config.workbench.activityBar.visible', true), localize('activityBar', "Activity Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: activityBarLeftIcon, iconB: activityBarRightIcon }), CreateToggleLayoutItem(ToggleSidebarVisibilityAction.ID, SideBarVisibleContext, localize('sideBar', "Primary Side Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: panelLeftIcon, iconB: panelRightIcon }), - CreateToggleLayoutItem(TogglePanelAction.ID, PanelVisibleContext, localize('panel', "Panel"), panelIcon), CreateToggleLayoutItem(ToggleAuxiliaryBarAction.ID, AuxiliaryBarVisibleContext, localize('secondarySideBar', "Secondary Side Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: panelRightIcon, iconB: panelLeftIcon }), + CreateToggleLayoutItem(TogglePanelAction.ID, PanelVisibleContext, localize('panel', "Panel"), panelIcon), CreateToggleLayoutItem(ToggleStatusbarVisibilityAction.ID, ContextKeyExpr.equals('config.workbench.statusBar.visible', true), localize('statusBar', "Status Bar"), statusBarIcon), ]); From 9addadc0b0fb6764d3666be80c141d67ae65d0d2 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 11 Mar 2022 09:22:10 -0800 Subject: [PATCH 124/175] Serialize commands and send them over during replay Fixes #142669 --- .../common/capabilities/capabilities.ts | 2 + .../commandDetectionCapability.ts | 28 +++++++++++++ src/vs/platform/terminal/common/terminal.ts | 3 +- .../terminal/common/terminalProcess.ts | 14 ++++++- .../terminal/common/terminalRecorder.ts | 4 +- .../common/xterm/shellIntegrationAddon.ts | 8 ++++ src/vs/platform/terminal/node/ptyService.ts | 42 +++++++++++-------- .../terminal/browser/remoteTerminalBackend.ts | 11 ++++- .../terminal/browser/terminalService.ts | 3 ++ .../terminal/browser/xterm/decorationAddon.ts | 9 ++++ .../contrib/terminal/common/terminal.ts | 3 +- .../terminal/electron-sandbox/localPty.ts | 4 +- .../electron-sandbox/localTerminalBackend.ts | 11 ++++- 13 files changed, 115 insertions(+), 27 deletions(-) diff --git a/src/vs/platform/terminal/common/capabilities/capabilities.ts b/src/vs/platform/terminal/common/capabilities/capabilities.ts index e95ca2b32c0..a73003dd535 100644 --- a/src/vs/platform/terminal/common/capabilities/capabilities.ts +++ b/src/vs/platform/terminal/common/capabilities/capabilities.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Event } from 'vs/base/common/event'; +import { ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess'; /** * Primarily driven by the shell integration feature, a terminal capability is the mechanism for @@ -103,6 +104,7 @@ export interface ICommandDetectionCapability { * Set the command line explicitly. */ setCommandLine(commandLine: string): void; + restoreCommands(serialized: ISerializedCommand[]): void; } export interface INaiveCwdDetectionCapability { diff --git a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts index 822b5354230..ee3ae071162 100644 --- a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts +++ b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts @@ -7,6 +7,7 @@ import { timeout } from 'vs/base/common/async'; import { Emitter } from 'vs/base/common/event'; import { ILogService } from 'vs/platform/log/common/log'; import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand } from 'vs/platform/terminal/common/capabilities/capabilities'; +import { ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess'; // Importing types is safe in any layer // eslint-disable-next-line code-import-patterns import type { IBuffer, IDisposable, IMarker, Terminal } from 'xterm-headless'; @@ -223,6 +224,33 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { this._logService.debug('CommandDetectionCapability#setCommandLine', commandLine); this._currentCommand.command = commandLine; } + + restoreCommands(serialized: ISerializedCommand[]): void { + console.log('restoreCommands', serialized); + const buffer = this._terminal.buffer.normal; + for (const e of serialized) { + const marker = e.startLine !== undefined ? this._terminal.registerMarker(e.startLine - (buffer.baseY + buffer.cursorY)) : undefined; + if (!marker) { + continue; + } + this._onCommandStarted.fire({ marker } as ITerminalCommand); + const newCommand = { + command: '', + marker, + endMarker: e.endLine !== undefined ? this._terminal.registerMarker(e.endLine - (buffer.baseY + buffer.cursorY)) : undefined, + timestamp: e.timestamp, + cwd: e.cwd, + exitCode: e.exitCode, + hasOutput: false, + getOutput: () => '' + // hasOutput: !!(this._currentCommand.commandExecutedMarker && this._currentCommand.commandFinishedMarker && this._currentCommand.commandExecutedMarker?.line < this._currentCommand.commandFinishedMarker!.line), + // getOutput: () => getOutputForCommand(clonedPartialCommand, buffer) + }; + this._commands.push(newCommand); + this._logService.debug('CommandDetectionCapability#onCommandFinished', newCommand); + this._onCommandFinished.fire(newCommand); + } + } } function getOutputForCommand(command: ICurrentPartialCommand, buffer: IBuffer): string | undefined { diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index e8e415726ed..90f2479bc2a 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -8,7 +8,7 @@ import { IProcessEnvironment, OperatingSystem } from 'vs/base/common/platform'; import { URI, UriComponents } from 'vs/base/common/uri'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ITerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/capabilities'; -import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess'; +import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISerializedCommand, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; export const enum TerminalSettingPrefix { @@ -772,4 +772,5 @@ export type ITerminalProfileType = ITerminalProfile | IExtensionTerminalProfile; export interface IShellIntegration { capabilities: ITerminalCapabilityStore; + restoreCommands(serialized: ISerializedCommand[]): void; } diff --git a/src/vs/platform/terminal/common/terminalProcess.ts b/src/vs/platform/terminal/common/terminalProcess.ts index d32d309235b..0bff257fd7a 100644 --- a/src/vs/platform/terminal/common/terminalProcess.ts +++ b/src/vs/platform/terminal/common/terminalProcess.ts @@ -63,7 +63,19 @@ export interface IProcessDetails { export type ITerminalTabLayoutInfoDto = IRawTerminalTabLayoutInfo; -export interface ReplayEntry { cols: number; rows: number; data: string } +export interface ReplayEntry { + cols: number; + rows: number; + data: string; +} +export interface ISerializedCommand { + cwd: string | undefined; + startLine: number | undefined; + endLine: number | undefined; + exitCode: number | undefined; + timestamp: number; +} export interface IPtyHostProcessReplayEvent { events: ReplayEntry[]; + commands: ISerializedCommand[]; } diff --git a/src/vs/platform/terminal/common/terminalRecorder.ts b/src/vs/platform/terminal/common/terminalRecorder.ts index b0fb739f9e5..d68cc59bc26 100644 --- a/src/vs/platform/terminal/common/terminalRecorder.ts +++ b/src/vs/platform/terminal/common/terminalRecorder.ts @@ -84,7 +84,9 @@ export class TerminalRecorder { } }); return { - events: this._entries.map(entry => ({ cols: entry.cols, rows: entry.rows, data: entry.data[0] ?? '' })) + events: this._entries.map(entry => ({ cols: entry.cols, rows: entry.rows, data: entry.data[0] ?? '' })), + // No command restoration is needed when relaunching terminals + commands: [] }; } diff --git a/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts b/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts index f7372d44ff5..07e0affd6ac 100644 --- a/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts +++ b/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts @@ -14,6 +14,7 @@ import { ILogService } from 'vs/platform/log/common/log'; // Importing types is safe in any layer // eslint-disable-next-line code-import-patterns import type { ITerminalAddon, Terminal } from 'xterm-headless'; +import { ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess'; /** * Shell integration is a feature that enhances the terminal's understanding of what's happening @@ -190,6 +191,13 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati return false; } + restoreCommands(serialized: ISerializedCommand[]): void { + if (!this._terminal) { + throw new Error('Cannot restore commands before addon is activated'); + } + this._createOrGetCommandDetection(this._terminal).restoreCommands(serialized); + } + protected _createOrGetCwdDetection(): ICwdDetectionCapability { let cwdDetection = this.capabilities.get(TerminalCapability.CwdDetection); if (!cwdDetection) { diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index d92281146f8..4e441704437 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -18,7 +18,7 @@ import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnviro import { Terminal as XtermTerminal } from 'xterm-headless'; import type { ISerializeOptions, SerializeAddon as XtermSerializeAddon } from 'xterm-addon-serialize'; import type { Unicode11Addon as XtermUnicode11Addon } from 'xterm-addon-unicode11'; -import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs, ITerminalTabLayoutInfoDto } from 'vs/platform/terminal/common/terminalProcess'; +import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISerializedCommand, ISetTerminalLayoutInfoArgs, ITerminalTabLayoutInfoDto } from 'vs/platform/terminal/common/terminalProcess'; import { getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment'; import { TerminalProcess } from 'vs/platform/terminal/node/terminalProcess'; import { localize } from 'vs/nls'; @@ -26,6 +26,7 @@ import { ignoreProcessNames } from 'vs/platform/terminal/node/childProcessMonito import { TerminalAutoResponder } from 'vs/platform/terminal/common/terminalAutoResponder'; import { ErrorNoTelemetry } from 'vs/base/common/errors'; import { ShellIntegrationAddon } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon'; +import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; type WorkspaceId = string; @@ -725,9 +726,9 @@ export class PersistentTerminalProcess extends Disposable { } class XtermSerializer implements ITerminalSerializer { - private _xterm: XtermTerminal; + private readonly _xterm: XtermTerminal; + private readonly _shellIntegrationAddon: ShellIntegrationAddon; private _unicodeAddon?: XtermUnicode11Addon; - private _shellIntegrationEnabled: boolean = false; constructor( cols: number, @@ -740,22 +741,10 @@ class XtermSerializer implements ITerminalSerializer { this._xterm = new XtermTerminal({ cols, rows, scrollback }); if (reviveBuffer) { this._xterm.writeln(reviveBuffer); - if (this._shellIntegrationEnabled) { - this._xterm.write('\x1b033]133;E\x1b007'); - } } - this._xterm.parser.registerOscHandler(133, (data => this._handleShellIntegration(data))); this.setUnicodeVersion(unicodeVersion); - this._xterm.loadAddon(new ShellIntegrationAddon(logService)); - } - - private _handleShellIntegration(data: string): boolean { - const [command,] = data.split(';'); - if (command === 'E') { - this._shellIntegrationEnabled = true; - return true; - } - return false; + this._shellIntegrationAddon = new ShellIntegrationAddon(logService); + this._xterm.loadAddon(this._shellIntegrationAddon); } handleData(data: string): void { @@ -782,7 +771,8 @@ class XtermSerializer implements ITerminalSerializer { rows: this._xterm.getOption('rows'), data: serialized } - ] + ], + commands: this._getSerializedCommands() }; } @@ -813,6 +803,22 @@ class XtermSerializer implements ITerminalSerializer { } return SerializeAddon; } + + private _getSerializedCommands(): ISerializedCommand[] { + const commandDetection = this._shellIntegrationAddon.capabilities.get(TerminalCapability.CommandDetection); + if (!commandDetection) { + return []; + } + return commandDetection.commands.map(e => { + return { + cwd: e.cwd, + startLine: e.marker?.line, + endLine: e.endMarker?.line, + exitCode: e.exitCode, + timestamp: e.timestamp + }; + }); + } } function printTime(ms: number): string { diff --git a/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts b/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts index 20f572c7a34..96d93de365d 100644 --- a/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts @@ -15,7 +15,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IShellLaunchConfig, IShellLaunchConfigDto, ITerminalChildProcess, ITerminalEnvironment, ITerminalProcessOptions, ITerminalProfile, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, ProcessPropertyType, TerminalIcon, TerminalSettingId, TitleEventSource } from 'vs/platform/terminal/common/terminal'; -import { IProcessDetails } from 'vs/platform/terminal/common/terminalProcess'; +import { IProcessDetails, ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { BaseTerminalBackend } from 'vs/workbench/contrib/terminal/browser/baseTerminalBackend'; @@ -52,6 +52,8 @@ class RemoteTerminalBackend extends BaseTerminalBackend implements ITerminalBack private readonly _onDidRequestDetach = this._register(new Emitter<{ requestId: number; workspaceId: string; instanceId: number }>()); readonly onDidRequestDetach = this._onDidRequestDetach.event; + private readonly _onRestoreCommands = this._register(new Emitter<{ id: number; commands: ISerializedCommand[] }>()); + readonly onRestoreCommands = this._onRestoreCommands.event; constructor( readonly remoteAuthority: string | undefined, @@ -70,7 +72,12 @@ class RemoteTerminalBackend extends BaseTerminalBackend implements ITerminalBack super(_remoteTerminalChannel, logService, notificationService, _historyService, configurationResolverService, workspaceContextService); this._remoteTerminalChannel.onProcessData(e => this._ptys.get(e.id)?.handleData(e.event)); - this._remoteTerminalChannel.onProcessReplay(e => this._ptys.get(e.id)?.handleReplay(e.event)); + this._remoteTerminalChannel.onProcessReplay(e => { + this._ptys.get(e.id)?.handleReplay(e.event); + if (e.event.commands.length > 0) { + this._onRestoreCommands.fire({ id: e.id, commands: e.event.commands }); + } + }); this._remoteTerminalChannel.onProcessOrphanQuestion(e => this._ptys.get(e.id)?.handleOrphanQuestion()); this._remoteTerminalChannel.onDidRequestDetach(e => this._onDidRequestDetach.fire(e)); this._remoteTerminalChannel.onProcessReady(e => this._ptys.get(e.id)?.handleReady(e.event)); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 31995a09e77..5eb4f42ad41 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -281,6 +281,9 @@ export class TerminalService implements ITerminalService { } } }); + backend.onRestoreCommands(e => { + this.getInstanceFromId(e.id)?.xterm?.shellIntegration?.restoreCommands(e.commands); + }); } } diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts index a1b54a1272a..e2caecd6fcf 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts @@ -131,6 +131,12 @@ export class DecorationAddon extends Disposable implements ITerminalAddon { if (!capability) { return; } + if (capability.commands.length > 0) { + const lastCommand = capability.commands[capability.commands.length - 1]; + if (lastCommand.marker && !lastCommand.endMarker) { + this.registerCommandDecoration(lastCommand, true); + } + } this._commandStartedListener = capability.onCommandStarted(command => this.registerCommandDecoration(command, true)); } @@ -143,6 +149,9 @@ export class DecorationAddon extends Disposable implements ITerminalAddon { if (!capability) { return; } + for (const command of capability.commands) { + this.registerCommandDecoration(command); + } this._commandFinishedListener = capability.onCommandFinished(command => { if (command.command.trim().toLowerCase() === 'clear' || command.command.trim().toLowerCase() === 'cls') { this.clearDecorations(); diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index fc8caf18454..65a9db55745 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -12,7 +12,7 @@ import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChi import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; -import { IProcessDetails } from 'vs/platform/terminal/common/terminalProcess'; +import { IProcessDetails, ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess'; import { Registry } from 'vs/platform/registry/common/platform'; import { ITerminalCapabilityStore, IXtermMarker } from 'vs/platform/terminal/common/capabilities/capabilities'; @@ -114,6 +114,7 @@ export interface ITerminalBackend { onPtyHostRestart: Event; onDidRequestDetach: Event<{ requestId: number; workspaceId: string; instanceId: number }>; + onRestoreCommands: Event<{ id: number; commands: ISerializedCommand[] }>; attachToProcess(id: number): Promise; listProcesses(): Promise; diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts index 689d383539d..20fcdd0371c 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts @@ -7,7 +7,7 @@ import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal'; import { IProcessDataEvent, ITerminalChildProcess, ITerminalLaunchError, IProcessProperty, IProcessPropertyMap, ProcessPropertyType, IProcessReadyEvent } from 'vs/platform/terminal/common/terminal'; -import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminalProcess'; +import { IPtyHostProcessReplayEvent, ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess'; import { URI } from 'vs/base/common/uri'; /** @@ -36,6 +36,8 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { readonly onDidChangeProperty = this._onDidChangeProperty.event; private readonly _onProcessExit = this._register(new Emitter()); readonly onProcessExit = this._onProcessExit.event; + private readonly _onRestoreCommands = this._register(new Emitter()); + readonly onRestoreCommands = this._onRestoreCommands.event; constructor( readonly id: number, diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts index c38b20757e8..0629896166f 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts @@ -15,7 +15,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { Registry } from 'vs/platform/registry/common/platform'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IProcessPropertyMap, IShellLaunchConfig, ITerminalChildProcess, ITerminalEnvironment, ITerminalProcessOptions, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, ProcessPropertyType, TerminalSettingId, TitleEventSource } from 'vs/platform/terminal/common/terminal'; -import { IGetTerminalLayoutInfoArgs, IProcessDetails, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess'; +import { IGetTerminalLayoutInfoArgs, IProcessDetails, ISerializedCommand, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess'; import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; @@ -47,6 +47,8 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke private readonly _onDidRequestDetach = this._register(new Emitter<{ requestId: number; workspaceId: string; instanceId: number }>()); readonly onDidRequestDetach = this._onDidRequestDetach.event; + private readonly _onRestoreCommands = this._register(new Emitter<{ id: number; commands: ISerializedCommand[] }>()); + readonly onRestoreCommands = this._onRestoreCommands.event; constructor( readonly remoteAuthority: string | undefined, @@ -80,7 +82,12 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke } }); this._localPtyService.onProcessReady(e => this._ptys.get(e.id)?.handleReady(e.event)); - this._localPtyService.onProcessReplay(e => this._ptys.get(e.id)?.handleReplay(e.event)); + this._localPtyService.onProcessReplay(e => { + this._ptys.get(e.id)?.handleReplay(e.event); + if (e.event.commands.length > 0) { + this._onRestoreCommands.fire({ id: e.id, commands: e.event.commands }); + } + }); this._localPtyService.onProcessOrphanQuestion(e => this._ptys.get(e.id)?.handleOrphanQuestion()); this._localPtyService.onDidRequestDetach(e => this._onDidRequestDetach.fire(e)); From dfd530095900d98bdeeaa5cde514e00b75b8177e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Mar 2022 18:51:33 +0100 Subject: [PATCH 125/175] Revert "show reload button when extension with different targetplatform is updated" This reverts commit dffa71af994ce24e6f3fa8c440f44afc961c5dc2. --- .../workbench/contrib/extensions/browser/extensionsActions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index d3cfdba7cda..e4d00340619 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -1427,8 +1427,8 @@ export class ReloadAction extends ExtensionAction { const runningExtensionServer = this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension)); if (isSameExtensionRunning) { - // Different version or target platform of same extension is running. Requires reload to run the current version - if (this.extension.version !== runningExtension.version || this.extension.local.targetPlatform !== runningExtension.targetPlatform) { + // Different version of same extension is running. Requires reload to run the current version + if (this.extension.version !== runningExtension.version) { this.enabled = true; this.label = localize('reloadRequired', "Reload Required"); this.tooltip = localize('postUpdateTooltip', "Please reload Visual Studio Code to enable the updated extension."); From d3aafb63475b94381cd0cdbe69ce1d6dba849acd Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Fri, 11 Mar 2022 18:57:55 +0100 Subject: [PATCH 126/175] SCM diff decorator - modified diff decorator with a pattern (#144906) * Update modified diff decorator to use a pattern * Adjust hover transition Co-authored-by: Miguel Solorio --- .../contrib/scm/browser/dirtydiffDecorator.ts | 13 ++++++++++--- .../scm/browser/media/dirtydiffDecorator.css | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts index c8d653822db..41e89303e50 100644 --- a/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts +++ b/src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts @@ -20,7 +20,7 @@ import { URI } from 'vs/base/common/uri'; import { ISCMService, ISCMRepository, ISCMProvider } from 'vs/workbench/contrib/scm/common/scm'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { registerThemingParticipant, IColorTheme, ICssStyleCollector, themeColorFromId, IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { editorErrorForeground, registerColor, transparent } from 'vs/platform/theme/common/colorRegistry'; +import { editorBackground, editorErrorForeground, registerColor, transparent } from 'vs/platform/theme/common/colorRegistry'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction } from 'vs/editor/browser/editorExtensions'; import { PeekViewWidget, getOuterEditor, peekViewBorder, peekViewTitleBackground, peekViewTitleForeground, peekViewTitleInfoForeground } from 'vs/editor/contrib/peekView/browser/peekView'; @@ -1461,15 +1461,22 @@ export class DirtyDiffWorkbenchController extends Disposable implements ext.IWor registerEditorContribution(DirtyDiffController.ID, DirtyDiffController); registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { + const editorBackgroundColor = theme.getColor(editorBackground); const editorGutterModifiedBackgroundColor = theme.getColor(editorGutterModifiedBackground); + const linearGradient = `-45deg, ${editorGutterModifiedBackgroundColor} 25%, ${editorBackgroundColor} 25%, ${editorBackgroundColor} 50%, ${editorGutterModifiedBackgroundColor} 50%, ${editorGutterModifiedBackgroundColor} 75%, ${editorBackgroundColor} 75%, ${editorBackgroundColor}`; + if (editorGutterModifiedBackgroundColor) { collector.addRule(` .monaco-editor .dirty-diff-modified { - border-left: 3px solid ${editorGutterModifiedBackgroundColor}; + background-size: 3px 3px; + background-repeat-x: no-repeat; + background-image: linear-gradient(${linearGradient}); transition: opacity 0.5s; } .monaco-editor .dirty-diff-modified:before { - background: ${editorGutterModifiedBackgroundColor}; + transform: translateX(3px); + background-size: 3px 3px; + background-image: linear-gradient(${linearGradient}); } .monaco-editor .margin:hover .dirty-diff-modified { opacity: 1; diff --git a/src/vs/workbench/contrib/scm/browser/media/dirtydiffDecorator.css b/src/vs/workbench/contrib/scm/browser/media/dirtydiffDecorator.css index dd0921f4d60..833aa22b57a 100644 --- a/src/vs/workbench/contrib/scm/browser/media/dirtydiffDecorator.css +++ b/src/vs/workbench/contrib/scm/browser/media/dirtydiffDecorator.css @@ -28,7 +28,7 @@ height: 100%; width: 0; left: -2px; - transition: width 80ms linear, left 80ms linear; + transition: width 80ms linear, left 80ms linear, transform 80ms linear; } .monaco-editor .dirty-diff-deleted:before { From 3740be6c1eb087c2d87c37740a3844d67dd333cd Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Mar 2022 20:08:48 +0100 Subject: [PATCH 127/175] Compute affinity for extensions running in a local process extension host --- .../abstractRuntimeExtensionsEditor.ts | 14 +- .../browser/browserRuntimeExtensionsEditor.ts | 28 +-- .../runtimeExtensionsEditor.ts | 4 +- .../extensions/browser/extensionService.ts | 2 +- .../common/abstractExtensionService.ts | 163 +++++++++++++++++- .../services/extensions/common/extensions.ts | 16 +- .../electron-browser/extensionService.ts | 6 +- 7 files changed, 192 insertions(+), 41 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts index 03cd181a377..3e6cc3f51db 100644 --- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts @@ -36,6 +36,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; import { Action2, MenuId } from 'vs/platform/actions/common/actions'; import { CATEGORIES } from 'vs/workbench/common/actions'; +import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; interface IExtensionProfileInformation { /** @@ -80,6 +81,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { @IStorageService storageService: IStorageService, @ILabelService private readonly _labelService: ILabelService, @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, + @IClipboardService private readonly _clipboardService: IClipboardService, ) { super(AbstractRuntimeExtensionsEditor.ID, telemetryService, themeService, storageService); @@ -427,11 +429,21 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { const actions: IAction[] = []; + actions.push(new Action( + 'runtimeExtensionsEditor.action.copyId', + nls.localize('copy id', "Copy id ({0})", e.element!.description.identifier.value), + undefined, + true, + () => { + this._clipboardService.writeText(e.element!.description.identifier.value); + } + )); + const reportExtensionIssueAction = this._createReportExtensionIssueAction(e.element); if (reportExtensionIssueAction) { actions.push(reportExtensionIssueAction); - actions.push(new Separator()); } + actions.push(new Separator()); if (e.element!.marketplaceInfo) { actions.push(new Action('runtimeExtensionsEditor.action.disableWorkspace', nls.localize('disable workspace', "Disable (Workspace)"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo!, EnablementState.DisabledWorkspace))); diff --git a/src/vs/workbench/contrib/extensions/browser/browserRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/browserRuntimeExtensionsEditor.ts index a3b1e809050..87a4c50df78 100644 --- a/src/vs/workbench/contrib/extensions/browser/browserRuntimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/browserRuntimeExtensionsEditor.ts @@ -4,38 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Action } from 'vs/base/common/actions'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IExtensionService, IExtensionHostProfile } from 'vs/workbench/services/extensions/common/extensions'; -import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IStorageService } from 'vs/platform/storage/common/storage'; -import { ILabelService } from 'vs/platform/label/common/label'; +import { IExtensionHostProfile } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { AbstractRuntimeExtensionsEditor, IRuntimeExtension } from 'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor'; export class RuntimeExtensionsEditor extends AbstractRuntimeExtensionsEditor { - constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IThemeService themeService: IThemeService, - @IContextKeyService contextKeyService: IContextKeyService, - @IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService, - @IExtensionService extensionService: IExtensionService, - @INotificationService notificationService: INotificationService, - @IContextMenuService contextMenuService: IContextMenuService, - @IInstantiationService instantiationService: IInstantiationService, - @IStorageService storageService: IStorageService, - @ILabelService labelService: ILabelService, - @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, - ) { - super(telemetryService, themeService, contextKeyService, extensionsWorkbenchService, extensionService, notificationService, contextMenuService, instantiationService, storageService, labelService, environmentService); - } - protected _getProfileInfo(): IExtensionHostProfile | null { return null; } diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/runtimeExtensionsEditor.ts index ca31c6145d1..b53ea1625f5 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/runtimeExtensionsEditor.ts @@ -26,6 +26,7 @@ import { URI } from 'vs/base/common/uri'; import { IFileService } from 'vs/platform/files/common/files'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { IV8Profile, Utils } from 'vs/platform/profiling/common/profiling'; +import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; export const IExtensionHostProfileService = createDecorator('extensionHostProfileService'); export const CONTEXT_PROFILE_SESSION_STATE = new RawContextKey('profileSessionState', 'none'); @@ -72,9 +73,10 @@ export class RuntimeExtensionsEditor extends AbstractRuntimeExtensionsEditor { @IStorageService storageService: IStorageService, @ILabelService labelService: ILabelService, @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, + @IClipboardService clipboardService: IClipboardService, @IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService, ) { - super(telemetryService, themeService, contextKeyService, extensionsWorkbenchService, extensionService, notificationService, contextMenuService, instantiationService, storageService, labelService, environmentService); + super(telemetryService, themeService, contextKeyService, extensionsWorkbenchService, extensionService, notificationService, contextMenuService, instantiationService, storageService, labelService, environmentService, clipboardService); this._profileInfo = this._extensionHostProfileService.lastProfile; this._extensionsHostRecorded = CONTEXT_EXTENSION_HOST_PROFILE_RECORDED.bindTo(contextKeyService); this._profileSessionState = CONTEXT_PROFILE_SESSION_STATE.bindTo(contextKeyService); diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts index 7e9a24b23e5..8e1c2eed1e0 100644 --- a/src/vs/workbench/services/extensions/browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/browser/extensionService.ts @@ -201,7 +201,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten const remoteAgentConnection = this._remoteAgentService.getConnection(); // `determineRunningLocation` will look at the complete picture (e.g. an extension installed on both sides), // takes care of duplicates and picks a running location for each extension - this._runningLocation = this._computeInitialRunningLocation(localExtensions, remoteExtensions); + this._runningLocation = this._computeRunningLocation(localExtensions, remoteExtensions, true); // Some remote extensions could run locally in the web worker, so store them const remoteExtensionsThatNeedToRunLocally = filterByExtensionHostKind(remoteExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 000454328c4..025fb3217dc 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -276,7 +276,136 @@ export abstract class AbstractExtensionService extends Disposable implements IEx //#region running location - protected _computeInitialRunningLocation(localExtensions: IExtensionDescription[], remoteExtensions: IExtensionDescription[]): Map { + private _computeAffinity(inputExtensions: IExtensionDescription[], extensionHostKind: ExtensionHostKind, isInitialAllocation: boolean): { affinities: Map; maxAffinity: number } { + // Only analyze extensions that can execute + const extensions = new Map(); + for (const extension of inputExtensions) { + if (extension.main || extension.browser) { + extensions.set(ExtensionIdentifier.toKey(extension.identifier), extension); + } + } + // Also add existing extensions of the same kind that can execute + for (const extension of this._registry.getAllExtensionDescriptions()) { + if (extension.main || extension.browser) { + const runningLocation = this._runningLocation.get(ExtensionIdentifier.toKey(extension.identifier)); + if (runningLocation && runningLocation.kind === extensionHostKind) { + extensions.set(ExtensionIdentifier.toKey(extension.identifier), extension); + } + } + } + + // Initially, each extension belongs to its own group + const groups = new Map(); + let groupNumber = 0; + for (const [_, extension] of extensions) { + groups.set(ExtensionIdentifier.toKey(extension.identifier), ++groupNumber); + } + + const changeGroup = (from: number, to: number) => { + for (const [key, group] of groups) { + if (group === from) { + groups.set(key, to); + } + } + }; + + // We will group things together when there are dependencies + for (const [_, extension] of extensions) { + if (!extension.extensionDependencies) { + continue; + } + const myGroup = groups.get(ExtensionIdentifier.toKey(extension.identifier))!; + for (const depId of extension.extensionDependencies) { + const depGroup = groups.get(ExtensionIdentifier.toKey(depId)); + if (!depGroup) { + // probably can't execute, so it has no impact + continue; + } + + if (depGroup === myGroup) { + // already in the same group + continue; + } + + changeGroup(depGroup, myGroup); + } + } + + // Initialize with existing affinities + const resultingAffinities = new Map(); + let lastAffinity = 0; + for (const [_, extension] of extensions) { + const runningLocation = this._runningLocation.get(ExtensionIdentifier.toKey(extension.identifier)); + if (runningLocation) { + const group = groups.get(ExtensionIdentifier.toKey(extension.identifier))!; + resultingAffinities.set(group, runningLocation.affinity); + lastAffinity = Math.max(lastAffinity, runningLocation.affinity); + } + } + + // Go through each configured affinity and try to accomodate it + const configuredAffinities = this._configurationService.getValue<{ [extensionId: string]: number } | undefined>('extensions.experimental.affinity') || {}; + const configuredExtensionIds = Object.keys(configuredAffinities); + const configuredAffinityToResultingAffinity = new Map(); + for (const extensionId of configuredExtensionIds) { + const configuredAffinity = configuredAffinities[extensionId]; + if (typeof configuredAffinity !== 'number' || configuredAffinity <= 0 || Math.floor(configuredAffinity) !== configuredAffinity) { + this._logService.info(`Ignoring configured affinity for '${extensionId}' because the value is not a positive integer.`); + continue; + } + const group = groups.get(ExtensionIdentifier.toKey(extensionId)); + if (!group) { + this._logService.info(`Ignoring configured affinity for '${extensionId}' because the extension is unknown or cannot execute.`); + continue; + } + + const affinity1 = resultingAffinities.get(group); + if (affinity1) { + // Affinity for this group is already established + configuredAffinityToResultingAffinity.set(configuredAffinity, affinity1); + continue; + } + + const affinity2 = configuredAffinityToResultingAffinity.get(configuredAffinity); + if (affinity2) { + // Affinity for this configuration is already established + resultingAffinities.set(group, affinity2); + continue; + } + + if (!isInitialAllocation) { + this._logService.info(`Ignoring configured affinity for '${extensionId}' because extension host(s) are already running. Reload window.`); + continue; + } + + const affinity3 = ++lastAffinity; + configuredAffinityToResultingAffinity.set(configuredAffinity, affinity3); + resultingAffinities.set(group, affinity3); + } + + const result = new Map(); + for (const extension of inputExtensions) { + const group = groups.get(ExtensionIdentifier.toKey(extension.identifier)) || 0; + const affinity = resultingAffinities.get(group) || 0; + result.set(ExtensionIdentifier.toKey(extension.identifier), affinity); + } + + if (lastAffinity > 0 && isInitialAllocation) { + for (let affinity = 1; affinity <= lastAffinity; affinity++) { + const extensionIds: ExtensionIdentifier[] = []; + for (const extension of inputExtensions) { + if (result.get(ExtensionIdentifier.toKey(extension.identifier)) === affinity) { + extensionIds.push(extension.identifier); + } + } + this._logService.info(`Placing extension(s) ${extensionIds.map(e => e.value).join(', ')} on a separate extension host.`); + } + } + + return { affinities: result, maxAffinity: lastAffinity }; + } + + protected _computeRunningLocation(localExtensions: IExtensionDescription[], remoteExtensions: IExtensionDescription[], isInitialAllocation: boolean): Map { const extensionHostKinds = ExtensionHostKindClassifier.determineExtensionHostKinds( localExtensions, remoteExtensions, @@ -284,11 +413,23 @@ export abstract class AbstractExtensionService extends Disposable implements IEx (extensionId, extensionKinds, isInstalledLocally, isInstalledRemotely, preference) => this._pickExtensionHostKind(extensionId, extensionKinds, isInstalledLocally, isInstalledRemotely, preference) ); + const extensions = new Map(); + for (const extension of localExtensions) { + extensions.set(ExtensionIdentifier.toKey(extension.identifier), extension); + } + for (const extension of remoteExtensions) { + extensions.set(ExtensionIdentifier.toKey(extension.identifier), extension); + } + const result = new Map(); + const localProcessExtensions: IExtensionDescription[] = []; for (const [extensionIdKey, extensionHostKind] of extensionHostKinds) { let runningLocation: ExtensionRunningLocation | null = null; if (extensionHostKind === ExtensionHostKind.LocalProcess) { - runningLocation = new LocalProcessRunningLocation(); + const extensionDescription = extensions.get(ExtensionIdentifier.toKey(extensionIdKey)); + if (extensionDescription) { + localProcessExtensions.push(extensionDescription); + } } else if (extensionHostKind === ExtensionHostKind.LocalWebWorker) { runningLocation = new LocalWebWorkerRunningLocation(); } else if (extensionHostKind === ExtensionHostKind.Remote) { @@ -296,6 +437,13 @@ export abstract class AbstractExtensionService extends Disposable implements IEx } result.set(extensionIdKey, runningLocation); } + + const { affinities } = this._computeAffinity(localProcessExtensions, ExtensionHostKind.LocalProcess, isInitialAllocation); + for (const extension of localProcessExtensions) { + const affinity = affinities.get(ExtensionIdentifier.toKey(extension.identifier)) || 0; + result.set(ExtensionIdentifier.toKey(extension.identifier), new LocalProcessRunningLocation(affinity)); + } + return result; } @@ -304,13 +452,14 @@ export abstract class AbstractExtensionService extends Disposable implements IEx */ private _updateRunningLocationForAddedExtensions(toAdd: IExtensionDescription[]): void { // Determine new running location + const localProcessExtensions: IExtensionDescription[] = []; for (const extension of toAdd) { const extensionKind = this._getExtensionKind(extension); const isRemote = extension.extensionLocation.scheme === Schemas.vscodeRemote; const extensionHostKind = this._pickExtensionHostKind(extension.identifier, extensionKind, !isRemote, isRemote, ExtensionRunningPreference.None); let runningLocation: ExtensionRunningLocation | null = null; if (extensionHostKind === ExtensionHostKind.LocalProcess) { - runningLocation = new LocalProcessRunningLocation(); + localProcessExtensions.push(extension); } else if (extensionHostKind === ExtensionHostKind.LocalWebWorker) { runningLocation = new LocalWebWorkerRunningLocation(); } else if (extensionHostKind === ExtensionHostKind.Remote) { @@ -318,6 +467,12 @@ export abstract class AbstractExtensionService extends Disposable implements IEx } this._runningLocation.set(ExtensionIdentifier.toKey(extension.identifier), runningLocation); } + + const { affinities } = this._computeAffinity(localProcessExtensions, ExtensionHostKind.LocalProcess, false); + for (const extension of localProcessExtensions) { + const affinity = affinities.get(ExtensionIdentifier.toKey(extension.identifier)) || 0; + this._runningLocation.set(ExtensionIdentifier.toKey(extension.identifier), new LocalProcessRunningLocation(affinity)); + } } //#endregion @@ -608,7 +763,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx // When a debugger attaches to the extension host, it will surface all console.log messages from the extension host, // but not necessarily from the window. So it would be best if any errors get printed to the console of the extension host. // That is why here we use the local process extension host even for non-file URIs - runningLocation = new LocalProcessRunningLocation(); + runningLocation = new LocalProcessRunningLocation(0); } } if (runningLocation !== null) { diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index f549c009a7b..da5b3e915ac 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -39,17 +39,24 @@ export interface IMessage { export class LocalProcessRunningLocation { public readonly kind = ExtensionHostKind.LocalProcess; + constructor( + public readonly affinity: number + ) { } public equals(other: ExtensionRunningLocation) { - return this.kind === other.kind; + return (this.kind === other.kind && this.affinity === other.affinity); } public asString(): string { - return 'LocalProcess'; + if (this.affinity === 0) { + return 'LocalProcess'; + } + return `LocalProcess${this.affinity}`; } } export class LocalWebWorkerRunningLocation { public readonly kind = ExtensionHostKind.LocalWebWorker; + public readonly affinity = 0; public equals(other: ExtensionRunningLocation) { - return this.kind === other.kind; + return (this.kind === other.kind); } public asString(): string { return 'LocalWebWorker'; @@ -57,8 +64,9 @@ export class LocalWebWorkerRunningLocation { } export class RemoteRunningLocation { public readonly kind = ExtensionHostKind.Remote; + public readonly affinity = 0; public equals(other: ExtensionRunningLocation) { - return this.kind === other.kind; + return (this.kind === other.kind); } public asString(): string { return 'Remote'; diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index edad11cc75b..dbaaab3c904 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -160,7 +160,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten if (isInitialStart) { // Here we load even extensions that would be disabled by workspace trust const localExtensions = this._checkEnabledAndProposedAPI(await this._scanAllLocalExtensions(), /* ignore workspace trust */true); - const runningLocation = this._computeInitialRunningLocation(localExtensions, []); + const runningLocation = this._computeRunningLocation(localExtensions, [], false); const localProcessExtensions = filterByRunningLocation(localExtensions, runningLocation, desiredRunningLocation); return { autoStart: false, @@ -237,7 +237,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten protected _createExtensionHosts(isInitialStart: boolean): IExtensionHost[] { const result: IExtensionHost[] = []; - const localProcessRunningLocation = new LocalProcessRunningLocation(); + const localProcessRunningLocation = new LocalProcessRunningLocation(0); const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, localProcessRunningLocation, this._createLocalExtensionHostDataProvider(isInitialStart, localProcessRunningLocation)); result.push(localProcessExtHost); @@ -545,7 +545,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten remoteExtensions = this._checkEnabledAndProposedAPI(remoteExtensions, false); const localExtensions = this._checkEnabledAndProposedAPI(await this._scanAllLocalExtensions(), false); - this._runningLocation = this._computeInitialRunningLocation(localExtensions, remoteExtensions); + this._runningLocation = this._computeRunningLocation(localExtensions, remoteExtensions, true); // remove non-UI extensions from the local extensions const localProcessExtensions = filterByExtensionHostKind(localExtensions, this._runningLocation, ExtensionHostKind.LocalProcess); From 420e8724641a92df43b796fcc2ce705039ad7d3e Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Fri, 11 Mar 2022 12:01:16 -0800 Subject: [PATCH 128/175] Update Codicons: Adjust layout-statusbar https://github.com/microsoft/vscode-codicons/commit/4b27dcfb2f5068b06c9d329ca33300ccc273aea1 --- .../browser/ui/codicons/codicon/codicon.ttf | Bin 70776 -> 70776 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon.ttf b/src/vs/base/browser/ui/codicons/codicon/codicon.ttf index 7eba31492ba78bbdc6cb62f91c005e051c790057..02beee38fd2f2b644f420ff9cb3fc397b4c82a94 100644 GIT binary patch delta 58 zcmV-A0LB0Ks08?^1du=k*x_)|kwjbp&yk@=1Sgvdjj`;0h6xkl5)$DP;m*#pbBDck Q0XLH|{fhxNv%USh7B`6-`v3p{ delta 58 zcmV-A0LB0Ks08?^1du=k#?W2Rkwjbp&5@x;1W&y&kFo52h6xhk6BFSQ&b+*{bBDck Q0XCB{{fhxMv%USh7C0Xp`v3p{ From 9925da41e4523ce5efdff8448899be9a7d7e8f67 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 11 Mar 2022 11:44:22 -0800 Subject: [PATCH 129/175] Fix wrong notebook cell drag offset with global toolbar active --- .../contrib/notebook/browser/view/cellParts/cellDnd.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts index de90b76a0ff..11c165dbe51 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts @@ -44,11 +44,11 @@ export class CellDragAndDropController extends Disposable { constructor( private readonly notebookEditor: INotebookEditorDelegate, - insertionIndicatorContainer: HTMLElement + private readonly notebookListContainer: HTMLElement ) { super(); - this.listInsertionIndicator = DOM.append(insertionIndicatorContainer, $('.cell-list-insertion-indicator')); + this.listInsertionIndicator = DOM.append(notebookListContainer, $('.cell-list-insertion-indicator')); this._register(DOM.addDisposableListener(document.body, DOM.EventType.DRAG_START, this.onGlobalDragStart.bind(this), true)); this._register(DOM.addDisposableListener(document.body, DOM.EventType.DRAG_END, this.onGlobalDragEnd.bind(this), true)); @@ -110,7 +110,7 @@ export class CellDragAndDropController extends Disposable { } private toCellDragEvent(event: DragEvent): CellDragEvent | undefined { - const targetTop = this.notebookEditor.getDomNode().getBoundingClientRect().top; + const targetTop = this.notebookListContainer.getBoundingClientRect().top; const dragOffset = this.list.scrollTop + event.clientY - targetTop; const draggedOverCell = this.list.elementAt(dragOffset); if (!draggedOverCell) { From a6b461df7f6176b90ea961f972d5eb42dc2ed787 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 11 Mar 2022 12:04:51 -0800 Subject: [PATCH 130/175] Fix wrong run button color in non-focused notebook cell --- src/vs/workbench/contrib/notebook/browser/media/notebook.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index baf7eafb288..53e3584e427 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -531,7 +531,7 @@ flex-direction: row-reverse; } -.monaco-workbench .notebookOverlay .monaco-list:focus-within .monaco-list-row.focused .codicon:not(.suggest-icon) { +.monaco-workbench .notebookOverlay .monaco-list:focus-within .monaco-list-row .codicon:not(.suggest-icon) { color: inherit; } From 92bf104b5294d976c0fcfbdc69e43ba70208b6e8 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 11 Mar 2022 12:33:43 -0800 Subject: [PATCH 131/175] Spelling --- .../contrib/markdownRenderer/browser/markdownRenderer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/markdownRenderer/browser/markdownRenderer.ts b/src/vs/editor/contrib/markdownRenderer/browser/markdownRenderer.ts index d5cb8c34935..2a323d76679 100644 --- a/src/vs/editor/contrib/markdownRenderer/browser/markdownRenderer.ts +++ b/src/vs/editor/contrib/markdownRenderer/browser/markdownRenderer.ts @@ -64,7 +64,7 @@ export class MarkdownRenderer { }; } - protected _getRenderOptions(markdown: IMarkdownString, disposeables: DisposableStore): MarkdownRenderOptions { + protected _getRenderOptions(markdown: IMarkdownString, disposables: DisposableStore): MarkdownRenderOptions { return { codeBlockRenderer: async (languageAlias, value) => { // In markdown, @@ -98,7 +98,7 @@ export class MarkdownRenderer { asyncRenderCallback: () => this._onDidRenderAsync.fire(), actionHandler: { callback: (content) => this._openerService.open(content, { fromUserGesture: true, allowContributedOpeners: true, allowCommands: markdown.isTrusted }).catch(onUnexpectedError), - disposables: disposeables + disposables: disposables } }; } From c521f36041dd318ed32268d6aedefcdd7adef959 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 11 Mar 2022 13:00:27 -0800 Subject: [PATCH 132/175] Fix anchors and data images in extension pages Fixes #144897 Refactors to have a single `hookDomPurifyHrefAndSrcSanitizer` function that handles sanitizing the href and src attributes. Also updates this function to allow fragment links `#` and data images --- src/vs/base/browser/dom.ts | 64 +++++++++++++------ src/vs/base/browser/markdownRenderer.ts | 18 +----- .../browser/markdownDocumentRenderer.ts | 21 ++---- 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 54366a688e9..73071670728 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -1417,6 +1417,49 @@ export function detectFullscreen(): IDetectedFullscreen | null { // -- sanitize and trusted html +/** + * Hooks dompurify using `afterSanitizeAttributes` to check that all `href` and `src` + * attributes are valid. + */ +export function hookDomPurifyHrefAndSrcSanitizer(allowedProtocols: readonly string[], allowDataImages = false): IDisposable { + // https://github.com/cure53/DOMPurify/blob/main/demos/hooks-scheme-allowlist.html + + // build an anchor to map URLs to + const anchor = document.createElement('a'); + + dompurify.addHook('afterSanitizeAttributes', (node) => { + // check all href/src attributes for validity + for (const attr of ['href', 'src']) { + if (node.hasAttribute(attr)) { + const attrValue = node.getAttribute(attr) as string; + if (attr === 'href' && attrValue.startsWith('#')) { + // Allow fragment links + continue; + } + + anchor.href = attrValue; + if (!allowedProtocols.includes(anchor.protocol.replace(/:$/, ''))) { + if (allowDataImages && attr === 'src' && anchor.href.startsWith('data:')) { + continue; + } + + node.removeAttribute(attr); + } + } + } + }); + + return toDisposable(() => { + dompurify.removeHook('afterSanitizeAttributes'); + }); +} + +const defaultSafeProtocols = [ + Schemas.http, + Schemas.https, + Schemas.command, +]; + /** * Sanitizes the given `value` and reset the given `node` with it. */ @@ -1428,29 +1471,12 @@ export function safeInnerHtml(node: HTMLElement, value: string): void { RETURN_DOM_FRAGMENT: false, }; - const allowedProtocols = [Schemas.http, Schemas.https, Schemas.command]; - - // https://github.com/cure53/DOMPurify/blob/main/demos/hooks-scheme-allowlist.html - dompurify.addHook('afterSanitizeAttributes', (node) => { - // build an anchor to map URLs to - const anchor = document.createElement('a'); - - // check all href/src attributes for validity - for (const attr in ['href', 'src']) { - if (node.hasAttribute(attr)) { - anchor.href = node.getAttribute(attr) as string; - if (!allowedProtocols.includes(anchor.protocol)) { - node.removeAttribute(attr); - } - } - } - }); - + const hook = hookDomPurifyHrefAndSrcSanitizer(defaultSafeProtocols); try { const html = dompurify.sanitize(value, { ...options, RETURN_TRUSTED_TYPE: true }); node.innerHTML = html as unknown as string; } finally { - dompurify.removeHook('afterSanitizeAttributes'); + hook.dispose(); } } diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index 813218db45b..61108e58c67 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -326,27 +326,13 @@ function sanitizeRenderedMarkdown( } }); - // build an anchor to map URLs to - const anchor = document.createElement('a'); - - // https://github.com/cure53/DOMPurify/blob/main/demos/hooks-scheme-allowlist.html - dompurify.addHook('afterSanitizeAttributes', (node) => { - // check all href/src attributes for validity - for (const attr of ['href', 'src']) { - if (node.hasAttribute(attr)) { - anchor.href = node.getAttribute(attr) as string; - if (!allowedSchemes.includes(anchor.protocol.replace(/:$/, ''))) { - node.removeAttribute(attr); - } - } - } - }); + const hook = DOM.hookDomPurifyHrefAndSrcSanitizer(allowedSchemes); try { return dompurify.sanitize(renderedMarkdown, { ...config, RETURN_TRUSTED_TYPE: true }); } finally { dompurify.removeHook('uponSanitizeAttribute'); - dompurify.removeHook('afterSanitizeAttributes'); + hook.dispose(); } } diff --git a/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts b/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts index 1c602d327e3..c47ff0b58ff 100644 --- a/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts +++ b/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts @@ -3,11 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { hookDomPurifyHrefAndSrcSanitizer } from 'vs/base/browser/dom'; import * as dompurify from 'vs/base/browser/dompurify/dompurify'; import { marked } from 'vs/base/common/marked/marked'; import { Schemas } from 'vs/base/common/network'; -import { tokenizeToString } from 'vs/editor/common/languages/textToHtmlTokenizer'; import { ILanguageService } from 'vs/editor/common/languages/language'; +import { tokenizeToString } from 'vs/editor/common/languages/textToHtmlTokenizer'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; export const DEFAULT_MARKDOWN_STYLES = ` @@ -152,21 +153,7 @@ code > div { const allowedProtocols = [Schemas.http, Schemas.https, Schemas.command]; function sanitize(documentContent: string, allowUnknownProtocols: boolean): string { - // https://github.com/cure53/DOMPurify/blob/main/demos/hooks-scheme-allowlist.html - dompurify.addHook('afterSanitizeAttributes', (node) => { - // build an anchor to map URLs to - const anchor = document.createElement('a'); - - // check all href/src attributes for validity - for (const attr of ['href', 'src']) { - if (node.hasAttribute(attr)) { - anchor.href = node.getAttribute(attr) as string; - if (!allowedProtocols.includes(anchor.protocol.replace(/:$/, ''))) { - node.removeAttribute(attr); - } - } - } - }); + const hook = hookDomPurifyHrefAndSrcSanitizer(allowedProtocols, true); try { return dompurify.sanitize(documentContent, { @@ -186,7 +173,7 @@ function sanitize(documentContent: string, allowUnknownProtocols: boolean): stri ...(allowUnknownProtocols ? { ALLOW_UNKNOWN_PROTOCOLS: true } : {}), }); } finally { - dompurify.removeHook('afterSanitizeAttributes'); + hook.dispose(); } } From 5b3c42cb261dc73254e3d95fa01fa26eaf368704 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Mar 2022 22:07:01 +0100 Subject: [PATCH 133/175] Launch multiple extension host processes --- .../extensions/browser/extensionService.ts | 45 ++++---- .../common/abstractExtensionService.ts | 105 +++++++++++++----- .../electron-browser/extensionService.ts | 56 +++++----- 3 files changed, 124 insertions(+), 82 deletions(-) diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts index 8e1c2eed1e0..3484860be18 100644 --- a/src/vs/workbench/services/extensions/browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/browser/extensionService.ts @@ -9,11 +9,11 @@ import { IWorkbenchExtensionEnablementService, IWebExtensionsScannerService } fr import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IExtensionService, IExtensionHost, toExtensionDescription, ExtensionRunningLocation, ExtensionHostKind, RemoteRunningLocation, LocalWebWorkerRunningLocation, extensionHostKindToString } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionService, IExtensionHost, toExtensionDescription, ExtensionRunningLocation, ExtensionHostKind, extensionHostKindToString } from 'vs/workbench/services/extensions/common/extensions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { IProductService } from 'vs/platform/product/common/productService'; -import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString, filterByExtensionHostKind, filterByRunningLocation } from 'vs/workbench/services/extensions/common/abstractExtensionService'; +import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString } from 'vs/workbench/services/extensions/common/abstractExtensionService'; import { RemoteExtensionHost, IRemoteExtensionHostDataProvider, IRemoteExtensionHostInitData } from 'vs/workbench/services/extensions/common/remoteExtensionHost'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IWebWorkerExtensionHostDataProvider, WebWorkerExtensionHost } from 'vs/workbench/services/extensions/browser/webWorkerExtensionHost'; @@ -72,8 +72,6 @@ export class ExtensionService extends AbstractExtensionService implements IExten logService ); - this._runningLocation = new Map(); - // Initialize installed extensions first and do it only after workbench is ready this._lifecycleService.when(LifecyclePhase.Ready).then(async () => { await this._userDataInitializationService.initializeInstalledExtensions(this._instantiationService); @@ -111,7 +109,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten return { getInitData: async () => { const allExtensions = await this.getExtensions(); - const localWebWorkerExtensions = filterByRunningLocation(allExtensions, this._runningLocation, desiredRunningLocation); + const localWebWorkerExtensions = this._filterByRunningLocation(allExtensions, desiredRunningLocation); return { autoStart: true, extensions: localWebWorkerExtensions @@ -171,21 +169,22 @@ export class ExtensionService extends AbstractExtensionService implements IExten return (result.length > 0 ? result[0] : null); } - protected _createExtensionHosts(_isInitialStart: boolean): IExtensionHost[] { - const result: IExtensionHost[] = []; - - const localWebWorkerRunningLocation = new LocalWebWorkerRunningLocation(); - const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, localWebWorkerRunningLocation, false, this._createLocalExtensionHostDataProvider(localWebWorkerRunningLocation)); - result.push(webWorkerExtHost); - - const remoteAgentConnection = this._remoteAgentService.getConnection(); - if (remoteAgentConnection) { - const remoteRunningLocation = new RemoteRunningLocation(); - const remoteExtHost = this._instantiationService.createInstance(RemoteExtensionHost, remoteRunningLocation, this._createRemoteExtensionHostDataProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory); - result.push(remoteExtHost); + protected _createExtensionHost(runningLocation: ExtensionRunningLocation, _isInitialStart: boolean): IExtensionHost | null { + switch (runningLocation.kind) { + case ExtensionHostKind.LocalProcess: { + return null; + } + case ExtensionHostKind.LocalWebWorker: { + return this._instantiationService.createInstance(WebWorkerExtensionHost, runningLocation, false, this._createLocalExtensionHostDataProvider(runningLocation)); + } + case ExtensionHostKind.Remote: { + const remoteAgentConnection = this._remoteAgentService.getConnection(); + if (remoteAgentConnection) { + return this._instantiationService.createInstance(RemoteExtensionHost, runningLocation, this._createRemoteExtensionHostDataProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory); + } + return null; + } } - - return result; } protected async _scanAndHandleExtensions(): Promise { @@ -201,12 +200,12 @@ export class ExtensionService extends AbstractExtensionService implements IExten const remoteAgentConnection = this._remoteAgentService.getConnection(); // `determineRunningLocation` will look at the complete picture (e.g. an extension installed on both sides), // takes care of duplicates and picks a running location for each extension - this._runningLocation = this._computeRunningLocation(localExtensions, remoteExtensions, true); + this._initializeRunningLocation(localExtensions, remoteExtensions); // Some remote extensions could run locally in the web worker, so store them - const remoteExtensionsThatNeedToRunLocally = filterByExtensionHostKind(remoteExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); - localExtensions = filterByExtensionHostKind(localExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); - remoteExtensions = filterByExtensionHostKind(remoteExtensions, this._runningLocation, ExtensionHostKind.Remote); + const remoteExtensionsThatNeedToRunLocally = this._filterByExtensionHostKind(remoteExtensions, ExtensionHostKind.LocalWebWorker); + localExtensions = this._filterByExtensionHostKind(localExtensions, ExtensionHostKind.LocalWebWorker); + remoteExtensions = this._filterByExtensionHostKind(remoteExtensions, ExtensionHostKind.Remote); // Add locally the remote extensions that need to run locally in the web worker for (const ext of remoteExtensionsThatNeedToRunLocally) { diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 025fb3217dc..ab89f991856 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -132,28 +132,28 @@ export abstract class AbstractExtensionService extends Disposable implements IEx public _serviceBrand: undefined; - protected readonly _onDidRegisterExtensions: Emitter = this._register(new Emitter()); + private readonly _onDidRegisterExtensions: Emitter = this._register(new Emitter()); public readonly onDidRegisterExtensions = this._onDidRegisterExtensions.event; - protected readonly _onDidChangeExtensionsStatus: Emitter = this._register(new Emitter()); + private readonly _onDidChangeExtensionsStatus: Emitter = this._register(new Emitter()); public readonly onDidChangeExtensionsStatus: Event = this._onDidChangeExtensionsStatus.event; - protected readonly _onDidChangeExtensions: Emitter = this._register(new Emitter({ leakWarningThreshold: 400 })); + private readonly _onDidChangeExtensions: Emitter = this._register(new Emitter({ leakWarningThreshold: 400 })); public readonly onDidChangeExtensions: Event = this._onDidChangeExtensions.event; - protected readonly _onWillActivateByEvent = this._register(new Emitter()); + private readonly _onWillActivateByEvent = this._register(new Emitter()); public readonly onWillActivateByEvent: Event = this._onWillActivateByEvent.event; - protected readonly _onDidChangeResponsiveChange = this._register(new Emitter()); + private readonly _onDidChangeResponsiveChange = this._register(new Emitter()); public readonly onDidChangeResponsiveChange: Event = this._onDidChangeResponsiveChange.event; protected readonly _registry: ExtensionDescriptionRegistry; private readonly _registryLock: Lock; private readonly _installedExtensionsReady: Barrier; - protected readonly _isDev: boolean; + private readonly _isDev: boolean; private readonly _extensionsMessages: Map; - protected readonly _allRequestedActivateEvents = new Set(); + private readonly _allRequestedActivateEvents = new Set(); private readonly _proposedApiController: ProposedApiController; private readonly _isExtensionDevHost: boolean; protected readonly _isExtensionDevTestFromCli: boolean; @@ -161,11 +161,12 @@ export abstract class AbstractExtensionService extends Disposable implements IEx private _deltaExtensionsQueue: DeltaExtensionsQueueItem[]; private _inHandleDeltaExtensions: boolean; - protected _runningLocation: Map; + private _runningLocation: Map; private _lastExtensionHostId: number = 0; + private _maxLocalProcessAffinity: number = 0; // --- Members used per extension host process - protected _extensionHostManagers: IExtensionHostManager[]; + private _extensionHostManagers: IExtensionHostManager[]; protected _extensionHostActiveExtensions: Map; private _extensionHostActivationTimes: Map; private _extensionHostExtensionRuntimeErrors: Map; @@ -405,7 +406,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx return { affinities: result, maxAffinity: lastAffinity }; } - protected _computeRunningLocation(localExtensions: IExtensionDescription[], remoteExtensions: IExtensionDescription[], isInitialAllocation: boolean): Map { + private _computeRunningLocation(localExtensions: IExtensionDescription[], remoteExtensions: IExtensionDescription[], isInitialAllocation: boolean): { runningLocation: Map; maxLocalProcessAffinity: number } { const extensionHostKinds = ExtensionHostKindClassifier.determineExtensionHostKinds( localExtensions, remoteExtensions, @@ -438,13 +439,24 @@ export abstract class AbstractExtensionService extends Disposable implements IEx result.set(extensionIdKey, runningLocation); } - const { affinities } = this._computeAffinity(localProcessExtensions, ExtensionHostKind.LocalProcess, isInitialAllocation); + const { affinities, maxAffinity } = this._computeAffinity(localProcessExtensions, ExtensionHostKind.LocalProcess, isInitialAllocation); for (const extension of localProcessExtensions) { const affinity = affinities.get(ExtensionIdentifier.toKey(extension.identifier)) || 0; result.set(ExtensionIdentifier.toKey(extension.identifier), new LocalProcessRunningLocation(affinity)); } - return result; + return { runningLocation: result, maxLocalProcessAffinity: maxAffinity }; + } + + protected _determineRunningLocation(localExtensions: IExtensionDescription[]): Map { + return this._computeRunningLocation(localExtensions, [], false).runningLocation; + } + + protected _initializeRunningLocation(localExtensions: IExtensionDescription[], remoteExtensions: IExtensionDescription[]): void { + const { runningLocation, maxLocalProcessAffinity } = this._computeRunningLocation(localExtensions, remoteExtensions, true); + this._runningLocation = runningLocation; + this._maxLocalProcessAffinity = maxLocalProcessAffinity; + this._startExtensionHostsIfNecessary(true, []); } /** @@ -475,6 +487,18 @@ export abstract class AbstractExtensionService extends Disposable implements IEx } } + protected _filterByRunningLocation(extensions: IExtensionDescription[], desiredRunningLocation: ExtensionRunningLocation): IExtensionDescription[] { + return filterByRunningLocation(extensions, this._runningLocation, desiredRunningLocation); + } + + protected _filterByExtensionHostKind(extensions: IExtensionDescription[], desiredExtensionHostKind: ExtensionHostKind): IExtensionDescription[] { + return filterByExtensionHostKind(extensions, this._runningLocation, desiredExtensionHostKind); + } + + protected _filterByExtensionHostManager(extensions: IExtensionDescription[], extensionHostManager: IExtensionHostManager): IExtensionDescription[] { + return filterByExtensionHostManager(extensions, this._runningLocation, extensionHostManager); + } + //#endregion //#region deltaExtensions @@ -705,7 +729,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx protected async _initialize(): Promise { perf.mark('code/willLoadExtensions'); - this._startExtensionHosts(true, []); + this._startExtensionHostsIfNecessary(true, []); const lock = await this._registryLock.acquire('_initialize'); try { @@ -799,21 +823,42 @@ export abstract class AbstractExtensionService extends Disposable implements IEx } } - private _startExtensionHosts(isInitialStart: boolean, initialActivationEvents: string[]): void { - const extensionHosts = this._createExtensionHosts(isInitialStart); - extensionHosts.forEach((extensionHost) => { - const extensionHostId = String(++this._lastExtensionHostId); - const processManager: IExtensionHostManager = createExtensionHostManager(this._instantiationService, extensionHostId, extensionHost, isInitialStart, initialActivationEvents, this._acquireInternalAPI()); - processManager.onDidExit(([code, signal]) => this._onExtensionHostCrashOrExit(processManager, code, signal)); - processManager.onDidChangeResponsiveState((responsiveState) => { - this._onDidChangeResponsiveChange.fire({ - extensionHostId: extensionHostId, - extensionHostKind: processManager.kind, - isResponsive: responsiveState === ResponsiveState.Responsive - }); + private _startExtensionHostsIfNecessary(isInitialStart: boolean, initialActivationEvents: string[]): void { + const locations: ExtensionRunningLocation[] = []; + for (let affinity = 0; affinity <= this._maxLocalProcessAffinity; affinity++) { + locations.push(new LocalProcessRunningLocation(affinity)); + } + locations.push(new LocalWebWorkerRunningLocation()); + locations.push(new RemoteRunningLocation()); + for (const location of locations) { + if (this._getExtensionHostManagerByRunningLocation(location)) { + // already running + continue; + } + const extHostManager = this._createExtensionHostManager(location, isInitialStart, initialActivationEvents); + if (extHostManager) { + this._extensionHostManagers.push(extHostManager); + } + } + } + + private _createExtensionHostManager(runningLocation: ExtensionRunningLocation, isInitialStart: boolean, initialActivationEvents: string[]): IExtensionHostManager | null { + const extensionHost = this._createExtensionHost(runningLocation, isInitialStart); + if (!extensionHost) { + return null; + } + + const extensionHostId = String(++this._lastExtensionHostId); + const processManager: IExtensionHostManager = createExtensionHostManager(this._instantiationService, extensionHostId, extensionHost, isInitialStart, initialActivationEvents, this._acquireInternalAPI()); + processManager.onDidExit(([code, signal]) => this._onExtensionHostCrashOrExit(processManager, code, signal)); + processManager.onDidChangeResponsiveState((responsiveState) => { + this._onDidChangeResponsiveChange.fire({ + extensionHostId: extensionHostId, + extensionHostKind: processManager.kind, + isResponsive: responsiveState === ResponsiveState.Responsive }); - this._extensionHostManagers.push(processManager); }); + return processManager; } private _onExtensionHostCrashOrExit(extensionHost: IExtensionHostManager, code: number, signal: string | null): void { @@ -847,7 +892,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx const lock = await this._registryLock.acquire('startExtensionHosts'); try { - this._startExtensionHosts(false, Array.from(this._allRequestedActivateEvents.keys())); + this._startExtensionHostsIfNecessary(false, Array.from(this._allRequestedActivateEvents.keys())); const localProcessExtensionHosts = this._getExtensionHostManagers(ExtensionHostKind.LocalProcess); await Promise.all(localProcessExtensionHosts.map(extHost => extHost.ready())); @@ -1238,7 +1283,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx //#endregion - protected abstract _createExtensionHosts(isInitialStart: boolean): IExtensionHost[]; + protected abstract _createExtensionHost(runningLocation: ExtensionRunningLocation, isInitialStart: boolean): IExtensionHost | null; protected abstract _scanAndHandleExtensions(): Promise; protected abstract _scanSingleExtension(extension: IExtension): Promise; public abstract _onExtensionHostExit(code: number): void; @@ -1453,11 +1498,11 @@ function _filterByRunningLocation(extensions: T[], extId: (item: T) => Extens return _filterExtensions(extensions, extId, runningLocation, extRunningLocation => desiredRunningLocation.equals(extRunningLocation)); } -export function filterByExtensionHostKind(extensions: IExtensionDescription[], runningLocation: Map, desiredExtensionHostKind: ExtensionHostKind): IExtensionDescription[] { +function filterByExtensionHostKind(extensions: IExtensionDescription[], runningLocation: Map, desiredExtensionHostKind: ExtensionHostKind): IExtensionDescription[] { return _filterExtensions(extensions, ext => ext.identifier, runningLocation, extRunningLocation => extRunningLocation.kind === desiredExtensionHostKind); } -export function filterByExtensionHostManager(extensions: IExtensionDescription[], runningLocation: Map, extensionHostManager: IExtensionHostManager): IExtensionDescription[] { +function filterByExtensionHostManager(extensions: IExtensionDescription[], runningLocation: Map, extensionHostManager: IExtensionHostManager): IExtensionDescription[] { return _filterByExtensionHostManager(extensions, ext => ext.identifier, runningLocation, extensionHostManager); } diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index dbaaab3c904..241c06d4f07 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -7,7 +7,7 @@ import { ILocalProcessExtensionHostDataProvider, LocalProcessExtensionHost } fro import { CachedExtensionScanner } from 'vs/workbench/services/extensions/electron-sandbox/cachedExtensionScanner'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString, filterByExtensionHostManager, filterByExtensionHostKind, filterByRunningLocation } from 'vs/workbench/services/extensions/common/abstractExtensionService'; +import { AbstractExtensionService, ExtensionRunningPreference, extensionRunningPreferenceToString, filterByRunningLocation } from 'vs/workbench/services/extensions/common/abstractExtensionService'; import * as nls from 'vs/nls'; import { runWhenIdle } from 'vs/base/common/async'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -22,7 +22,7 @@ import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecyc import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { IExtensionService, toExtension, ExtensionHostKind, IExtensionHost, webWorkerExtHostConfig, ExtensionRunningLocation, WebWorkerExtHostConfigValue, extensionHostKindToString, LocalProcessRunningLocation, RemoteRunningLocation, LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtensionService, toExtension, ExtensionHostKind, IExtensionHost, webWorkerExtHostConfig, ExtensionRunningLocation, WebWorkerExtHostConfigValue, extensionHostKindToString } from 'vs/workbench/services/extensions/common/extensions'; import { IExtensionHostManager } from 'vs/workbench/services/extensions/common/extensionHostManager'; import { ExtensionIdentifier, IExtension, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { ExtensionKind } from 'vs/platform/environment/common/environment'; @@ -160,7 +160,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten if (isInitialStart) { // Here we load even extensions that would be disabled by workspace trust const localExtensions = this._checkEnabledAndProposedAPI(await this._scanAllLocalExtensions(), /* ignore workspace trust */true); - const runningLocation = this._computeRunningLocation(localExtensions, [], false); + const runningLocation = this._determineRunningLocation(localExtensions); const localProcessExtensions = filterByRunningLocation(localExtensions, runningLocation, desiredRunningLocation); return { autoStart: false, @@ -169,7 +169,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten } else { // restart case const allExtensions = await this.getExtensions(); - const localProcessExtensions = filterByRunningLocation(allExtensions, this._runningLocation, desiredRunningLocation); + const localProcessExtensions = this._filterByRunningLocation(allExtensions, desiredRunningLocation); return { autoStart: true, extensions: localProcessExtensions @@ -234,27 +234,25 @@ export class ExtensionService extends AbstractExtensionService implements IExten return (result.length > 0 ? result[0] : null); } - protected _createExtensionHosts(isInitialStart: boolean): IExtensionHost[] { - const result: IExtensionHost[] = []; - - const localProcessRunningLocation = new LocalProcessRunningLocation(0); - const localProcessExtHost = this._instantiationService.createInstance(LocalProcessExtensionHost, localProcessRunningLocation, this._createLocalExtensionHostDataProvider(isInitialStart, localProcessRunningLocation)); - result.push(localProcessExtHost); - - if (this._enableLocalWebWorker) { - const localWebWorkerRunningLocation = new LocalWebWorkerRunningLocation(); - const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, localWebWorkerRunningLocation, this._lazyLocalWebWorker, this._createLocalExtensionHostDataProvider(isInitialStart, localWebWorkerRunningLocation)); - result.push(webWorkerExtHost); + protected _createExtensionHost(runningLocation: ExtensionRunningLocation, isInitialStart: boolean): IExtensionHost | null { + switch (runningLocation.kind) { + case ExtensionHostKind.LocalProcess: { + return this._instantiationService.createInstance(LocalProcessExtensionHost, runningLocation, this._createLocalExtensionHostDataProvider(isInitialStart, runningLocation)); + } + case ExtensionHostKind.LocalWebWorker: { + if (this._enableLocalWebWorker) { + return this._instantiationService.createInstance(WebWorkerExtensionHost, runningLocation, this._lazyLocalWebWorker, this._createLocalExtensionHostDataProvider(isInitialStart, runningLocation)); + } + return null; + } + case ExtensionHostKind.Remote: { + const remoteAgentConnection = this._remoteAgentService.getConnection(); + if (remoteAgentConnection) { + return this._instantiationService.createInstance(RemoteExtensionHost, runningLocation, this._createRemoteExtensionHostDataProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory); + } + return null; + } } - - const remoteAgentConnection = this._remoteAgentService.getConnection(); - if (remoteAgentConnection) { - const remoteRunningLocation = new RemoteRunningLocation(); - const remoteExtHost = this._instantiationService.createInstance(RemoteExtensionHost, remoteRunningLocation, this._createRemoteExtensionHostDataProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory); - result.push(remoteExtHost); - } - - return result; } protected override _onExtensionHostCrashed(extensionHost: IExtensionHostManager, code: number, signal: string | null): void { @@ -545,12 +543,12 @@ export class ExtensionService extends AbstractExtensionService implements IExten remoteExtensions = this._checkEnabledAndProposedAPI(remoteExtensions, false); const localExtensions = this._checkEnabledAndProposedAPI(await this._scanAllLocalExtensions(), false); - this._runningLocation = this._computeRunningLocation(localExtensions, remoteExtensions, true); + this._initializeRunningLocation(localExtensions, remoteExtensions); // remove non-UI extensions from the local extensions - const localProcessExtensions = filterByExtensionHostKind(localExtensions, this._runningLocation, ExtensionHostKind.LocalProcess); - const localWebWorkerExtensions = filterByExtensionHostKind(localExtensions, this._runningLocation, ExtensionHostKind.LocalWebWorker); - remoteExtensions = filterByExtensionHostKind(remoteExtensions, this._runningLocation, ExtensionHostKind.Remote); + const localProcessExtensions = this._filterByExtensionHostKind(localExtensions, ExtensionHostKind.LocalProcess); + const localWebWorkerExtensions = this._filterByExtensionHostKind(localExtensions, ExtensionHostKind.LocalWebWorker); + remoteExtensions = this._filterByExtensionHostKind(remoteExtensions, ExtensionHostKind.Remote); const result = this._registry.deltaExtensions(remoteExtensions.concat(localProcessExtensions).concat(localWebWorkerExtensions), []); if (result.removedDueToLooping.length > 0) { @@ -586,7 +584,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten } private _startExtensionHost(extensionHostManager: IExtensionHostManager, _extensions: IExtensionDescription[]): void { - const extensions = filterByExtensionHostManager(_extensions, this._runningLocation, extensionHostManager); + const extensions = this._filterByExtensionHostManager(_extensions, extensionHostManager); extensionHostManager.start(extensions.map(extension => extension.identifier)); } From 0006ca4db2713ec9adbd4cae35f77485d7900d36 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Mar 2022 16:46:15 +0100 Subject: [PATCH 134/175] move TargetPlatform to extensions (resolve cycle) --- .../abstractExtensionManagementService.ts | 4 ++-- .../common/extensionGalleryService.ts | 4 ++-- .../common/extensionManagement.ts | 24 +------------------ .../common/extensionManagementIpc.ts | 4 ++-- .../common/extensionManagementUtil.ts | 6 ++--- .../node/extensionManagementService.ts | 4 ++-- .../node/extensionsScanner.ts | 4 ++-- .../common/extensionGalleryService.test.ts | 2 +- .../test/common/extensionManagement.test.ts | 3 ++- .../platform/extensions/common/extensions.ts | 23 +++++++++++++++++- .../browser/extensionsWorkbenchService.ts | 4 ++-- .../test/electron-browser/extension.test.ts | 4 ++-- .../browser/webExtensionsScannerService.ts | 4 ++-- .../common/extensionManagementService.ts | 4 ++-- .../common/webExtensionManagementService.ts | 4 ++-- 15 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts index ab363c1457d..22cb64686fa 100644 --- a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts +++ b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts @@ -15,10 +15,10 @@ import { URI } from 'vs/base/common/uri'; import * as nls from 'vs/nls'; import { DidUninstallExtensionEvent, ExtensionManagementError, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementParticipant, IExtensionManagementService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallExtensionEvent, InstallExtensionResult, InstallOperation, InstallOptions, - InstallVSIXOptions, IExtensionsControlManifest, StatisticType, UninstallOptions, TargetPlatform, isTargetPlatformCompatible, TargetPlatformToString, ExtensionManagementErrorCode + InstallVSIXOptions, IExtensionsControlManifest, StatisticType, UninstallOptions, isTargetPlatformCompatible, TargetPlatformToString, ExtensionManagementErrorCode } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions, ExtensionKey, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; -import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; +import { ExtensionType, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { ILogService } from 'vs/platform/log/common/log'; import { IProductService } from 'vs/platform/product/common/productService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts index 9c01f7a1d90..f372afd9f3b 100644 --- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts @@ -16,9 +16,9 @@ import { URI } from 'vs/base/common/uri'; import { IRequestContext, IRequestOptions } from 'vs/base/parts/request/common/request'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { getFallbackTargetPlarforms, getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionInfo, IGalleryExtension, IGalleryExtensionAsset, IGalleryExtensionAssets, IGalleryExtensionVersion, InstallOperation, IQueryOptions, IExtensionsControlManifest, isNotWebExtensionInWebTargetPlatform, isTargetPlatformCompatible, ITranslation, SortBy, SortOrder, StatisticType, TargetPlatform, toTargetPlatform, WEB_EXTENSION_TAG, IExtensionQueryOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { getFallbackTargetPlarforms, getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionInfo, IGalleryExtension, IGalleryExtensionAsset, IGalleryExtensionAssets, IGalleryExtensionVersion, InstallOperation, IQueryOptions, IExtensionsControlManifest, isNotWebExtensionInWebTargetPlatform, isTargetPlatformCompatible, ITranslation, SortBy, SortOrder, StatisticType, toTargetPlatform, WEB_EXTENSION_TAG, IExtensionQueryOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; import { adoptToGalleryExtensionId, areSameExtensions, getGalleryExtensionId, getGalleryExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; -import { IExtensionManifest } from 'vs/platform/extensions/common/extensions'; +import { IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator'; import { IFileService } from 'vs/platform/files/common/files'; import { ILogService } from 'vs/platform/log/common/log'; diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index 49906652ff2..065219a2885 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -11,7 +11,7 @@ import { Platform } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; import { adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; -import { ExtensionType, IExtension, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; +import { ExtensionType, IExtension, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const EXTENSION_IDENTIFIER_PATTERN = '^([a-z0-9A-Z][a-z0-9-A-Z]*)\\.([a-z0-9A-Z][a-z0-9-A-Z]*)$'; @@ -27,28 +27,6 @@ export function getIdAndVersion(id: string): [string, string | undefined] { return [adoptToGalleryExtensionId(id), undefined]; } -export const enum TargetPlatform { - WIN32_X64 = 'win32-x64', - WIN32_IA32 = 'win32-ia32', - WIN32_ARM64 = 'win32-arm64', - - LINUX_X64 = 'linux-x64', - LINUX_ARM64 = 'linux-arm64', - LINUX_ARMHF = 'linux-armhf', - - ALPINE_X64 = 'alpine-x64', - ALPINE_ARM64 = 'alpine-arm64', - - DARWIN_X64 = 'darwin-x64', - DARWIN_ARM64 = 'darwin-arm64', - - WEB = 'web', - - UNIVERSAL = 'universal', - UNKNOWN = 'unknown', - UNDEFINED = 'undefined', -} - export function TargetPlatformToString(targetPlatform: TargetPlatform) { switch (targetPlatform) { case TargetPlatform.WIN32_X64: return 'Windows 64 bit'; diff --git a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts index 3141cf69855..c4ed5030344 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts @@ -9,8 +9,8 @@ import { cloneAndChange } from 'vs/base/common/objects'; import { URI, UriComponents } from 'vs/base/common/uri'; import { DefaultURITransformer, IURITransformer, transformAndReviveIncomingURIs } from 'vs/base/common/uriIpc'; import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; -import { DidUninstallExtensionEvent, IExtensionIdentifier, IExtensionManagementService, IExtensionTipsService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallExtensionEvent, InstallExtensionResult, InstallOptions, InstallVSIXOptions, IExtensionsControlManifest, isTargetPlatformCompatible, TargetPlatform, UninstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; +import { DidUninstallExtensionEvent, IExtensionIdentifier, IExtensionManagementService, IExtensionTipsService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallExtensionEvent, InstallExtensionResult, InstallOptions, InstallVSIXOptions, IExtensionsControlManifest, isTargetPlatformCompatible, UninstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionType, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions'; function transformIncomingURI(uri: UriComponents, transformer: IURITransformer | null): URI { return URI.revive(transformer ? transformer.transformIncoming(uri) : uri); diff --git a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts index aec656f287b..303319fa2d4 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { compareIgnoreCase } from 'vs/base/common/strings'; -import { IExtensionIdentifier, IGalleryExtension, ILocalExtension, IExtensionsControlManifest, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { ExtensionIdentifier, IExtension } from 'vs/platform/extensions/common/extensions'; +import { IExtensionIdentifier, IGalleryExtension, ILocalExtension, IExtensionsControlManifest } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionIdentifier, IExtension, TargetPlatform } from 'vs/platform/extensions/common/extensions'; export function areSameExtensions(a: IExtensionIdentifier, b: IExtensionIdentifier): boolean { if (a.uuid && b.uuid) { @@ -23,7 +23,7 @@ export class ExtensionKey { static create(extension: ILocalExtension | IGalleryExtension): ExtensionKey { const version = (extension as ILocalExtension).manifest ? (extension as ILocalExtension).manifest.version : (extension as IGalleryExtension).version; - const targetPlatform = (extension as ILocalExtension).targetPlatform ? (extension as ILocalExtension).targetPlatform : (extension as IGalleryExtension).properties.targetPlatform; + const targetPlatform = (extension as ILocalExtension).manifest ? (extension as ILocalExtension).targetPlatform : (extension as IGalleryExtension).properties.targetPlatform; return new ExtensionKey(extension.identifier, version, targetPlatform); } diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index d946e6a4941..daa4309b2c7 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -23,7 +23,7 @@ import { INativeEnvironmentService } from 'vs/platform/environment/common/enviro import { AbstractExtensionManagementService, AbstractExtensionTask, IInstallExtensionTask, IUninstallExtensionTask, joinErrors, UninstallExtensionTaskOptions } from 'vs/platform/extensionManagement/common/abstractExtensionManagementService'; import { ExtensionManagementError, ExtensionManagementErrorCode, getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallOperation, InstallOptions, - InstallVSIXOptions, Metadata, TargetPlatform + InstallVSIXOptions, Metadata } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions, ExtensionKey, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionsDownloader } from 'vs/platform/extensionManagement/node/extensionDownloader'; @@ -32,7 +32,7 @@ import { getManifest } from 'vs/platform/extensionManagement/node/extensionManag import { ExtensionsManifestCache } from 'vs/platform/extensionManagement/node/extensionsManifestCache'; import { ExtensionsScanner, ILocalExtensionManifest } from 'vs/platform/extensionManagement/node/extensionsScanner'; import { ExtensionsWatcher } from 'vs/platform/extensionManagement/node/extensionsWatcher'; -import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; +import { ExtensionType, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator'; import { IFileService } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/platform/extensionManagement/node/extensionsScanner.ts b/src/vs/platform/extensionManagement/node/extensionsScanner.ts index 99a6e495a50..5ca4c56bcfd 100644 --- a/src/vs/platform/extensionManagement/node/extensionsScanner.ts +++ b/src/vs/platform/extensionManagement/node/extensionsScanner.ts @@ -20,10 +20,10 @@ import * as pfs from 'vs/base/node/pfs'; import { extract, ExtractError } from 'vs/base/node/zip'; import { localize } from 'vs/nls'; import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; -import { ExtensionManagementError, ExtensionManagementErrorCode, Metadata, ILocalExtension, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionManagementError, ExtensionManagementErrorCode, Metadata, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions, ExtensionKey, getGalleryExtensionId, groupByExtension } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls'; -import { ExtensionType, IExtensionIdentifier, IExtensionManifest, UNDEFINED_PUBLISHER } from 'vs/platform/extensions/common/extensions'; +import { ExtensionType, IExtensionIdentifier, IExtensionManifest, TargetPlatform, UNDEFINED_PUBLISHER } from 'vs/platform/extensions/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { ILogService } from 'vs/platform/log/common/log'; import { IProductService } from 'vs/platform/product/common/productService'; diff --git a/src/vs/platform/extensionManagement/test/common/extensionGalleryService.test.ts b/src/vs/platform/extensionManagement/test/common/extensionGalleryService.test.ts index 11533d2f326..4312de805f8 100644 --- a/src/vs/platform/extensionManagement/test/common/extensionGalleryService.test.ts +++ b/src/vs/platform/extensionManagement/test/common/extensionGalleryService.test.ts @@ -13,7 +13,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IRawGalleryExtensionVersion, sortExtensionVersions } from 'vs/platform/extensionManagement/common/extensionGalleryService'; -import { TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IFileService } from 'vs/platform/files/common/files'; import { FileService } from 'vs/platform/files/common/fileService'; import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider'; @@ -23,6 +22,7 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { resolveMarketplaceHeaders } from 'vs/platform/externalServices/common/marketplace'; import { InMemoryStorageService, IStorageService } from 'vs/platform/storage/common/storage'; import { TelemetryConfiguration, TELEMETRY_SETTING_ID } from 'vs/platform/telemetry/common/telemetry'; +import { TargetPlatform } from 'vs/platform/extensions/common/extensions'; class EnvironmentServiceMock extends mock() { override readonly serviceMachineIdResource: URI; diff --git a/src/vs/platform/extensionManagement/test/common/extensionManagement.test.ts b/src/vs/platform/extensionManagement/test/common/extensionManagement.test.ts index adb910b63d3..9f29115a827 100644 --- a/src/vs/platform/extensionManagement/test/common/extensionManagement.test.ts +++ b/src/vs/platform/extensionManagement/test/common/extensionManagement.test.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EXTENSION_IDENTIFIER_PATTERN, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { EXTENSION_IDENTIFIER_PATTERN } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionKey } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { TargetPlatform } from 'vs/platform/extensions/common/extensions'; suite('Extension Identifier Pattern', () => { diff --git a/src/vs/platform/extensions/common/extensions.ts b/src/vs/platform/extensions/common/extensions.ts index cfa20e0799d..82086430a00 100644 --- a/src/vs/platform/extensions/common/extensions.ts +++ b/src/vs/platform/extensions/common/extensions.ts @@ -6,7 +6,6 @@ import * as strings from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { ExtensionKind } from 'vs/platform/environment/common/environment'; -import { TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { getRemoteName } from 'vs/platform/remote/common/remoteHosts'; @@ -288,6 +287,28 @@ export const enum ExtensionType { User } +export const enum TargetPlatform { + WIN32_X64 = 'win32-x64', + WIN32_IA32 = 'win32-ia32', + WIN32_ARM64 = 'win32-arm64', + + LINUX_X64 = 'linux-x64', + LINUX_ARM64 = 'linux-arm64', + LINUX_ARMHF = 'linux-armhf', + + ALPINE_X64 = 'alpine-x64', + ALPINE_ARM64 = 'alpine-arm64', + + DARWIN_X64 = 'darwin-x64', + DARWIN_ARM64 = 'darwin-arm64', + + WEB = 'web', + + UNIVERSAL = 'universal', + UNKNOWN = 'unknown', + UNDEFINED = 'undefined', +} + export interface IExtension { readonly type: ExtensionType; readonly isBuiltin: boolean; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index ec4a1287475..a6e9045425c 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -15,7 +15,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IExtensionGalleryService, ILocalExtension, IGalleryExtension, IQueryOptions, InstallExtensionEvent, DidUninstallExtensionEvent, IExtensionIdentifier, InstallOperation, InstallOptions, WEB_EXTENSION_TAG, InstallExtensionResult, - IExtensionsControlManifest, InstallVSIXOptions, IExtensionInfo, IExtensionQueryOptions, TargetPlatform + IExtensionsControlManifest, InstallVSIXOptions, IExtensionInfo, IExtensionQueryOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService, DefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, groupByExtension, ExtensionKey, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; @@ -34,7 +34,7 @@ import * as resources from 'vs/base/common/resources'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IFileService } from 'vs/platform/files/common/files'; -import { IExtensionManifest, ExtensionType, IExtension as IPlatformExtension } from 'vs/platform/extensions/common/extensions'; +import { IExtensionManifest, ExtensionType, IExtension as IPlatformExtension, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { ILanguageService } from 'vs/editor/common/languages/language'; import { IProductService } from 'vs/platform/product/common/productService'; import { FileAccess } from 'vs/base/common/network'; diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts index 3026178faca..cb37de9dadd 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts @@ -6,8 +6,8 @@ import * as assert from 'assert'; import { ExtensionState } from 'vs/workbench/contrib/extensions/common/extensions'; import { Extension } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService'; -import { IGalleryExtension, IGalleryExtensionProperties, ILocalExtension, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; +import { IGalleryExtension, IGalleryExtensionProperties, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionType, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { URI } from 'vs/base/common/uri'; import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { generateUuid } from 'vs/base/common/uuid'; diff --git a/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts b/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts index ebd50ecda8b..e45603178db 100644 --- a/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts +++ b/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IBuiltinExtensionsScannerService, ExtensionType, IExtensionIdentifier, IExtension, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; +import { IBuiltinExtensionsScannerService, ExtensionType, IExtensionIdentifier, IExtension, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; import { IScannedExtension, IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { isWeb } from 'vs/base/common/platform'; @@ -15,7 +15,7 @@ import { Queue } from 'vs/base/common/async'; import { VSBuffer } from 'vs/base/common/buffer'; import { ILogService } from 'vs/platform/log/common/log'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { IExtensionGalleryService, IGalleryExtension, IGalleryMetadata, Metadata, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionGalleryService, IGalleryExtension, IGalleryMetadata, Metadata } from 'vs/platform/extensionManagement/common/extensionManagement'; import { groupByExtension, areSameExtensions, getGalleryExtensionId, getExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { Disposable } from 'vs/base/common/lifecycle'; import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls'; diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts index 538950c4c25..1f0e39e2d2e 100644 --- a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts @@ -5,10 +5,10 @@ import { Event, EventMultiplexer } from 'vs/base/common/event'; import { - ILocalExtension, IGalleryExtension, IExtensionIdentifier, IExtensionsControlManifest, IGalleryMetadata, IExtensionGalleryService, InstallOptions, UninstallOptions, InstallVSIXOptions, InstallExtensionResult, TargetPlatform, ExtensionManagementError, ExtensionManagementErrorCode + ILocalExtension, IGalleryExtension, IExtensionIdentifier, IExtensionsControlManifest, IGalleryMetadata, IExtensionGalleryService, InstallOptions, UninstallOptions, InstallVSIXOptions, InstallExtensionResult, ExtensionManagementError, ExtensionManagementErrorCode } from 'vs/platform/extensionManagement/common/extensionManagement'; import { DidUninstallExtensionOnServerEvent, IExtensionManagementServer, IExtensionManagementServerService, InstallExtensionOnServerEvent, IWorkbenchExtensionManagementService, UninstallExtensionOnServerEvent } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; -import { ExtensionType, isLanguagePackExtension, IExtensionManifest, getWorkspaceSupportTypeMessage } from 'vs/platform/extensions/common/extensions'; +import { ExtensionType, isLanguagePackExtension, IExtensionManifest, getWorkspaceSupportTypeMessage, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { URI } from 'vs/base/common/uri'; import { Disposable } from 'vs/base/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; diff --git a/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts index e9acbbe1ace..2d997c69fed 100644 --- a/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ExtensionType, IExtensionIdentifier, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; -import { IExtensionManagementService, ILocalExtension, IGalleryExtension, IGalleryMetadata, InstallOperation, IExtensionGalleryService, InstallOptions, Metadata, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ExtensionType, IExtensionIdentifier, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions'; +import { IExtensionManagementService, ILocalExtension, IGalleryExtension, IGalleryMetadata, InstallOperation, IExtensionGalleryService, InstallOptions, Metadata } from 'vs/platform/extensionManagement/common/extensionManagement'; import { URI } from 'vs/base/common/uri'; import { areSameExtensions, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IScannedExtension, IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; From 4cc9f9eee2e7c77ac06f2d8e6c926a4e0523f398 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Mar 2022 16:57:13 +0100 Subject: [PATCH 135/175] fix reload required action --- .../extensionManagement/common/extensionManagement.ts | 1 - .../extensionManagement/node/extensionsScanner.ts | 2 +- src/vs/platform/extensions/common/extensions.ts | 3 ++- .../api/test/common/extHostExtensionActivator.test.ts | 3 ++- .../workbench/contrib/debug/test/node/debugger.test.ts | 5 ++++- .../browser/builtinExtensionsScannerService.ts | 3 ++- .../browser/webExtensionsScannerService.ts | 3 ++- .../services/extensions/common/extensionPoints.ts | 9 ++++----- .../workbench/services/extensions/common/extensions.ts | 4 +++- 9 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index 065219a2885..70d25a5485e 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -256,7 +256,6 @@ export interface ILocalExtension extends IExtension { installedTimestamp?: number; isPreReleaseVersion: boolean; preRelease: boolean; - targetPlatform: TargetPlatform; } export const enum SortBy { diff --git a/src/vs/platform/extensionManagement/node/extensionsScanner.ts b/src/vs/platform/extensionManagement/node/extensionsScanner.ts index 5ca4c56bcfd..03d75a5e8ff 100644 --- a/src/vs/platform/extensionManagement/node/extensionsScanner.ts +++ b/src/vs/platform/extensionManagement/node/extensionsScanner.ts @@ -30,7 +30,7 @@ import { IProductService } from 'vs/platform/product/common/productService'; export type ILocalExtensionManifest = IExtensionManifest & { __metadata?: Metadata }; -type IRelaxedLocalExtension = Omit & { isBuiltin: boolean }; +type IRelaxedLocalExtension = Omit & { isBuiltin: boolean; targetPlatform: TargetPlatform }; export class ExtensionsScanner extends Disposable { diff --git a/src/vs/platform/extensions/common/extensions.ts b/src/vs/platform/extensions/common/extensions.ts index 82086430a00..a1eae1bb07d 100644 --- a/src/vs/platform/extensions/common/extensions.ts +++ b/src/vs/platform/extensions/common/extensions.ts @@ -315,6 +315,7 @@ export interface IExtension { readonly identifier: IExtensionIdentifier; readonly manifest: IExtensionManifest; readonly location: URI; + readonly targetPlatform: TargetPlatform; readonly readmeUrl?: URI; readonly changelogUrl?: URI; } @@ -377,7 +378,7 @@ export class ExtensionIdentifier { export interface IExtensionDescription extends IExtensionManifest { readonly identifier: ExtensionIdentifier; readonly uuid?: string; - readonly targetPlatform?: TargetPlatform; + readonly targetPlatform: TargetPlatform; readonly isBuiltin: boolean; readonly isUserBuiltin: boolean; readonly isUnderDevelopment: boolean; diff --git a/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts b/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts index 18850a98dd2..ddaaa76bb35 100644 --- a/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts +++ b/src/vs/workbench/api/test/common/extHostExtensionActivator.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { timeout } from 'vs/base/common/async'; import { URI } from 'vs/base/common/uri'; -import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { ExtensionIdentifier, IExtensionDescription, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { NullLogService } from 'vs/platform/log/common/log'; import { ActivatedExtension, EmptyExtension, ExtensionActivationTimes, ExtensionsActivator, IExtensionsActivatorHost } from 'vs/workbench/api/common/extHostExtensionActivator'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; @@ -261,6 +261,7 @@ suite('ExtensionsActivator', () => { isUserBuiltin: false, activationEvents, main: 'index.js', + targetPlatform: TargetPlatform.UNDEFINED, extensionDependencies: deps.map(d => d.value) }; } diff --git a/src/vs/workbench/contrib/debug/test/node/debugger.test.ts b/src/vs/workbench/contrib/debug/test/node/debugger.test.ts index 8f1278c1cd6..72ff6b21db2 100644 --- a/src/vs/workbench/contrib/debug/test/node/debugger.test.ts +++ b/src/vs/workbench/contrib/debug/test/node/debugger.test.ts @@ -12,7 +12,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/ import { URI } from 'vs/base/common/uri'; import { ExecutableDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter'; import { TestTextResourcePropertiesService } from 'vs/editor/test/common/services/testTextResourcePropertiesService'; -import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { ExtensionIdentifier, IExtensionDescription, TargetPlatform } from 'vs/platform/extensions/common/extensions'; suite('Debug - Debugger', () => { @@ -58,6 +58,7 @@ suite('Debug - Debugger', () => { isUserBuiltin: false, isUnderDevelopment: false, engines: null!, + targetPlatform: TargetPlatform.UNDEFINED, contributes: { 'debuggers': [ debuggerContribution @@ -76,6 +77,7 @@ suite('Debug - Debugger', () => { isUserBuiltin: false, isUnderDevelopment: false, engines: null!, + targetPlatform: TargetPlatform.UNDEFINED, contributes: { 'debuggers': [ { @@ -100,6 +102,7 @@ suite('Debug - Debugger', () => { isUserBuiltin: false, isUnderDevelopment: false, engines: null!, + targetPlatform: TargetPlatform.UNDEFINED, contributes: { 'debuggers': [ { diff --git a/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts b/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts index 5eb9d09bf2e..c22e2718d6a 100644 --- a/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts +++ b/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IBuiltinExtensionsScannerService, ExtensionType, IExtensionManifest, IExtension } from 'vs/platform/extensions/common/extensions'; +import { IBuiltinExtensionsScannerService, ExtensionType, IExtensionManifest, IExtension, TargetPlatform } from 'vs/platform/extensions/common/extensions'; import { isWeb } from 'vs/base/common/platform'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; @@ -57,6 +57,7 @@ export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScanne manifest: e.packageNLS ? localizeManifest(e.packageJSON, e.packageNLS) : e.packageJSON, readmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.readmePath) : undefined, changelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.changelogPath) : undefined, + targetPlatform: TargetPlatform.WEB, })); } } diff --git a/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts b/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts index e45603178db..6fd477d3f44 100644 --- a/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts +++ b/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts @@ -465,7 +465,8 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten isBuiltin, readmeUrl: webExtension.readmeUri, changelogUrl: webExtension.changelogUri, - metadata: webExtension.metadata + metadata: webExtension.metadata, + targetPlatform: TargetPlatform.WEB }; } diff --git a/src/vs/workbench/services/extensions/common/extensionPoints.ts b/src/vs/workbench/services/extensions/common/extensionPoints.ts index 95ebdd0691f..eaca238a299 100644 --- a/src/vs/workbench/services/extensions/common/extensionPoints.ts +++ b/src/vs/workbench/services/extensions/common/extensionPoints.ts @@ -14,7 +14,7 @@ import * as types from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { getGalleryExtensionId, groupByExtension, getExtensionId, ExtensionKey } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { isValidExtensionVersion } from 'vs/platform/extensions/common/extensionValidator'; -import { ExtensionIdentifier, IExtensionDescription, UNDEFINED_PUBLISHER } from 'vs/platform/extensions/common/extensions'; +import { ExtensionIdentifier, IExtensionDescription, TargetPlatform, UNDEFINED_PUBLISHER } from 'vs/platform/extensions/common/extensions'; const MANIFEST_FILE = 'package.json'; @@ -133,10 +133,8 @@ class ExtensionManifestParser extends ExtensionManifestHandler { if (json.getNodeType(manifest) !== 'object') { this._error(this._absoluteFolderPath, nls.localize('jsonParseInvalidType', "Invalid manifest file {0}: Not an JSON object.", this._absoluteManifestPath)); } else if (errors.length === 0) { - if (manifest.__metadata) { - manifest.uuid = manifest.__metadata.id; - manifest.targetPlatform = manifest.__metadata.targetPlatform; - } + manifest.uuid = manifest.__metadata?.id; + manifest.targetPlatform = manifest.__metadata?.targetPlatform ?? TargetPlatform.UNDEFINED; manifest.isUserBuiltin = !!manifest.__metadata?.isBuiltin; delete manifest.__metadata; return manifest; @@ -366,6 +364,7 @@ class ExtensionManifestNLSReplacer extends ExtensionManifestHandler { export interface IRelaxedExtensionDescription { id: string; uuid?: string; + targetPlatform: TargetPlatform; identifier: ExtensionIdentifier; name: string; version: string; diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 6398b447a1a..20be37510fc 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -340,6 +340,7 @@ export function toExtension(extensionDescription: IExtensionDescription): IExten identifier: { id: getGalleryExtensionId(extensionDescription.publisher, extensionDescription.name), uuid: extensionDescription.uuid }, manifest: extensionDescription, location: extensionDescription.extensionLocation, + targetPlatform: extensionDescription.targetPlatform, }; } @@ -351,7 +352,8 @@ export function toExtensionDescription(extension: IExtension, isUnderDevelopment isUnderDevelopment: !!isUnderDevelopment, extensionLocation: extension.location, ...extension.manifest, - uuid: extension.identifier.uuid + uuid: extension.identifier.uuid, + targetPlatform: extension.targetPlatform }; } From 7b42b0502986fcdacc6cf84765eedbdaa432cf35 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Mar 2022 16:58:18 +0100 Subject: [PATCH 136/175] Fix #142087 --- .../views/common/viewContainerModel.ts | 27 ++++++++++++++----- .../test/browser/viewContainerModel.test.ts | 24 +++++++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index 21fbe13df29..95f94f9965f 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -15,7 +15,7 @@ import { move } from 'vs/base/common/arrays'; import { isUndefined, isUndefinedOrNull } from 'vs/base/common/types'; import { isEqual } from 'vs/base/common/resources'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { groupBy } from 'vs/base/common/collections'; +import { groupBy, IStringDictionary } from 'vs/base/common/collections'; export function getViewsStateStorageId(viewContainerStorageId: string): string { return `${viewContainerStorageId}.hidden`; } @@ -109,9 +109,9 @@ class ViewDescriptorsState extends Disposable { } private updateWorkspaceState(viewDescriptors: ReadonlyArray): void { - const storedViewsStates: { [id: string]: IStoredWorkspaceViewState } = JSON.parse(this.storageService.get(this.workspaceViewsStateStorageId, StorageScope.WORKSPACE, '{}')); + const storedViewsStates = this.getStoredWorkspaceState(); for (const viewDescriptor of viewDescriptors) { - const viewState = this.state.get(viewDescriptor.id); + const viewState = this.get(viewDescriptor.id); if (viewState) { storedViewsStates[viewDescriptor.id] = { collapsed: !!viewState.collapsed, @@ -132,7 +132,7 @@ class ViewDescriptorsState extends Disposable { private updateGlobalState(viewDescriptors: ReadonlyArray): void { const storedGlobalState = this.getStoredGlobalState(); for (const viewDescriptor of viewDescriptors) { - const state = this.state.get(viewDescriptor.id); + const state = this.get(viewDescriptor.id); storedGlobalState.set(viewDescriptor.id, { id: viewDescriptor.id, isHidden: state && viewDescriptor.canToggleVisibility ? !state.visibleGlobal : false, @@ -147,13 +147,24 @@ class ViewDescriptorsState extends Disposable { && this.globalViewsStatesValue !== this.getStoredGlobalViewsStatesValue() /* This checks if current window changed the value or not */) { this._globalViewsStatesValue = undefined; const storedViewsVisibilityStates = this.getStoredGlobalState(); + const storedWorkspaceViewsStates = this.getStoredWorkspaceState(); const changedStates: { id: string; visible: boolean }[] = []; for (const [id, storedState] of storedViewsVisibilityStates) { - const state = this.state.get(id); + const state = this.get(id); if (state) { if (state.visibleGlobal !== !storedState.isHidden) { changedStates.push({ id, visible: !storedState.isHidden }); } + } else { + const workspaceViewState = storedWorkspaceViewsStates[id]; + this.set(id, { + active: false, + visibleGlobal: !storedState.isHidden, + visibleWorkspace: isUndefined(workspaceViewState?.isHidden) ? undefined : !workspaceViewState?.isHidden, + collapsed: workspaceViewState?.collapsed, + order: workspaceViewState?.order, + size: workspaceViewState?.size, + }); } } if (changedStates.length) { @@ -164,7 +175,7 @@ class ViewDescriptorsState extends Disposable { private initialize(): Map { const viewStates = new Map(); - const workspaceViewsStates = <{ [id: string]: IStoredWorkspaceViewState }>JSON.parse(this.storageService.get(this.workspaceViewsStateStorageId, StorageScope.WORKSPACE, '{}')); + const workspaceViewsStates = this.getStoredWorkspaceState(); for (const id of Object.keys(workspaceViewsStates)) { const workspaceViewState = workspaceViewsStates[id]; viewStates.set(id, { @@ -224,6 +235,10 @@ class ViewDescriptorsState extends Disposable { return viewStates; } + private getStoredWorkspaceState(): IStringDictionary { + return JSON.parse(this.storageService.get(this.workspaceViewsStateStorageId, StorageScope.WORKSPACE, '{}')); + } + private getStoredGlobalState(): Map { return this.parseStoredGlobalState(this.globalViewsStatesValue).state; } diff --git a/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts b/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts index ef47ed5bbb8..7a80ca793e5 100644 --- a/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts +++ b/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts @@ -17,6 +17,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { Event } from 'vs/base/common/event'; +import { getViewsStateStorageId } from 'vs/workbench/services/views/common/viewContainerModel'; const ViewContainerRegistry = Registry.as(ViewContainerExtensions.ViewContainersRegistry); const ViewsRegistry = Registry.as(ViewContainerExtensions.ViewsRegistry); @@ -580,4 +581,27 @@ suite('ViewContainerModel', () => { assert.strictEqual(target.elements.length, 0); }); + test('#142087: view descriptor visibility is not reset', async function () { + container = ViewContainerRegistry.registerViewContainer({ id: 'test', title: 'test', ctorDescriptor: new SyncDescriptor({}) }, ViewContainerLocation.Sidebar); + const testObject = viewDescriptorService.getViewContainerModel(container); + const viewDescriptor: IViewDescriptor = { + id: 'view1', + ctorDescriptor: null!, + name: 'Test View 1', + canToggleVisibility: true + }; + + storageService.store(getViewsStateStorageId('test.state'), JSON.stringify([{ + id: viewDescriptor.id, + isHidden: true, + order: undefined + }]), StorageScope.GLOBAL, StorageTarget.USER); + + ViewsRegistry.registerViews([viewDescriptor], container); + + assert.strictEqual(testObject.isVisible(viewDescriptor.id), false); + assert.strictEqual(testObject.activeViewDescriptors[0].id, viewDescriptor.id); + assert.strictEqual(testObject.visibleViewDescriptors.length, 0); + }); + }); From cf4fe193cf67bb6805433a839866e81825ecaf31 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Mar 2022 18:49:58 +0100 Subject: [PATCH 137/175] Fix #143625 --- src/vs/workbench/common/views.ts | 2 +- .../views/common/viewContainerModel.ts | 102 ++++----- .../test/browser/viewContainerModel.test.ts | 203 ++++++++++++++++++ 3 files changed, 255 insertions(+), 52 deletions(-) diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index dd2a97af53d..f7f12808de1 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -346,7 +346,7 @@ export interface IViewContainerModel { readonly onDidMoveVisibleViewDescriptors: Event<{ from: IViewDescriptorRef; to: IViewDescriptorRef }>; isVisible(id: string): boolean; - setVisible(id: string, visible: boolean, size?: number): void; + setVisible(id: string, visible: boolean): void; isCollapsed(id: string): boolean; setCollapsed(id: string, collapsed: boolean): void; diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index 95f94f9965f..d497e159f85 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -11,11 +11,11 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; -import { move } from 'vs/base/common/arrays'; +import { coalesce, move } from 'vs/base/common/arrays'; import { isUndefined, isUndefinedOrNull } from 'vs/base/common/types'; import { isEqual } from 'vs/base/common/resources'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { groupBy, IStringDictionary } from 'vs/base/common/collections'; +import { IStringDictionary } from 'vs/base/common/collections'; export function getViewsStateStorageId(viewContainerStorageId: string): string { return `${viewContainerStorageId}.hidden`; } @@ -404,61 +404,61 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode return this.isViewDescriptorVisible(viewDescriptorItem); } - setVisible(id: string, visible: boolean, size?: number): void { - this.updateVisibility([{ id, visible, size }]); + setVisible(id: string, visible: boolean): void { + this.updateVisibility([{ id, visible }]); } - private updateVisibility(viewDescriptors: { id: string; visible: boolean; size?: number }[]): void { - const { toBeAdded, toBeRemoved } = groupBy(viewDescriptors, viewDescriptor => viewDescriptor.visible ? 'toBeAdded' : 'toBeRemoved'); - - const updateVisibility = (viewDescriptors: { id: string; visible: boolean; size?: number }[]): { viewDescriptorItem: IViewDescriptorItem; visibleIndex: number }[] => { - const result: { viewDescriptorItem: IViewDescriptorItem; visibleIndex: number }[] = []; - for (const { id, visible, size } of viewDescriptors) { - const foundViewDescriptor = this.findAndIgnoreIfNotFound(id); - if (!foundViewDescriptor) { - continue; - } - - const { viewDescriptorItem, visibleIndex } = foundViewDescriptor; - const viewDescriptor = viewDescriptorItem.viewDescriptor; - - if (!viewDescriptor.canToggleVisibility) { - continue; - } - - if (this.isViewDescriptorVisibleWhenActive(viewDescriptorItem) === visible) { - continue; - } - - if (viewDescriptor.workspace) { - viewDescriptorItem.state.visibleWorkspace = visible; - } else { - viewDescriptorItem.state.visibleGlobal = visible; - } - - if (typeof viewDescriptorItem.state.size === 'number') { - viewDescriptorItem.state.size = size; - } - - if (this.isViewDescriptorVisible(viewDescriptorItem) !== visible) { - // do not add events if visibility is not changed - continue; - } - - result.push({ viewDescriptorItem, visibleIndex }); + private updateVisibility(viewDescriptors: { id: string; visible: boolean }[]): void { + // First: Update and remove the view descriptors which are asked to be hidden + const viewDescriptorItemsToHide = coalesce(viewDescriptors.filter(({ visible }) => !visible) + .map(({ id }) => this.findAndIgnoreIfNotFound(id))); + const removed: IViewDescriptorRef[] = []; + for (const { viewDescriptorItem, visibleIndex } of viewDescriptorItemsToHide) { + if (this.updateViewDescriptorItemVisibility(viewDescriptorItem, false)) { + removed.push({ viewDescriptor: viewDescriptorItem.viewDescriptor, index: visibleIndex }); } - return result; - }; - - if (toBeRemoved?.length) { - const removedVisibleDescriptors = updateVisibility(toBeRemoved).map(({ viewDescriptorItem, visibleIndex }) => ({ viewDescriptor: viewDescriptorItem.viewDescriptor, index: visibleIndex })); - this.broadCastRemovedVisibleViewDescriptors(removedVisibleDescriptors); + } + if (removed.length) { + this.broadCastRemovedVisibleViewDescriptors(removed); } - if (toBeAdded?.length) { - const addedVisibleDescriptors = updateVisibility(toBeAdded).map(({ viewDescriptorItem, visibleIndex }) => ({ index: visibleIndex, viewDescriptor: viewDescriptorItem.viewDescriptor, size: viewDescriptorItem.state.size, collapsed: !!viewDescriptorItem.state.collapsed })); - this.broadCastAddedVisibleViewDescriptors(addedVisibleDescriptors); + // Second: Update and add the view descriptors which are asked to be shown + const added: IAddedViewDescriptorRef[] = []; + for (const { id, visible } of viewDescriptors) { + if (!visible) { + continue; + } + const foundViewDescriptor = this.findAndIgnoreIfNotFound(id); + if (!foundViewDescriptor) { + continue; + } + const { viewDescriptorItem, visibleIndex } = foundViewDescriptor; + if (this.updateViewDescriptorItemVisibility(viewDescriptorItem, true)) { + added.push({ index: visibleIndex, viewDescriptor: viewDescriptorItem.viewDescriptor, size: viewDescriptorItem.state.size, collapsed: !!viewDescriptorItem.state.collapsed }); + } } + if (added.length) { + this.broadCastAddedVisibleViewDescriptors(added); + } + } + + private updateViewDescriptorItemVisibility(viewDescriptorItem: IViewDescriptorItem, visible: boolean): boolean { + if (!viewDescriptorItem.viewDescriptor.canToggleVisibility) { + return false; + } + if (this.isViewDescriptorVisibleWhenActive(viewDescriptorItem) === visible) { + return false; + } + + // update visibility + if (viewDescriptorItem.viewDescriptor.workspace) { + viewDescriptorItem.state.visibleWorkspace = visible; + } else { + viewDescriptorItem.state.visibleGlobal = visible; + } + + // return `true` only if visibility is changed + return this.isViewDescriptorVisible(viewDescriptorItem) === visible; } isCollapsed(id: string): boolean { diff --git a/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts b/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts index 7a80ca793e5..a08f79dfa63 100644 --- a/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts +++ b/src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts @@ -604,4 +604,207 @@ suite('ViewContainerModel', () => { assert.strictEqual(testObject.visibleViewDescriptors.length, 0); }); + test('remove event is triggered properly if mutliple views are hidden at the same time', async function () { + container = ViewContainerRegistry.registerViewContainer({ id: 'test', title: 'test', ctorDescriptor: new SyncDescriptor({}) }, ViewContainerLocation.Sidebar); + const testObject = viewDescriptorService.getViewContainerModel(container); + const target = disposableStore.add(new ViewDescriptorSequence(testObject)); + const viewDescriptor1: IViewDescriptor = { + id: 'view1', + ctorDescriptor: null!, + name: 'Test View 1', + canToggleVisibility: true + }; + const viewDescriptor2: IViewDescriptor = { + id: 'view2', + ctorDescriptor: null!, + name: 'Test View 2', + canToggleVisibility: true + }; + const viewDescriptor3: IViewDescriptor = { + id: 'view3', + ctorDescriptor: null!, + name: 'Test View 3', + canToggleVisibility: true + }; + + ViewsRegistry.registerViews([viewDescriptor1, viewDescriptor2, viewDescriptor3], container); + + const remomveEvent = sinon.spy(); + testObject.onDidRemoveVisibleViewDescriptors(remomveEvent); + + const addEvent = sinon.spy(); + testObject.onDidAddVisibleViewDescriptors(addEvent); + + storageService.store(getViewsStateStorageId('test.state'), JSON.stringify([{ + id: viewDescriptor1.id, + isHidden: false, + order: undefined + }, { + id: viewDescriptor2.id, + isHidden: true, + order: undefined + }, { + id: viewDescriptor3.id, + isHidden: true, + order: undefined + }]), StorageScope.GLOBAL, StorageTarget.USER); + + assert.ok(!addEvent.called, 'add event should not be called'); + assert.ok(remomveEvent.calledOnce, 'remove event should be called'); + assert.deepStrictEqual(remomveEvent.args[0][0], [{ + viewDescriptor: viewDescriptor3, + index: 2 + }, { + viewDescriptor: viewDescriptor2, + index: 1 + }]); + assert.strictEqual(target.elements.length, 1); + assert.strictEqual(target.elements[0].id, viewDescriptor1.id); + }); + + test('add event is triggered properly if mutliple views are hidden at the same time', async function () { + container = ViewContainerRegistry.registerViewContainer({ id: 'test', title: 'test', ctorDescriptor: new SyncDescriptor({}) }, ViewContainerLocation.Sidebar); + const testObject = viewDescriptorService.getViewContainerModel(container); + const target = disposableStore.add(new ViewDescriptorSequence(testObject)); + const viewDescriptor1: IViewDescriptor = { + id: 'view1', + ctorDescriptor: null!, + name: 'Test View 1', + canToggleVisibility: true + }; + const viewDescriptor2: IViewDescriptor = { + id: 'view2', + ctorDescriptor: null!, + name: 'Test View 2', + canToggleVisibility: true + }; + const viewDescriptor3: IViewDescriptor = { + id: 'view3', + ctorDescriptor: null!, + name: 'Test View 3', + canToggleVisibility: true + }; + + ViewsRegistry.registerViews([viewDescriptor1, viewDescriptor2, viewDescriptor3], container); + testObject.setVisible(viewDescriptor1.id, false); + testObject.setVisible(viewDescriptor3.id, false); + + const removeEvent = sinon.spy(); + testObject.onDidRemoveVisibleViewDescriptors(removeEvent); + + const addEvent = sinon.spy(); + testObject.onDidAddVisibleViewDescriptors(addEvent); + + storageService.store(getViewsStateStorageId('test.state'), JSON.stringify([{ + id: viewDescriptor1.id, + isHidden: false, + order: undefined + }, { + id: viewDescriptor2.id, + isHidden: false, + order: undefined + }, { + id: viewDescriptor3.id, + isHidden: false, + order: undefined + }]), StorageScope.GLOBAL, StorageTarget.USER); + + assert.ok(!removeEvent.called, 'remove event should not be called'); + + assert.ok(addEvent.calledOnce, 'add event should be called once'); + assert.deepStrictEqual(addEvent.args[0][0], [{ + viewDescriptor: viewDescriptor1, + index: 0, + collapsed: false, + size: undefined + }, { + viewDescriptor: viewDescriptor3, + index: 2, + collapsed: false, + size: undefined + }]); + + assert.strictEqual(target.elements.length, 3); + assert.strictEqual(target.elements[0].id, viewDescriptor1.id); + assert.strictEqual(target.elements[1].id, viewDescriptor2.id); + assert.strictEqual(target.elements[2].id, viewDescriptor3.id); + }); + + test('add and remove events are triggered properly if mutliple views are hidden and added at the same time', async function () { + container = ViewContainerRegistry.registerViewContainer({ id: 'test', title: 'test', ctorDescriptor: new SyncDescriptor({}) }, ViewContainerLocation.Sidebar); + const testObject = viewDescriptorService.getViewContainerModel(container); + const target = disposableStore.add(new ViewDescriptorSequence(testObject)); + const viewDescriptor1: IViewDescriptor = { + id: 'view1', + ctorDescriptor: null!, + name: 'Test View 1', + canToggleVisibility: true + }; + const viewDescriptor2: IViewDescriptor = { + id: 'view2', + ctorDescriptor: null!, + name: 'Test View 2', + canToggleVisibility: true + }; + const viewDescriptor3: IViewDescriptor = { + id: 'view3', + ctorDescriptor: null!, + name: 'Test View 3', + canToggleVisibility: true + }; + const viewDescriptor4: IViewDescriptor = { + id: 'view4', + ctorDescriptor: null!, + name: 'Test View 4', + canToggleVisibility: true + }; + + ViewsRegistry.registerViews([viewDescriptor1, viewDescriptor2, viewDescriptor3, viewDescriptor4], container); + testObject.setVisible(viewDescriptor1.id, false); + + const removeEvent = sinon.spy(); + testObject.onDidRemoveVisibleViewDescriptors(removeEvent); + + const addEvent = sinon.spy(); + testObject.onDidAddVisibleViewDescriptors(addEvent); + + storageService.store(getViewsStateStorageId('test.state'), JSON.stringify([{ + id: viewDescriptor1.id, + isHidden: false, + order: undefined + }, { + id: viewDescriptor2.id, + isHidden: true, + order: undefined + }, { + id: viewDescriptor3.id, + isHidden: false, + order: undefined + }, { + id: viewDescriptor4.id, + isHidden: true, + order: undefined + }]), StorageScope.GLOBAL, StorageTarget.USER); + + assert.ok(removeEvent.calledOnce, 'remove event should be called once'); + assert.deepStrictEqual(removeEvent.args[0][0], [{ + viewDescriptor: viewDescriptor4, + index: 2 + }, { + viewDescriptor: viewDescriptor2, + index: 0 + }]); + + assert.ok(addEvent.calledOnce, 'add event should be called once'); + assert.deepStrictEqual(addEvent.args[0][0], [{ + viewDescriptor: viewDescriptor1, + index: 0, + collapsed: false, + size: undefined + }]); + assert.strictEqual(target.elements.length, 2); + assert.strictEqual(target.elements[0].id, viewDescriptor1.id); + assert.strictEqual(target.elements[1].id, viewDescriptor3.id); + }); + }); From 5a7b43ee2712efb347cf00c736e51f54fc408303 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 11 Mar 2022 21:54:12 +0100 Subject: [PATCH 138/175] Revert "Revert "show reload button when extension with different targetplatform is updated"" This reverts commit dfd530095900d98bdeeaa5cde514e00b75b8177e. --- .../workbench/contrib/extensions/browser/extensionsActions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index e4d00340619..d3cfdba7cda 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -1427,8 +1427,8 @@ export class ReloadAction extends ExtensionAction { const runningExtensionServer = this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension)); if (isSameExtensionRunning) { - // Different version of same extension is running. Requires reload to run the current version - if (this.extension.version !== runningExtension.version) { + // Different version or target platform of same extension is running. Requires reload to run the current version + if (this.extension.version !== runningExtension.version || this.extension.local.targetPlatform !== runningExtension.targetPlatform) { this.enabled = true; this.label = localize('reloadRequired', "Reload Required"); this.tooltip = localize('postUpdateTooltip', "Please reload Visual Studio Code to enable the updated extension."); From cf8969e45082cd8403e2a417aaffaeb41985a775 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Fri, 11 Mar 2022 22:14:26 +0100 Subject: [PATCH 139/175] Render affinity in the running extension editor --- .../extensions/browser/abstractRuntimeExtensionsEditor.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts index 3e6cc3f51db..ed27525eb03 100644 --- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts @@ -381,6 +381,8 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { } else { extraLabel = `$(remote) ${element.description.extensionLocation.authority}`; } + } else if (element.status.runningLocation && element.status.runningLocation.affinity > 0) { + extraLabel = `$(server-process) local process ${element.status.runningLocation.affinity + 1}`; } if (extraLabel) { From b83e48cf00a4bef27167998b7dc3135b093297e3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 11 Mar 2022 13:11:59 -0800 Subject: [PATCH 140/175] Reduce indent levels for switch/case --- .../view/renderers/backLayerWebView.ts | 447 +++++++++--------- 1 file changed, 212 insertions(+), 235 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 55fa13fd799..429fbb49a1c 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -563,273 +563,250 @@ var requirejs = (function() { } switch (data.type) { - case 'initialized': + case 'initialized': { this.initializeWebViewState(); break; - case 'dimension': - { - for (const update of data.updates) { - const height = update.height; - if (update.isOutput) { - const resolvedResult = this.resolveOutputId(update.id); - if (resolvedResult) { - const { cellInfo, output } = resolvedResult; - this.notebookEditor.updateOutputHeight(cellInfo, output, height, !!update.init, 'webview#dimension'); - this.notebookEditor.scheduleOutputHeightAck(cellInfo, update.id, height); - } - } else { - this.notebookEditor.updateMarkupCellHeight(update.id, height, !!update.init); + } + case 'dimension': { + for (const update of data.updates) { + const height = update.height; + if (update.isOutput) { + const resolvedResult = this.resolveOutputId(update.id); + if (resolvedResult) { + const { cellInfo, output } = resolvedResult; + this.notebookEditor.updateOutputHeight(cellInfo, output, height, !!update.init, 'webview#dimension'); + this.notebookEditor.scheduleOutputHeightAck(cellInfo, update.id, height); } + } else { + this.notebookEditor.updateMarkupCellHeight(update.id, height, !!update.init); } - break; } - case 'mouseenter': - { - const resolvedResult = this.resolveOutputId(data.id); - if (resolvedResult) { - const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); - if (latestCell) { - latestCell.outputIsHovered = true; - } + break; + } + case 'mouseenter': { + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); + if (latestCell) { + latestCell.outputIsHovered = true; } - break; } - case 'mouseleave': - { - const resolvedResult = this.resolveOutputId(data.id); - if (resolvedResult) { - const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); - if (latestCell) { - latestCell.outputIsHovered = false; - } + break; + } + case 'mouseleave': { + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); + if (latestCell) { + latestCell.outputIsHovered = false; } - break; } - case 'outputFocus': - { - const resolvedResult = this.resolveOutputId(data.id); - if (resolvedResult) { - const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); - if (latestCell) { - latestCell.outputIsFocused = true; - } + break; + } + case 'outputFocus': { + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); + if (latestCell) { + latestCell.outputIsFocused = true; } - break; } - case 'outputBlur': - { - const resolvedResult = this.resolveOutputId(data.id); - if (resolvedResult) { - const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); - if (latestCell) { - latestCell.outputIsFocused = false; - } + break; + } + case 'outputBlur': { + const resolvedResult = this.resolveOutputId(data.id); + if (resolvedResult) { + const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo); + if (latestCell) { + latestCell.outputIsFocused = false; } - break; } - case 'scroll-ack': - { - // const date = new Date(); - // const top = data.data.top; - // console.log('ack top ', top, ' version: ', data.version, ' - ', date.getMinutes() + ':' + date.getSeconds() + ':' + date.getMilliseconds()); - break; - } - case 'scroll-to-reveal': - { - this.notebookEditor.setScrollTop(data.scrollTop); - break; - } - case 'did-scroll-wheel': - { - this.notebookEditor.triggerScroll({ - ...data.payload, - preventDefault: () => { }, - stopPropagation: () => { } - }); - break; - } - case 'focus-editor': - { - const cell = this.notebookEditor.getCellById(data.cellId); - if (cell) { - if (data.focusNext) { - this.notebookEditor.focusNextNotebookCell(cell, 'editor'); - } else { - this.notebookEditor.focusNotebookCell(cell, 'editor'); - } + break; + } + case 'scroll-ack': { + // const date = new Date(); + // const top = data.data.top; + // console.log('ack top ', top, ' version: ', data.version, ' - ', date.getMinutes() + ':' + date.getSeconds() + ':' + date.getMilliseconds()); + break; + } + case 'scroll-to-reveal': { + this.notebookEditor.setScrollTop(data.scrollTop); + break; + } + case 'did-scroll-wheel': { + this.notebookEditor.triggerScroll({ + ...data.payload, + preventDefault: () => { }, + stopPropagation: () => { } + }); + break; + } + case 'focus-editor': { + const cell = this.notebookEditor.getCellById(data.cellId); + if (cell) { + if (data.focusNext) { + this.notebookEditor.focusNextNotebookCell(cell, 'editor'); + } else { + this.notebookEditor.focusNotebookCell(cell, 'editor'); } - break; } - case 'clicked-data-url': - { - this._onDidClickDataLink(data); - break; - } - case 'clicked-link': - { - let linkToOpen: URI | string | undefined; - if (matchesScheme(data.href, Schemas.command)) { - const ret = /command\:workbench\.action\.openLargeOutput\?(.*)/.exec(data.href); - if (ret && ret.length === 2) { - const outputId = ret[1]; - const group = this.editorGroupService.activeGroup; + break; + } + case 'clicked-data-url': { + this._onDidClickDataLink(data); + break; + } + case 'clicked-link': { + let linkToOpen: URI | string | undefined; + if (matchesScheme(data.href, Schemas.command)) { + const ret = /command\:workbench\.action\.openLargeOutput\?(.*)/.exec(data.href); + if (ret && ret.length === 2) { + const outputId = ret[1]; + const group = this.editorGroupService.activeGroup; - if (group) { - if (group.activeEditor) { - group.pinEditor(group.activeEditor); - } + if (group) { + if (group.activeEditor) { + group.pinEditor(group.activeEditor); } + } - this.openerService.open(CellUri.generateCellOutputUri(this.documentUri, outputId)); + this.openerService.open(CellUri.generateCellOutputUri(this.documentUri, outputId)); + return; + } + } + if (matchesSomeScheme(data.href, Schemas.http, Schemas.https, Schemas.mailto, Schemas.command, Schemas.vscodeNotebookCell, Schemas.vscodeNotebook)) { + linkToOpen = data.href; + } else if (!/^[\w\-]+:/.test(data.href)) { + if (this.documentUri.scheme === Schemas.untitled) { + const folders = this.workspaceContextService.getWorkspace().folders; + if (!folders.length) { return; } - } - if (matchesSomeScheme(data.href, Schemas.http, Schemas.https, Schemas.mailto, Schemas.command, Schemas.vscodeNotebookCell, Schemas.vscodeNotebook)) { - linkToOpen = data.href; - } else if (!/^[\w\-]+:/.test(data.href)) { - if (this.documentUri.scheme === Schemas.untitled) { - const folders = this.workspaceContextService.getWorkspace().folders; - if (!folders.length) { - return; - } - linkToOpen = URI.joinPath(folders[0].uri, data.href); - } else { - if (data.href.startsWith('/')) { - // Resolve relative to workspace - let folder = this.workspaceContextService.getWorkspaceFolder(this.documentUri); - if (!folder) { - const folders = this.workspaceContextService.getWorkspace().folders; - if (!folders.length) { - return; - } - folder = folders[0]; + linkToOpen = URI.joinPath(folders[0].uri, data.href); + } else { + if (data.href.startsWith('/')) { + // Resolve relative to workspace + let folder = this.workspaceContextService.getWorkspaceFolder(this.documentUri); + if (!folder) { + const folders = this.workspaceContextService.getWorkspace().folders; + if (!folders.length) { + return; } - linkToOpen = URI.joinPath(folder.uri, data.href); - } else { - // Resolve relative to notebook document - linkToOpen = URI.joinPath(dirname(this.documentUri), data.href); + folder = folders[0]; } - } - } - - if (linkToOpen) { - this.openerService.open(linkToOpen, { fromUserGesture: true, allowCommands: true }); - } - break; - } - case 'customKernelMessage': - { - this._onMessage.fire({ message: data.message }); - break; - } - case 'customRendererMessage': - { - this.rendererMessaging?.postMessage(data.rendererId, data.message); - break; - } - case 'clickMarkupCell': - { - const cell = this.notebookEditor.getCellById(data.cellId); - if (cell) { - if (data.shiftKey || (isMacintosh ? data.metaKey : data.ctrlKey)) { - // Modify selection - this.notebookEditor.toggleNotebookCellSelection(cell, /* fromPrevious */ data.shiftKey); + linkToOpen = URI.joinPath(folder.uri, data.href); } else { - // Normal click - this.notebookEditor.focusNotebookCell(cell, 'container', { skipReveal: true }); + // Resolve relative to notebook document + linkToOpen = URI.joinPath(dirname(this.documentUri), data.href); } } - break; } - case 'contextMenuMarkupCell': - { - const cell = this.notebookEditor.getCellById(data.cellId); - if (cell) { - // Focus the cell first + + if (linkToOpen) { + this.openerService.open(linkToOpen, { fromUserGesture: true, allowCommands: true }); + } + break; + } + case 'customKernelMessage': { + this._onMessage.fire({ message: data.message }); + break; + } + case 'customRendererMessage': { + this.rendererMessaging?.postMessage(data.rendererId, data.message); + break; + } + case 'clickMarkupCell': { + const cell = this.notebookEditor.getCellById(data.cellId); + if (cell) { + if (data.shiftKey || (isMacintosh ? data.metaKey : data.ctrlKey)) { + // Modify selection + this.notebookEditor.toggleNotebookCellSelection(cell, /* fromPrevious */ data.shiftKey); + } else { + // Normal click this.notebookEditor.focusNotebookCell(cell, 'container', { skipReveal: true }); + } + } + break; + } + case 'contextMenuMarkupCell': { + const cell = this.notebookEditor.getCellById(data.cellId); + if (cell) { + // Focus the cell first + this.notebookEditor.focusNotebookCell(cell, 'container', { skipReveal: true }); - // Then show the context menu - const webviewRect = this.element.getBoundingClientRect(); - this.contextMenuService.showContextMenu({ - getActions: () => { - const result: IAction[] = []; - const menu = this.menuService.createMenu(MenuId.NotebookCellTitle, this.contextKeyService); - createAndFillInContextMenuActions(menu, undefined, result); - menu.dispose(); - return result; - }, - getAnchor: () => ({ - x: webviewRect.x + data.clientX, - y: webviewRect.y + data.clientY - }) - }); - } - break; - } - case 'toggleMarkupPreview': - { - const cell = this.notebookEditor.getCellById(data.cellId); - if (cell && !this.notebookEditor.creationOptions.isReadOnly) { - this.notebookEditor.setMarkupCellEditState(data.cellId, CellEditState.Editing); - this.notebookEditor.focusNotebookCell(cell, 'editor', { skipReveal: true }); - } - break; - } - case 'mouseEnterMarkupCell': - { - const cell = this.notebookEditor.getCellById(data.cellId); - if (cell instanceof MarkupCellViewModel) { - cell.cellIsHovered = true; - } - break; - } - case 'mouseLeaveMarkupCell': - { - const cell = this.notebookEditor.getCellById(data.cellId); - if (cell instanceof MarkupCellViewModel) { - cell.cellIsHovered = false; - } - break; - } - case 'cell-drag-start': - { - this.notebookEditor.didStartDragMarkupCell(data.cellId, data); - break; - } - case 'cell-drag': - { - this.notebookEditor.didDragMarkupCell(data.cellId, data); - break; - } - case 'cell-drop': - { - this.notebookEditor.didDropMarkupCell(data.cellId, { - dragOffsetY: data.dragOffsetY, - ctrlKey: data.ctrlKey, - altKey: data.altKey, + // Then show the context menu + const webviewRect = this.element.getBoundingClientRect(); + this.contextMenuService.showContextMenu({ + getActions: () => { + const result: IAction[] = []; + const menu = this.menuService.createMenu(MenuId.NotebookCellTitle, this.contextKeyService); + createAndFillInContextMenuActions(menu, undefined, result); + menu.dispose(); + return result; + }, + getAnchor: () => ({ + x: webviewRect.x + data.clientX, + y: webviewRect.y + data.clientY + }) }); - break; } - case 'cell-drag-end': - { - this.notebookEditor.didEndDragMarkupCell(data.cellId); - break; + break; + } + case 'toggleMarkupPreview': { + const cell = this.notebookEditor.getCellById(data.cellId); + if (cell && !this.notebookEditor.creationOptions.isReadOnly) { + this.notebookEditor.setMarkupCellEditState(data.cellId, CellEditState.Editing); + this.notebookEditor.focusNotebookCell(cell, 'editor', { skipReveal: true }); + } + break; + } + case 'mouseEnterMarkupCell': { + const cell = this.notebookEditor.getCellById(data.cellId); + if (cell instanceof MarkupCellViewModel) { + cell.cellIsHovered = true; + } + break; + } + case 'mouseLeaveMarkupCell': { + const cell = this.notebookEditor.getCellById(data.cellId); + if (cell instanceof MarkupCellViewModel) { + cell.cellIsHovered = false; + } + break; + } + case 'cell-drag-start': { + this.notebookEditor.didStartDragMarkupCell(data.cellId, data); + break; + } + case 'cell-drag': { + this.notebookEditor.didDragMarkupCell(data.cellId, data); + break; + } + case 'cell-drop': { + this.notebookEditor.didDropMarkupCell(data.cellId, { + dragOffsetY: data.dragOffsetY, + ctrlKey: data.ctrlKey, + altKey: data.altKey, + }); + break; + } + case 'cell-drag-end': { + this.notebookEditor.didEndDragMarkupCell(data.cellId); + break; + } + case 'renderedMarkup': { + const cell = this.notebookEditor.getCellById(data.cellId); + if (cell instanceof MarkupCellViewModel) { + cell.renderedHtml = data.html; } - case 'renderedMarkup': - { - const cell = this.notebookEditor.getCellById(data.cellId); - if (cell instanceof MarkupCellViewModel) { - cell.renderedHtml = data.html; - } - this._handleHighlightCodeBlock(data.codeBlocks); - break; - } - case 'renderedCellOutput': - { - this._handleHighlightCodeBlock(data.codeBlocks); - break; - } + this._handleHighlightCodeBlock(data.codeBlocks); + break; + } + case 'renderedCellOutput': { + this._handleHighlightCodeBlock(data.codeBlocks); + break; + } } })); } From a1f4c800b44d4330ff905ac93cb8ab22be117b7c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 11 Mar 2022 13:17:13 -0800 Subject: [PATCH 141/175] Take into account NOTEBOOK_WEBVIEW_BOUNDARY Fixes #141577 --- .../notebook/browser/view/renderers/backLayerWebView.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 429fbb49a1c..9fb6dd2e103 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -32,6 +32,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust'; import { asWebviewUri, webviewGenericCspSource } from 'vs/workbench/common/webview'; import { CellEditState, ICellOutputViewModel, ICellViewModel, ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IDisplayOutputViewModel, IFocusNotebookCellOptions, IGenericCellViewModel, IInsetRenderOutput, INotebookEditorCreationOptions, INotebookWebviewMessage, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { NOTEBOOK_WEBVIEW_BOUNDARY } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList'; import { preloadsScriptStr, RendererMetadata } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads'; import { transformWebviewThemeVars } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping'; import { MarkupCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel'; @@ -630,7 +631,7 @@ var requirejs = (function() { break; } case 'scroll-to-reveal': { - this.notebookEditor.setScrollTop(data.scrollTop); + this.notebookEditor.setScrollTop(data.scrollTop - NOTEBOOK_WEBVIEW_BOUNDARY); break; } case 'did-scroll-wheel': { From 5738c241b1ff187c06704477be1fa8733029e290 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 11 Mar 2022 13:53:44 -0800 Subject: [PATCH 142/175] Fix restoring commands not working reliably --- .../common/capabilities/capabilities.ts | 1 + .../commandDetectionCapability.ts | 24 ++++++++++++++++++- src/vs/platform/terminal/common/terminal.ts | 1 + .../common/xterm/shellIntegrationAddon.ts | 8 +++++++ src/vs/platform/terminal/node/ptyService.ts | 21 ++-------------- .../contrib/terminal/browser/remotePty.ts | 8 ++++++- .../terminal/browser/terminalInstance.ts | 1 + .../browser/terminalProcessManager.ts | 8 +++++++ .../terminal/browser/terminalService.ts | 3 --- .../contrib/terminal/common/terminal.ts | 2 +- .../terminal/electron-sandbox/localPty.ts | 4 ++++ .../electron-sandbox/localTerminalBackend.ts | 11 ++------- 12 files changed, 58 insertions(+), 34 deletions(-) diff --git a/src/vs/platform/terminal/common/capabilities/capabilities.ts b/src/vs/platform/terminal/common/capabilities/capabilities.ts index a73003dd535..4f24ba26cc5 100644 --- a/src/vs/platform/terminal/common/capabilities/capabilities.ts +++ b/src/vs/platform/terminal/common/capabilities/capabilities.ts @@ -104,6 +104,7 @@ export interface ICommandDetectionCapability { * Set the command line explicitly. */ setCommandLine(commandLine: string): void; + serializeCommands(): ISerializedCommand[]; restoreCommands(serialized: ISerializedCommand[]): void; } diff --git a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts index ee3ae071162..a096b94e335 100644 --- a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts +++ b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts @@ -225,8 +225,29 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { this._currentCommand.command = commandLine; } + serializeCommands(): ISerializedCommand[] { + const serialized = this.commands.map(e => { + return { + startLine: e.marker?.line, + endLine: e.endMarker?.line, + cwd: e.cwd, + exitCode: e.exitCode, + timestamp: e.timestamp + }; + }); + if (this._currentCommand.commandStartMarker) { + serialized.push({ + startLine: this._currentCommand.commandStartMarker.line, + endLine: undefined, + cwd: undefined, + exitCode: undefined, + timestamp: 0, + }); + } + return serialized; + } + restoreCommands(serialized: ISerializedCommand[]): void { - console.log('restoreCommands', serialized); const buffer = this._terminal.buffer.normal; for (const e of serialized) { const marker = e.startLine !== undefined ? this._terminal.registerMarker(e.startLine - (buffer.baseY + buffer.cursorY)) : undefined; @@ -241,6 +262,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { timestamp: e.timestamp, cwd: e.cwd, exitCode: e.exitCode, + // TODO: Implement correctly hasOutput: false, getOutput: () => '' // hasOutput: !!(this._currentCommand.commandExecutedMarker && this._currentCommand.commandFinishedMarker && this._currentCommand.commandExecutedMarker?.line < this._currentCommand.commandFinishedMarker!.line), diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 90f2479bc2a..963650a762c 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -598,6 +598,7 @@ export interface ITerminalChildProcess { onProcessReady: Event; onDidChangeProperty: Event>; onProcessExit: Event; + onRestoreCommands?: Event; /** * Starts the process. diff --git a/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts b/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts index 07e0affd6ac..e886b19cb6d 100644 --- a/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts +++ b/src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts @@ -191,6 +191,14 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati return false; } + serializeCommands(): ISerializedCommand[] { + if (!this._terminal || !this.capabilities.has(TerminalCapability.CommandDetection)) { + return []; + } + const result = this._createOrGetCommandDetection(this._terminal).serializeCommands(); + return result; + } + restoreCommands(serialized: ISerializedCommand[]): void { if (!this._terminal) { throw new Error('Cannot restore commands before addon is activated'); diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 4e441704437..ed06eb1787a 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -18,7 +18,7 @@ import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnviro import { Terminal as XtermTerminal } from 'xterm-headless'; import type { ISerializeOptions, SerializeAddon as XtermSerializeAddon } from 'xterm-addon-serialize'; import type { Unicode11Addon as XtermUnicode11Addon } from 'xterm-addon-unicode11'; -import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISerializedCommand, ISetTerminalLayoutInfoArgs, ITerminalTabLayoutInfoDto } from 'vs/platform/terminal/common/terminalProcess'; +import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs, ITerminalTabLayoutInfoDto } from 'vs/platform/terminal/common/terminalProcess'; import { getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment'; import { TerminalProcess } from 'vs/platform/terminal/node/terminalProcess'; import { localize } from 'vs/nls'; @@ -26,7 +26,6 @@ import { ignoreProcessNames } from 'vs/platform/terminal/node/childProcessMonito import { TerminalAutoResponder } from 'vs/platform/terminal/common/terminalAutoResponder'; import { ErrorNoTelemetry } from 'vs/base/common/errors'; import { ShellIntegrationAddon } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon'; -import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; type WorkspaceId = string; @@ -772,7 +771,7 @@ class XtermSerializer implements ITerminalSerializer { data: serialized } ], - commands: this._getSerializedCommands() + commands: this._shellIntegrationAddon.serializeCommands() }; } @@ -803,22 +802,6 @@ class XtermSerializer implements ITerminalSerializer { } return SerializeAddon; } - - private _getSerializedCommands(): ISerializedCommand[] { - const commandDetection = this._shellIntegrationAddon.capabilities.get(TerminalCapability.CommandDetection); - if (!commandDetection) { - return []; - } - return commandDetection.commands.map(e => { - return { - cwd: e.cwd, - startLine: e.marker?.line, - endLine: e.endMarker?.line, - exitCode: e.exitCode, - timestamp: e.timestamp - }; - }); - } } function printTime(ms: number): string { diff --git a/src/vs/workbench/contrib/terminal/browser/remotePty.ts b/src/vs/workbench/contrib/terminal/browser/remotePty.ts index 62b17bf8ea8..99257c253d4 100644 --- a/src/vs/workbench/contrib/terminal/browser/remotePty.ts +++ b/src/vs/workbench/contrib/terminal/browser/remotePty.ts @@ -9,7 +9,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { ILogService } from 'vs/platform/log/common/log'; import { IProcessDataEvent, ITerminalChildProcess, ITerminalLaunchError, IProcessProperty, IProcessPropertyMap, ProcessPropertyType, IProcessReadyEvent } from 'vs/platform/terminal/common/terminal'; -import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminalProcess'; +import { IPtyHostProcessReplayEvent, ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess'; import { RemoteTerminalChannelClient } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; @@ -22,6 +22,8 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { readonly onDidChangeProperty = this._onDidChangeProperty.event; private readonly _onProcessExit = this._register(new Emitter()); readonly onProcessExit = this._onProcessExit.event; + private readonly _onRestoreCommands = this._register(new Emitter()); + readonly onRestoreCommands = this._onRestoreCommands.event; private _startBarrier: Barrier; @@ -178,6 +180,10 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { this._inReplay = false; } + if (e.commands.length > 0) { + this._onRestoreCommands.fire(e.commands); + } + // remove size override this._onDidChangeProperty.fire({ type: ProcessPropertyType.OverrideDimensions, value: undefined }); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 2299f73799c..15107b45f8d 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -708,6 +708,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._areLinksReady = true; this._onLinksReady.fire(this); }); + this._processManager.onRestoreCommands(e => this.xterm?.shellIntegration.restoreCommands(e)); this._loadTypeAheadAddon(xterm); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 3df2ed9b85c..1e1a286381a 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -32,6 +32,7 @@ import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilitie import { NaiveCwdDetectionCapability } from 'vs/platform/terminal/common/capabilities/naiveCwdDetectionCapability'; import { TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { URI } from 'vs/base/common/uri'; +import { ISerializedCommand } from 'vs/platform/terminal/common/terminalProcess'; /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; @@ -105,6 +106,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce readonly onEnvironmentVariableInfoChanged = this._onEnvironmentVariableInfoChange.event; private readonly _onProcessExit = this._register(new Emitter()); readonly onProcessExit = this._onProcessExit.event; + private readonly _onRestoreCommands = this._register(new Emitter()); + readonly onRestoreCommands = this._onRestoreCommands.event; get persistentProcessId(): number | undefined { return this._process?.id; } get shouldPersist(): boolean { return this._process ? this._process.shouldPersist : false; } @@ -334,6 +337,11 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce this._onDidChangeProperty.fire({ type, value }); }) ]; + if (newProcess.onRestoreCommands) { + this._processListeners.push(newProcess.onRestoreCommands(e => { + this._onRestoreCommands.fire(e); + })); + } setTimeout(() => { if (this.processState === ProcessState.Launching) { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 5eb4f42ad41..31995a09e77 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -281,9 +281,6 @@ export class TerminalService implements ITerminalService { } } }); - backend.onRestoreCommands(e => { - this.getInstanceFromId(e.id)?.xterm?.shellIntegration?.restoreCommands(e.commands); - }); } } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 65a9db55745..126c8a3938b 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -114,7 +114,6 @@ export interface ITerminalBackend { onPtyHostRestart: Event; onDidRequestDetach: Event<{ requestId: number; workspaceId: string; instanceId: number }>; - onRestoreCommands: Event<{ id: number; commands: ISerializedCommand[] }>; attachToProcess(id: number): Promise; listProcesses(): Promise; @@ -383,6 +382,7 @@ export interface ITerminalProcessManager extends IDisposable { readonly onEnvironmentVariableInfoChanged: Event; readonly onDidChangeProperty: Event>; readonly onProcessExit: Event; + readonly onRestoreCommands: Event; dispose(immediate?: boolean): void; detachFromProcess(): Promise; diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts index 20fcdd0371c..eb6df1f030b 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts @@ -141,6 +141,10 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { this._inReplay = false; } + if (e.commands.length > 0) { + this._onRestoreCommands.fire(e.commands); + } + // remove size override this._onDidChangeProperty.fire({ type: ProcessPropertyType.OverrideDimensions, value: undefined }); } diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts index 0629896166f..c38b20757e8 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts @@ -15,7 +15,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { Registry } from 'vs/platform/registry/common/platform'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IProcessPropertyMap, IShellLaunchConfig, ITerminalChildProcess, ITerminalEnvironment, ITerminalProcessOptions, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, ProcessPropertyType, TerminalSettingId, TitleEventSource } from 'vs/platform/terminal/common/terminal'; -import { IGetTerminalLayoutInfoArgs, IProcessDetails, ISerializedCommand, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess'; +import { IGetTerminalLayoutInfoArgs, IProcessDetails, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess'; import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; @@ -47,8 +47,6 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke private readonly _onDidRequestDetach = this._register(new Emitter<{ requestId: number; workspaceId: string; instanceId: number }>()); readonly onDidRequestDetach = this._onDidRequestDetach.event; - private readonly _onRestoreCommands = this._register(new Emitter<{ id: number; commands: ISerializedCommand[] }>()); - readonly onRestoreCommands = this._onRestoreCommands.event; constructor( readonly remoteAuthority: string | undefined, @@ -82,12 +80,7 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke } }); this._localPtyService.onProcessReady(e => this._ptys.get(e.id)?.handleReady(e.event)); - this._localPtyService.onProcessReplay(e => { - this._ptys.get(e.id)?.handleReplay(e.event); - if (e.event.commands.length > 0) { - this._onRestoreCommands.fire({ id: e.id, commands: e.event.commands }); - } - }); + this._localPtyService.onProcessReplay(e => this._ptys.get(e.id)?.handleReplay(e.event)); this._localPtyService.onProcessOrphanQuestion(e => this._ptys.get(e.id)?.handleOrphanQuestion()); this._localPtyService.onDidRequestDetach(e => this._onDidRequestDetach.fire(e)); From 3164ed22a0612f39e8367f1a1b05b82b5502a864 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 11 Mar 2022 14:17:35 -0800 Subject: [PATCH 143/175] Get current command working after reload --- .../capabilities/commandDetectionCapability.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts index a096b94e335..25ed46ed986 100644 --- a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts +++ b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts @@ -143,7 +143,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { } // Sanity check optional props - if (!this._currentCommand.commandStartMarker || !this._currentCommand.commandExecutedMarker || !this._currentCommand.commandStartX) { + if (!this._currentCommand.commandStartMarker || !this._currentCommand.commandExecutedMarker || this._currentCommand.commandStartX === undefined) { return; } @@ -251,10 +251,19 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { const buffer = this._terminal.buffer.normal; for (const e of serialized) { const marker = e.startLine !== undefined ? this._terminal.registerMarker(e.startLine - (buffer.baseY + buffer.cursorY)) : undefined; + // Check for invalid command if (!marker) { continue; } - this._onCommandStarted.fire({ marker } as ITerminalCommand); + // Partial command + if (!e.endLine) { + this._currentCommand.commandStartMarker = marker; + // TODO: Get real value if needed + this._currentCommand.commandStartX = 0; + this._onCommandStarted.fire({ marker } as ITerminalCommand); + continue; + } + // Full command const newCommand = { command: '', marker, From b38f0a6b975e9361846a1b252634fbcdb75f10f8 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 11 Mar 2022 14:29:08 -0800 Subject: [PATCH 144/175] Fix unit tests --- .../contrib/terminal/browser/xterm-private.d.ts | 1 + .../partialCommandDetectionCapability.test.ts | 8 ++++---- .../test/browser/terminalCommandTracker.test.ts | 14 +++++++------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/xterm-private.d.ts b/src/vs/workbench/contrib/terminal/browser/xterm-private.d.ts index cf8f8c46cdd..c015758c701 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm-private.d.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm-private.d.ts @@ -13,6 +13,7 @@ export interface IXtermCore { viewport?: { _innerRefresh(): void; }; + _onData: IEventEmitter; _onKey: IEventEmitter<{ key: string }>; _charSizeService: { diff --git a/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts b/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts index f584ffc13da..9475f8a1828 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/capabilities/partialCommandDetectionCapability.test.ts @@ -43,11 +43,11 @@ suite('PartialCommandDetectionCapability', () => { test('should not add commands when the cursor position is too close to the left side', async () => { assertCommands([]); - xterm._core._onKey.fire({ key: '\x0d' }); + xterm._core._onData.fire('\x0d'); await writeP(xterm, '\r\n'); assertCommands([]); await writeP(xterm, 'a'); - xterm._core._onKey.fire({ key: '\x0d' }); + xterm._core._onData.fire('\x0d'); await writeP(xterm, '\r\n'); assertCommands([]); }); @@ -55,11 +55,11 @@ suite('PartialCommandDetectionCapability', () => { test('should add commands when the cursor position is not too close to the left side', async () => { assertCommands([]); await writeP(xterm, 'ab'); - xterm._core._onKey.fire({ key: '\x0d' }); + xterm._core._onData.fire('\x0d'); await writeP(xterm, '\r\n\r\n'); assertCommands([0]); await writeP(xterm, 'cd'); - xterm._core._onKey.fire({ key: '\x0d' }); + xterm._core._onData.fire('\x0d'); await writeP(xterm, '\r\n'); assertCommands([0, 2]); }); diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts index ab12adaf02e..ff9274c35a3 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalCommandTracker.test.ts @@ -62,13 +62,13 @@ suite('Workbench - TerminalCommandTracker', function () { test('should track commands when the prompt is of sufficient size', async () => { assert.strictEqual(xterm.markers.length, 0); await writeP(xterm, '\x1b[3G'); // Move cursor to column 3 - xterm._core._onKey.fire({ key: '\x0d' }); + xterm._core._onData.fire('\x0d'); assert.strictEqual(xterm.markers.length, 1); }); test('should not track commands when the prompt is too small', async () => { assert.strictEqual(xterm.markers.length, 0); await writeP(xterm, '\x1b[2G'); // Move cursor to column 2 - xterm._core._onKey.fire({ key: '\x0d' }); + xterm._core._onData.fire('\x0d'); assert.strictEqual(xterm.markers.length, 0); }); }); @@ -85,7 +85,7 @@ suite('Workbench - TerminalCommandTracker', function () { }); test('should scroll to the next and previous commands', async () => { await writeP(xterm, '\x1b[3G'); // Move cursor to column 3 - xterm._core._onKey.fire({ key: '\x0d' }); // Mark line #10 + xterm._core._onData.fire('\x0d'); // Mark line #10 assert.strictEqual(xterm.markers[0].line, 9); await writeP(xterm, `\r\n`.repeat(20)); @@ -114,13 +114,13 @@ suite('Workbench - TerminalCommandTracker', function () { '\n\r1' + '\x1b[3G' // Move cursor to column 3 ); - xterm._core._onKey.fire({ key: '\x0d' }); // Mark line + xterm._core._onData.fire('\x0d'); // Mark line assert.strictEqual(xterm.markers[0].line, 10); await writeP(xterm, '\n\r2' + '\x1b[3G' // Move cursor to column 3 ); - xterm._core._onKey.fire({ key: '\x0d' }); // Mark line + xterm._core._onData.fire('\x0d'); // Mark line assert.strictEqual(xterm.markers[1].line, 11); await writeP(xterm, '\n\r3'); @@ -143,13 +143,13 @@ suite('Workbench - TerminalCommandTracker', function () { '\n\r1' + '\x1b[3G' // Move cursor to column 3 ); - xterm._core._onKey.fire({ key: '\x0d' }); // Mark line + xterm._core._onData.fire('\x0d'); // Mark line assert.strictEqual(xterm.markers[0].line, 10); await writeP(xterm, '\n\r2' + '\x1b[3G' // Move cursor to column 3 ); - xterm._core._onKey.fire({ key: '\x0d' }); // Mark line + xterm._core._onData.fire('\x0d'); // Mark line assert.strictEqual(xterm.markers[1].line, 11); await writeP(xterm, '\n\r3'); From 421e8bd7a1c3cb6c697b69efab92072b448e6e94 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Fri, 11 Mar 2022 15:59:44 -0800 Subject: [PATCH 145/175] configure layout directly with both option --- src/vs/workbench/browser/actions/layoutActions.ts | 8 +++++++- .../browser/parts/auxiliarybar/auxiliaryBarActions.ts | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 16793767636..f1b97346573 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -223,7 +223,7 @@ MenuRegistry.appendMenuItem(MenuId.LayoutControlMenu, { title: localize('configureLayout', "Configure Layout"), icon: configureLayoutIcon, group: '1_workbench_layout', - when: ContextKeyExpr.or(ContextKeyExpr.equals('config.workbench.experimental.layoutControl.type', 'menu'), ContextKeyExpr.equals('config.workbench.experimental.layoutControl.type', 'both')) + when: ContextKeyExpr.equals('config.workbench.experimental.layoutControl.type', 'menu') }); @@ -1170,10 +1170,16 @@ registerAction2(class CustomizeLayoutAction extends Action2 { id: 'workbench.action.customizeLayout', title: localize('customizeLayout', "Customize Layout..."), f1: true, + icon: configureLayoutIcon, menu: [ { id: MenuId.LayoutControlMenuSubmenu, group: 'z_end', + }, + { + id: MenuId.LayoutControlMenu, + when: ContextKeyExpr.equals('config.workbench.experimental.layoutControl.type', 'both'), + group: 'z_end' } ] }); diff --git a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts index 02f428254c7..64dfa1da6d1 100644 --- a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts +++ b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts @@ -77,7 +77,7 @@ MenuRegistry.appendMenuItems([ title: localize('miShowAuxiliaryBarNoMnemonic', "Show Secondary Side Bar"), toggled: AuxiliaryBarVisibleContext }, - order: 4 + order: 2 } }, { From 58966a9814a3b2c488d11af1a332832acadf887d Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Fri, 11 Mar 2022 16:02:05 -0800 Subject: [PATCH 146/175] try out layout type both default --- 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 d16406e9026..cffb5a75f84 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -398,7 +398,7 @@ const registry = Registry.as(ConfigurationExtensions.Con localize('layoutcontrol.type.both', "Shows both the dropdown and toggle buttons."), ], 'tags': ['experimental'], - 'default': 'menu', + 'default': 'both', 'description': localize('layoutControlType', "Controls whether the layout control in the custom title bar is displayed as a single menu button or with multiple UI toggles."), }, } From e4cf231274f8d9ad101c511f547a4773a1a08ea1 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 11 Mar 2022 13:50:54 -0800 Subject: [PATCH 147/175] fix typo --- .../notebook/browser/viewParts/notebookEditorToolbar.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorToolbar.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorToolbar.ts index 1e5302d296e..f897a762e74 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorToolbar.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorToolbar.ts @@ -317,7 +317,7 @@ export class NotebookEditorToolbar extends Disposable { } })); - this._reigsterNotebookActionsToolbar(); + this._registerNotebookActionsToolbar(); } private _buildBody() { @@ -338,7 +338,7 @@ export class NotebookEditorToolbar extends Disposable { DOM.append(this.domNode, this._notebookTopRightToolbarContainer); } - private _reigsterNotebookActionsToolbar() { + private _registerNotebookActionsToolbar() { this._notebookGlobalActionsMenu = this._register(this.menuService.createMenu(this.notebookEditor.creationOptions.menuIds.notebookToolbar, this.contextKeyService)); this._register(this._notebookGlobalActionsMenu); From 8ca417c5ab3657efe2c0494f5dc288417d937fe4 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 11 Mar 2022 20:34:17 -0500 Subject: [PATCH 148/175] run all functions in PROMPT_COMMAND (#144779) --- .../browser/media/shellIntegration-bash.sh | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh index 211b4ef32fa..964687b7854 100755 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh @@ -83,14 +83,34 @@ preexec() { update_prompt prompt_cmd_original() { STATUS="$?" - $ORIGINAL_PROMPT_COMMAND + if [[ "$ORIGINAL_PROMPT_COMMAND" =~ .+\;.+ ]]; then + IFS=';' + read -ra ADDR <<<"$ORIGINAL_PROMPT_COMMAND" + for ((i = 0; i < ${#ADDR[@]}; i++)); do + eval ${ADDR[i]} + done + IFS='' + else + for i in "${ORIGINAL_PROMPT_COMMAND[@]}"; do + eval $i + done + fi precmd } + prompt_cmd() { STATUS="$?" precmd } -ORIGINAL_PROMPT_COMMAND=$PROMPT_COMMAND + +if [[ "$PROMPT_COMMAND" =~ (.+\;.+) ]]; then + # item1;item2... + ORIGINAL_PROMPT_COMMAND="$PROMPT_COMMAND" +else + # (item1, item2...) + ORIGINAL_PROMPT_COMMAND=${PROMPT_COMMAND[@]} +fi + if [[ -n "$ORIGINAL_PROMPT_COMMAND" && "$ORIGINAL_PROMPT_COMMAND" != "prompt_cmd" ]]; then PROMPT_COMMAND=prompt_cmd_original else From 3e5c7e2c570a729e664253baceaf443b69e82da6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 12 Mar 2022 08:23:43 +0100 Subject: [PATCH 149/175] smoke - disable trust cc @sbatten @lszomoru --- test/automation/src/playwrightDriver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/automation/src/playwrightDriver.ts b/test/automation/src/playwrightDriver.ts index b0ecb7153d8..4f0f7a94fba 100644 --- a/test/automation/src/playwrightDriver.ts +++ b/test/automation/src/playwrightDriver.ts @@ -224,7 +224,7 @@ async function launchServer(options: LaunchOptions) { ...process.env }; - const args = ['--disable-telemetry', '--port', `${port++}`, '--driver', 'web', '--extensions-dir', extensionsPath, '--server-data-dir', agentFolder, '--accept-server-license-terms']; + const args = ['--disable-telemetry', '--disable-workspace-trust', '--port', `${port++}`, '--driver', 'web', '--extensions-dir', extensionsPath, '--server-data-dir', agentFolder, '--accept-server-license-terms']; let serverLocation: string | undefined; if (codeServerPath) { From bcbf1684e2e040dec491a9386438ce5af8ab9104 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 14 Mar 2022 16:12:28 +0530 Subject: [PATCH 150/175] fix outdated targetplatforms in web --- .../extensions/browser/extensionsWorkbenchService.ts | 6 +++++- .../extensions/test/electron-browser/extension.test.ts | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index a6e9045425c..fd83df23a39 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -221,7 +221,11 @@ export class Extension implements IExtension { } get outdatedTargetPlatform(): boolean { - return !!this.local && !!this.gallery && this.local.targetPlatform !== TargetPlatform.UNDEFINED && this.local.targetPlatform !== this.gallery.properties.targetPlatform && semver.eq(this.latestVersion, this.version); + return !!this.local && !!this.gallery + && ![TargetPlatform.UNDEFINED, TargetPlatform.WEB].includes(this.local.targetPlatform) + && this.gallery.properties.targetPlatform !== TargetPlatform.WEB + && this.local.targetPlatform !== this.gallery.properties.targetPlatform + && semver.eq(this.latestVersion, this.version); } get telemetryData(): any { diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts index cb37de9dadd..de60b59fab1 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extension.test.ts @@ -56,6 +56,16 @@ suite('Extension Test', () => { assert.strictEqual(extension.outdated, true); }); + test('extension is not outdated when local and gallery are on same version and local is on web', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', {}, { targetPlatform: TargetPlatform.WEB }), aGalleryExtension('somext')); + assert.strictEqual(extension.outdated, false); + }); + + test('extension is not outdated when local and gallery are on same version and gallery is on web', () => { + const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext'), aGalleryExtension('somext', {}, { targetPlatform: TargetPlatform.WEB })); + assert.strictEqual(extension.outdated, false); + }); + test('extension is not outdated when local is not pre-release but gallery is pre-release', () => { const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, undefined, aLocalExtension('somext', { version: '1.0.0' }), aGalleryExtension('somext', { version: '1.0.1' }, { isPreReleaseVersion: true })); assert.strictEqual(extension.outdated, false); From 9422f0a5686af6e46d1664384895cd71e34c2bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Mon, 14 Mar 2022 20:10:21 +0800 Subject: [PATCH 151/175] update Lua-grammar (#144975) * update Lua-grammar * Update test Co-authored-by: Alex Ross --- extensions/lua/cgmanifest.json | 2 +- extensions/lua/syntaxes/lua.tmLanguage.json | 8 ++------ .../test/colorize-results/test_lua.json | 20 +++++++++---------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/extensions/lua/cgmanifest.json b/extensions/lua/cgmanifest.json index 432d82cc8bf..153296f8cce 100644 --- a/extensions/lua/cgmanifest.json +++ b/extensions/lua/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "sumneko/lua.tmbundle", "repositoryUrl": "https://github.com/sumneko/lua.tmbundle", - "commitHash": "9b79cbc54c3267065fca3d7b5b3845d1efbd091d" + "commitHash": "43da68bb99b948782e57985f633fa0c395190674" } }, "licenseDetail": [ diff --git a/extensions/lua/syntaxes/lua.tmLanguage.json b/extensions/lua/syntaxes/lua.tmLanguage.json index 23404451fc9..05c4b16814f 100644 --- a/extensions/lua/syntaxes/lua.tmLanguage.json +++ b/extensions/lua/syntaxes/lua.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/sumneko/lua.tmbundle/commit/9b79cbc54c3267065fca3d7b5b3845d1efbd091d", + "version": "https://github.com/sumneko/lua.tmbundle/commit/43da68bb99b948782e57985f633fa0c395190674", "name": "Lua", "scopeName": "source.lua", "patterns": [ @@ -170,10 +170,6 @@ "match": "(? Date: Mon, 14 Mar 2022 13:43:55 +0100 Subject: [PATCH 152/175] Sort comments in view by resource Part of microsoft/vscode-pull-request-github#3354 --- .../contrib/comments/common/commentModel.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/comments/common/commentModel.ts b/src/vs/workbench/contrib/comments/common/commentModel.ts index a9c9fbf27ec..4986e959ffe 100644 --- a/src/vs/workbench/contrib/comments/common/commentModel.ts +++ b/src/vs/workbench/contrib/comments/common/commentModel.ts @@ -6,7 +6,7 @@ import { URI } from 'vs/base/common/uri'; import { IRange } from 'vs/editor/common/core/range'; import { Comment, CommentThread, CommentThreadChangedEvent } from 'vs/editor/common/languages'; -import { groupBy, flatten } from 'vs/base/common/arrays'; +import { groupBy } from 'vs/base/common/arrays'; import { localize } from 'vs/nls'; export interface ICommentThreadChangedEvent extends CommentThreadChangedEvent { @@ -71,9 +71,16 @@ export class CommentsModel { this.commentThreadsMap = new Map(); } + private updateResourceCommentThreads() { + this.resourceCommentThreads = [...this.commentThreadsMap.values()].flat(); + this.resourceCommentThreads.sort((a, b) => { + return a.resource.toString() > b.resource.toString() ? 1 : -1; + }); + } + public setCommentThreads(owner: string, commentThreads: CommentThread[]): void { this.commentThreadsMap.set(owner, this.groupByResource(owner, commentThreads)); - this.resourceCommentThreads = flatten([...this.commentThreadsMap.values()]); + this.updateResourceCommentThreads(); } public updateCommentThreads(event: ICommentThreadChangedEvent): boolean { @@ -123,7 +130,7 @@ export class CommentsModel { }); this.commentThreadsMap.set(owner, threadsForOwner); - this.resourceCommentThreads = flatten([...this.commentThreadsMap.values()]); + this.updateResourceCommentThreads(); return removed.length > 0 || changed.length > 0 || added.length > 0; } From 9212c3db3bf5585f9d316d513b63519b3db125fa Mon Sep 17 00:00:00 2001 From: Semphris Date: Sun, 13 Mar 2022 20:21:33 -0400 Subject: [PATCH 153/175] Update Seti theme --- extensions/theme-seti/cgmanifest.json | 2 +- extensions/theme-seti/icons/seti.woff | Bin 37204 -> 37204 bytes .../theme-seti/icons/vs-seti-icon-theme.json | 32 +++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/extensions/theme-seti/cgmanifest.json b/extensions/theme-seti/cgmanifest.json index e5fe1773015..00e2991fb96 100644 --- a/extensions/theme-seti/cgmanifest.json +++ b/extensions/theme-seti/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "seti-ui", "repositoryUrl": "https://github.com/jesseweed/seti-ui", - "commitHash": "921e46b4c378059032c2a9247a6cc96d0f9e57b4" + "commitHash": "8dba1bc311dad1b9bc23c4779149f3bf9baa8cb0" } }, "version": "0.1.0" diff --git a/extensions/theme-seti/icons/seti.woff b/extensions/theme-seti/icons/seti.woff index 05b5f72c2e4fbeb356ae00cd22128d3b32fef007..aeb87b845af6596a1b72e1590613ea35a538cc52 100644 GIT binary patch delta 59 zcmV-B0L1^)q5{;S0+5XZn-;3EkmZRb1Dp4j#Pi#HW#DFh0Tf}l7xGdXnP$Gs+z+HU R7??mj09bnq8nc>;x&~-18&CiM delta 59 zcmV-B0L1^)q5{;S0+5XZXE`FVkmZRbgVGf(@%%Pl8Mv8W07V$?S^Ww}rkO7@_X8;o R1||>>06nP+w6mIux(58_7t;U$ diff --git a/extensions/theme-seti/icons/vs-seti-icon-theme.json b/extensions/theme-seti/icons/vs-seti-icon-theme.json index 72f3c989c2a..41d2556aaa9 100644 --- a/extensions/theme-seti/icons/vs-seti-icon-theme.json +++ b/extensions/theme-seti/icons/vs-seti-icon-theme.json @@ -1781,10 +1781,16 @@ "karma.conf.js": "_karma", "karma.conf.coffee": "_karma", "readme.md": "_info", + "readme.txt": "_info", + "readme": "_info", "changelog.md": "_clock", + "changelog.txt": "_clock", "changelog": "_clock", "changes.md": "_clock", + "changes.txt": "_clock", + "changes": "_clock", "version.md": "_clock", + "version.txt": "_clock", "version": "_clock", "mvnw": "_maven", "tsconfig.json": "_tsconfig", @@ -1830,16 +1836,26 @@ "webpack.prod.cjs": "_webpack", "license": "_license", "licence": "_license", + "license.txt": "_license", + "licence.txt": "_license", "license.md": "_license", "licence.md": "_license", "copying": "_license", + "copying.txt": "_license", + "copying.md": "_license", "compiling": "_license_1", + "compiling.txt": "_license_1", + "compiling.md": "_license_1", "contributing": "_license_2", + "contributing.txt": "_license_2", + "contributing.md": "_license_2", "qmakefile": "_makefile_1", "omakefile": "_makefile_2", "cmakelists.txt": "_makefile_3", "procfile": "_heroku", "todo": "_todo", + "todo.txt": "_todo", + "todo.md": "_todo", "npm-debug.log": "_npm_ignored" }, "languageIds": { @@ -2239,10 +2255,16 @@ "karma.conf.js": "_karma_light", "karma.conf.coffee": "_karma_light", "readme.md": "_info_light", + "readme.txt": "_info_light", + "readme": "_info_light", "changelog.md": "_clock_light", + "changelog.txt": "_clock_light", "changelog": "_clock_light", "changes.md": "_clock_light", + "changes.txt": "_clock_light", + "changes": "_clock_light", "version.md": "_clock_light", + "version.txt": "_clock_light", "version": "_clock_light", "mvnw": "_maven_light", "tsconfig.json": "_tsconfig_light", @@ -2288,11 +2310,19 @@ "webpack.prod.cjs": "_webpack_light", "license": "_license_light", "licence": "_license_light", + "license.txt": "_license_light", + "licence.txt": "_license_light", "license.md": "_license_light", "licence.md": "_license_light", "copying": "_license_light", + "copying.txt": "_license_light", + "copying.md": "_license_light", "compiling": "_license_1_light", + "compiling.txt": "_license_1_light", + "compiling.md": "_license_1_light", "contributing": "_license_2_light", + "contributing.txt": "_license_2_light", + "contributing.md": "_license_2_light", "qmakefile": "_makefile_1_light", "omakefile": "_makefile_2_light", "cmakelists.txt": "_makefile_3_light", @@ -2300,5 +2330,5 @@ "npm-debug.log": "_npm_ignored_light" } }, - "version": "https://github.com/jesseweed/seti-ui/commit/921e46b4c378059032c2a9247a6cc96d0f9e57b4" + "version": "https://github.com/jesseweed/seti-ui/commit/8dba1bc311dad1b9bc23c4779149f3bf9baa8cb0" } \ No newline at end of file From 6e0be36443e86562f843d8406ac0fc706d784159 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 14 Mar 2022 14:41:54 +0100 Subject: [PATCH 154/175] Do not hard-code `Typing` as the label for `SingleModelEditStackElement` --- src/vs/editor/common/model/editStack.ts | 12 ++++++------ .../contrib/bulkEdit/browser/bulkTextEdits.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/editor/common/model/editStack.ts b/src/vs/editor/common/model/editStack.ts index bb67566ac5a..ad5a0f6d37d 100644 --- a/src/vs/editor/common/model/editStack.ts +++ b/src/vs/editor/common/model/editStack.ts @@ -161,11 +161,11 @@ export class SingleModelEditStackElement implements IResourceUndoRedoElement { return this.model.uri; } - public get label(): string { - return nls.localize('edit', "Typing"); - } - - constructor(model: ITextModel, beforeCursorState: Selection[] | null) { + constructor( + public readonly label: string, + model: ITextModel, + beforeCursorState: Selection[] | null + ) { this.model = model; this._data = SingleModelEditStackData.create(model, beforeCursorState); } @@ -413,7 +413,7 @@ export class EditStack { if (isEditStackElement(lastElement) && lastElement.canAppend(this._model)) { return lastElement; } - const newElement = new SingleModelEditStackElement(this._model, beforeCursorState); + const newElement = new SingleModelEditStackElement(nls.localize('edit', "Typing"), this._model, beforeCursorState); this._undoRedoService.pushElement(newElement); return newElement; } diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkTextEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkTextEdits.ts index 737c8d2a00d..c4042b8aec8 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkTextEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkTextEdits.ts @@ -249,7 +249,7 @@ export class BulkTextEdits { // This edit touches a single model => keep things simple const task = tasks[0]; if (!task.isNoOp()) { - const singleModelEditStackElement = new SingleModelEditStackElement(task.model, task.getBeforeCursorState()); + const singleModelEditStackElement = new SingleModelEditStackElement(this._label, task.model, task.getBeforeCursorState()); this._undoRedoService.pushElement(singleModelEditStackElement, this._undoRedoGroup, this._undoRedoSource); task.apply(); singleModelEditStackElement.close(); @@ -259,7 +259,7 @@ export class BulkTextEdits { // prepare multi model undo element const multiModelEditStackElement = new MultiModelEditStackElement( this._label, - tasks.map(t => new SingleModelEditStackElement(t.model, t.getBeforeCursorState())) + tasks.map(t => new SingleModelEditStackElement(this._label, t.model, t.getBeforeCursorState())) ); this._undoRedoService.pushElement(multiModelEditStackElement, this._undoRedoGroup, this._undoRedoSource); for (const task of tasks) { From 8a50a98acedbffab18473f59a1132fa6174731d2 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 14 Mar 2022 12:44:46 -0400 Subject: [PATCH 155/175] fix #145036 (#145040) --- .../browser/media/shellIntegration-bash.sh | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh index 964687b7854..adfdb1e634f 100755 --- a/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh +++ b/src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh @@ -85,16 +85,14 @@ prompt_cmd_original() { STATUS="$?" if [[ "$ORIGINAL_PROMPT_COMMAND" =~ .+\;.+ ]]; then IFS=';' - read -ra ADDR <<<"$ORIGINAL_PROMPT_COMMAND" - for ((i = 0; i < ${#ADDR[@]}; i++)); do - eval ${ADDR[i]} - done - IFS='' else - for i in "${ORIGINAL_PROMPT_COMMAND[@]}"; do - eval $i - done + IFS=' ' fi + read -ra ADDR <<<"$ORIGINAL_PROMPT_COMMAND" + for ((i = 0; i < ${#ADDR[@]}; i++)); do + eval ${ADDR[i]} + done + IFS='' precmd } From 5a751e2bed0aed8d70926ba535f489860622a010 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 14 Mar 2022 12:44:58 -0400 Subject: [PATCH 156/175] fix #145044 (#145054) --- src/vs/workbench/contrib/terminal/browser/media/terminal.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index 9702a0cc0c3..6605586e048 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -93,6 +93,10 @@ display: block; } +.monaco-workbench .editor-instance .xterm { + padding-left: 20px !important; +} + .monaco-workbench .pane-body.integrated-terminal .terminal-group .monaco-split-view2.horizontal .split-view-view:first-child .xterm, .integrated-terminal.shell-integration .xterm { padding-left: 20px !important; From 04f6cdc4ff2dfc5988ed057573d4af1477de7072 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Mon, 14 Mar 2022 12:45:30 -0400 Subject: [PATCH 157/175] support Copy as HTML in the terminal (#144784) --- .../contrib/terminal/browser/terminal.ts | 2 +- .../terminal/browser/terminalActions.ts | 14 ++++++++++ .../terminal/browser/terminalInstance.ts | 15 +++++++++-- .../contrib/terminal/browser/terminalMenus.ts | 26 +++++++++++++++++-- .../terminal/browser/xterm/xtermTerminal.ts | 19 ++++++++++++++ .../contrib/terminal/common/terminal.ts | 2 ++ 6 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index cfc20e347b5..ca036c6f1b9 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -649,7 +649,7 @@ export interface ITerminalInstance { /** * Copies the terminal selection to the clipboard. */ - copySelection(): Promise; + copySelection(asHtml?: boolean): Promise; /** * Current selection in the terminal. diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index a05ec3f927d..ed19ad2653a 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -2113,6 +2113,20 @@ export function registerTerminalActions() { await accessor.get(ITerminalService).activeInstance?.copySelection(); } }); + registerAction2(class extends Action2 { + constructor() { + super({ + id: TerminalCommandId.CopySelectionAsHtml, + title: { value: localize('workbench.action.terminal.copySelectionAsHtml', "Copy Selection as HTML"), original: 'Copy Selection as HTML' }, + f1: true, + category, + precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), TerminalContextKeys.textSelected) + }); + } + async run(accessor: ServicesAccessor) { + await accessor.get(ITerminalService).activeInstance?.copySelection(true); + } + }); } if (BrowserFeatures.clipboard.readText) { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index c4b868836cb..dea2f9b1fff 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -1126,10 +1126,21 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return this.xterm ? this.xterm.raw.hasSelection() : false; } - async copySelection(): Promise { + async copySelection(asHtml?: boolean): Promise { const xterm = await this._xtermReadyPromise; if (this.hasSelection()) { - await this._clipboardService.writeText(xterm.raw.getSelection()); + if (asHtml) { + const selectionAsHtml = await xterm.getSelectionAsHtml(); + function listener(e: any) { + e.clipboardData.setData('text/html', selectionAsHtml); + e.preventDefault(); + } + document.addEventListener('copy', listener); + document.execCommand('copy'); + document.removeEventListener('copy', listener); + } else { + await this._clipboardService.writeText(xterm.raw.getSelection()); + } } else { this._notificationService.warn(nls.localize('terminal.integrated.copySelection.noSelection', 'The terminal has no selection to copy')); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts b/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts index 94bbabfc054..5183542cb14 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts @@ -137,6 +137,17 @@ export function setupTerminalMenus(): void { order: 1 } }, + { + id: MenuId.TerminalInstanceContext, + item: { + command: { + id: TerminalCommandId.CopySelectionAsHtml, + title: localize('workbench.action.terminal.copySelectionAsHtml', "Copy as HTML") + }, + group: ContextMenuGroup.Edit, + order: 2 + } + }, { id: MenuId.TerminalInstanceContext, item: { @@ -145,7 +156,7 @@ export function setupTerminalMenus(): void { title: localize('workbench.action.terminal.paste.short', "Paste") }, group: ContextMenuGroup.Edit, - order: 2 + order: 3 } }, { @@ -237,6 +248,17 @@ export function setupTerminalMenus(): void { order: 1 } }, + { + id: MenuId.TerminalEditorInstanceContext, + item: { + command: { + id: TerminalCommandId.CopySelectionAsHtml, + title: localize('workbench.action.terminal.copySelectionAsHtml', "Copy as HTML") + }, + group: ContextMenuGroup.Edit, + order: 2 + } + }, { id: MenuId.TerminalEditorInstanceContext, item: { @@ -245,7 +267,7 @@ export function setupTerminalMenus(): void { title: localize('workbench.action.terminal.paste.short', "Paste") }, group: ContextMenuGroup.Edit, - order: 2 + order: 3 } }, { diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts index feec88f47ac..5bfb629b1be 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts @@ -7,6 +7,7 @@ import type { IBuffer, ITheme, RendererType, Terminal as RawXtermTerminal } from import type { ISearchOptions, SearchAddon as SearchAddonType } from 'xterm-addon-search'; import type { Unicode11Addon as Unicode11AddonType } from 'xterm-addon-unicode11'; import type { WebglAddon as WebglAddonType } from 'xterm-addon-webgl'; +import { SerializeAddon as SerializeAddonType } from 'xterm-addon-serialize'; import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; @@ -42,6 +43,7 @@ const NUMBER_OF_FRAMES_TO_MEASURE = 20; let SearchAddon: typeof SearchAddonType; let Unicode11Addon: typeof Unicode11AddonType; let WebglAddon: typeof WebglAddonType; +let SerializeAddon: typeof SerializeAddonType; /** * Wraps the xterm object with additional functionality. Interaction with the backing process is out @@ -64,6 +66,7 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal { private _searchAddon?: SearchAddonType; private _unicode11Addon?: Unicode11AddonType; private _webglAddon?: WebglAddonType; + private _serializeAddon?: SerializeAddonType; private readonly _onDidRequestRunCommand = new Emitter(); readonly onDidRequestRunCommand = this._onDidRequestRunCommand.event; @@ -167,6 +170,15 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal { this.raw.loadAddon(this._decorationAddon); } + async getSelectionAsHtml(): Promise { + if (!this._serializeAddon) { + const Addon = await this._getSerializeAddonConstructor(); + this._serializeAddon = new Addon(); + this.raw.loadAddon(this._serializeAddon); + } + return this._serializeAddon.serializeAsHTML({ onlySelection: true }); + } + attachToElement(container: HTMLElement): HTMLElement { // Update the theme when attaching as the terminal location could have changed this._updateTheme(); @@ -404,6 +416,13 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal { return WebglAddon; } + protected async _getSerializeAddonConstructor(): Promise { + if (!SerializeAddon) { + SerializeAddon = (await import('xterm-addon-serialize')).SerializeAddon; + } + return SerializeAddon; + } + private _disposeOfWebglRenderer(): void { try { this._webglAddon?.dispose(); diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 3178608dd07..996cfcd801b 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -475,6 +475,7 @@ export const enum TerminalCommandId { RunRecentCommand = 'workbench.action.terminal.runRecentCommand', GoToRecentDirectory = 'workbench.action.terminal.goToRecentDirectory', CopySelection = 'workbench.action.terminal.copySelection', + CopySelectionAsHtml = 'workbench.action.terminal.copySelectionAsHtml', SelectAll = 'workbench.action.terminal.selectAll', DeleteWordLeft = 'workbench.action.terminal.deleteWordLeft', DeleteWordRight = 'workbench.action.terminal.deleteWordRight', @@ -566,6 +567,7 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ TerminalCommandId.ClearSelection, TerminalCommandId.Clear, TerminalCommandId.CopySelection, + TerminalCommandId.CopySelectionAsHtml, TerminalCommandId.DeleteToLineStart, TerminalCommandId.DeleteWordLeft, TerminalCommandId.DeleteWordRight, From 53aaa205e6eec5deb6f0069d4bdd8c0293f9da86 Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Mon, 14 Mar 2022 13:26:45 -0400 Subject: [PATCH 158/175] Fix #144605 --- extensions/git/src/repository.ts | 2 +- .../src/singlefolder-tests/commands.test.ts | 6 ++-- .../src/singlefolder-tests/window.test.ts | 14 +++++----- .../api/common/extHostDebugService.ts | 2 +- .../workbench/api/common/extHostEditorTabs.ts | 10 +++---- .../test/browser/extHostEditorTabs.test.ts | 28 +++++++++---------- src/vscode-dts/vscode.proposed.tabs.d.ts | 3 +- 7 files changed, 32 insertions(+), 33 deletions(-) diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index ecac68568c4..a276eaca322 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -1273,7 +1273,7 @@ export class Repository implements Disposable { const diffEditorTabsToClose: Tab[] = []; // Index - const tabs = window.tabGroups.all.map(g => g.tabs).flat(1); + const tabs = window.tabGroups.groups.map(g => g.tabs).flat(1); diffEditorTabsToClose.push(...tabs .filter(t => t.resource && t.resource.scheme === 'git' && t.kind === TabKind.Diff && diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts index 780ed8ddc1e..17b0139d6ef 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts @@ -112,15 +112,15 @@ suite('vscode API - commands', () => { await commands.executeCommand('vscode.open', uri); assert.strictEqual(window.activeTextEditor?.viewColumn, ViewColumn.One); - assert.strictEqual(window.tabGroups.all[0].activeTab?.viewColumn, ViewColumn.One); + assert.strictEqual(window.tabGroups.groups[0].activeTab?.viewColumn, ViewColumn.One); await commands.executeCommand('vscode.open', uri, ViewColumn.Two); assert.strictEqual(window.activeTextEditor?.viewColumn, ViewColumn.Two); - assert.strictEqual(window.tabGroups.all[1].activeTab?.viewColumn, ViewColumn.Two); + assert.strictEqual(window.tabGroups.groups[1].activeTab?.viewColumn, ViewColumn.Two); await commands.executeCommand('vscode.open', uri, ViewColumn.One); assert.strictEqual(window.activeTextEditor?.viewColumn, ViewColumn.One); - assert.strictEqual(window.tabGroups.all[0].activeTab?.viewColumn, ViewColumn.One); + assert.strictEqual(window.tabGroups.groups[0].activeTab?.viewColumn, ViewColumn.One); let e1: Error | undefined = undefined; try { diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts index 3c1d22d5202..38565c017f5 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts @@ -383,12 +383,12 @@ suite('vscode API - window', () => { await window.showTextDocument(docC, { viewColumn: ViewColumn.Two, preview: false }); const tabGroups = window.tabGroups; - assert.strictEqual(tabGroups.all.length, 2); + assert.strictEqual(tabGroups.groups.length, 2); - const group1Tabs = tabGroups.all[0].tabs; + const group1Tabs = tabGroups.groups[0].tabs; assert.strictEqual(group1Tabs.length, 2); - const group2Tabs = tabGroups.all[1].tabs; + const group2Tabs = tabGroups.groups[1].tabs; assert.strictEqual(group2Tabs.length, 1); await group1Tabs[0].move(1, ViewColumn.One); @@ -397,7 +397,7 @@ suite('vscode API - window', () => { test('Tabs - vscode.open & vscode.diff', async function () { // Simple function to get the active tab const getActiveTab = () => { - return window.tabGroups.all.find(g => g.isActive)?.activeTab; + return window.tabGroups.groups.find(g => g.isActive)?.activeTab; }; const [docA, docB, docC] = await Promise.all([ @@ -420,7 +420,7 @@ suite('vscode API - window', () => { await commands.executeCommand('vscode.diff', leftDiff, rightDiff, 'Diff', { viewColumn: ViewColumn.Four, preview: false }); assert.strictEqual(getActiveTab()?.viewColumn, ViewColumn.Four); - const tabs = window.tabGroups.all.map(g => g.tabs).flat(1); + const tabs = window.tabGroups.groups.map(g => g.tabs).flat(1); assert.strictEqual(tabs.length, 5); assert.strictEqual(tabs[0].resource?.toString(), docA.uri.toString()); assert.strictEqual(tabs[1].resource?.toString(), docB.uri.toString()); @@ -451,7 +451,7 @@ suite('vscode API - window', () => { const rightDiff = await createRandomFile(); await commands.executeCommand('vscode.diff', leftDiff, rightDiff, 'Diff', { viewColumn: ViewColumn.Three, preview: false }); - const tabs = window.tabGroups.all.map(g => g.tabs).flat(1); + const tabs = window.tabGroups.groups.map(g => g.tabs).flat(1); assert.strictEqual(tabs.length, 5); // All resources should match the text documents as they're the only tabs currently open @@ -480,7 +480,7 @@ suite('vscode API - window', () => { // Function to acquire the active tab within the active group const getActiveTabInActiveGroup = () => { - const activeGroup = window.tabGroups.all.filter(group => group.isActive)[0]; + const activeGroup = window.tabGroups.groups.filter(group => group.isActive)[0]; return activeGroup.activeTab; }; diff --git a/src/vs/workbench/api/common/extHostDebugService.ts b/src/vs/workbench/api/common/extHostDebugService.ts index 26314660114..c0d3d9a3ea3 100644 --- a/src/vs/workbench/api/common/extHostDebugService.ts +++ b/src/vs/workbench/api/common/extHostDebugService.ts @@ -953,7 +953,7 @@ export class ExtHostVariableResolverService extends AbstractVariableResolverServ if (activeEditor) { return activeEditor.document.uri; } - const activeTab = editorTabs.tabGroups.all.find(group => group.isActive)?.activeTab; + const activeTab = editorTabs.tabGroups.groups.find(group => group.isActive)?.activeTab; if (activeTab !== undefined) { // Resolve a resource from the tab const asSideBySideResource = activeTab.resource as { primary?: URI; secondary?: URI } | undefined; diff --git a/src/vs/workbench/api/common/extHostEditorTabs.ts b/src/vs/workbench/api/common/extHostEditorTabs.ts index 5d6033c4849..e3b5fb3d5e9 100644 --- a/src/vs/workbench/api/common/extHostEditorTabs.ts +++ b/src/vs/workbench/api/common/extHostEditorTabs.ts @@ -33,7 +33,7 @@ export interface IEditorTabGroup { } export interface IEditorTabGroups { - all: IEditorTabGroup[]; + groups: IEditorTabGroup[]; activeTabGroup: IEditorTabGroup | undefined; readonly onDidChangeTabGroup: Event; readonly onDidChangeActiveTabGroup: Event; @@ -55,7 +55,7 @@ export class ExtHostEditorTabs implements IExtHostEditorTabs { private readonly _onDidChangeActiveTabGroup = new Emitter(); private _tabGroups: IEditorTabGroups = { - all: [], + groups: [], activeTabGroup: undefined, onDidChangeTabGroup: this._onDidChangeTabGroup.event, onDidChangeActiveTabGroup: this._onDidChangeActiveTabGroup.event @@ -71,7 +71,7 @@ export class ExtHostEditorTabs implements IExtHostEditorTabs { $acceptEditorTabModel(tabGroups: IEditorTabGroupDto[]): void { // Clears the tab groups array - this._tabGroups.all.length = 0; + this._tabGroups.groups.length = 0; let activeGroupFound = false; for (const group of tabGroups) { let activeTab: IEditorTab | undefined; @@ -82,7 +82,7 @@ export class ExtHostEditorTabs implements IExtHostEditorTabs { } return extHostTab; }); - this._tabGroups.all.push(Object.freeze({ + this._tabGroups.groups.push(Object.freeze({ isActive: group.isActive, viewColumn: typeConverters.ViewColumn.to(group.viewColumn), activeTab, @@ -93,7 +93,7 @@ export class ExtHostEditorTabs implements IExtHostEditorTabs { if (group.isActive) { activeGroupFound = true; const oldActiveTabGroup = this._tabGroups.activeTabGroup; - this._tabGroups.activeTabGroup = this._tabGroups.all[this._tabGroups.all.length - 1]; + this._tabGroups.activeTabGroup = this._tabGroups.groups[this._tabGroups.groups.length - 1]; // Diff the old and current active group to decide if we should fire a change event if (this.groupDiff(oldActiveTabGroup, this._tabGroups.activeTabGroup)) { this._onDidChangeActiveTabGroup.fire(this._tabGroups.activeTabGroup); diff --git a/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts b/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts index ed27b7b6dec..3a6be40a699 100644 --- a/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts +++ b/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts @@ -21,7 +21,7 @@ suite('ExtHostEditorTabs', function () { }) ); - assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 0); + assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 0); assert.strictEqual(extHostEditorTabs.tabGroups.activeTabGroup, undefined); }); @@ -50,8 +50,8 @@ suite('ExtHostEditorTabs', function () { tabs: [tab], activeTab: { ...tab } }]); - assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 1); - const [first] = extHostEditorTabs.tabGroups.all; + assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1); + const [first] = extHostEditorTabs.tabGroups.groups; assert.ok(first.activeTab); assert.strictEqual(first.tabs.indexOf(first.activeTab), 0); @@ -63,8 +63,8 @@ suite('ExtHostEditorTabs', function () { tabs: [tab], activeTab: undefined! // TODO@lramos15 unused }]); - assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 1); - const [first] = extHostEditorTabs.tabGroups.all; + assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1); + const [first] = extHostEditorTabs.tabGroups.groups; assert.ok(first.activeTab); assert.strictEqual(first.tabs.indexOf(first.activeTab), 0); } @@ -84,8 +84,8 @@ suite('ExtHostEditorTabs', function () { tabs: [], activeTab: undefined }]); - assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 1); - const [first] = extHostEditorTabs.tabGroups.all; + assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1); + const [first] = extHostEditorTabs.tabGroups.groups; assert.strictEqual(first.activeTab, undefined); assert.strictEqual(first.tabs.length, 0); }); @@ -101,7 +101,7 @@ suite('ExtHostEditorTabs', function () { extHostEditorTabs.tabGroups.onDidChangeTabGroup(() => count++); - assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 0); + assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 0); assert.strictEqual(extHostEditorTabs.tabGroups.activeTabGroup, undefined); assert.strictEqual(count, 0); extHostEditorTabs.$acceptEditorTabModel([{ @@ -113,7 +113,7 @@ suite('ExtHostEditorTabs', function () { }]); assert.ok(extHostEditorTabs.tabGroups.activeTabGroup); const activeTabGroup: IEditorTabGroup = extHostEditorTabs.tabGroups.activeTabGroup; - assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 1); + assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1); assert.strictEqual(activeTabGroup.tabs.length, 0); assert.strictEqual(count, 1); }); @@ -143,8 +143,8 @@ suite('ExtHostEditorTabs', function () { tabs: [tab], activeTab: { ...tab } }]); - assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 1); - const [first] = extHostEditorTabs.tabGroups.all; + assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1); + const [first] = extHostEditorTabs.tabGroups.groups; assert.ok(first.activeTab); assert.strictEqual(first.tabs.indexOf(first.activeTab), 0); assert.strictEqual(first.activeTab, first.tabs[0]); @@ -166,7 +166,7 @@ suite('ExtHostEditorTabs', function () { }); - assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 0); + assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 0); assert.strictEqual(extHostEditorTabs.tabGroups.activeTabGroup, undefined); assert.strictEqual(count, 0); const tabModel = [{ @@ -240,7 +240,7 @@ suite('ExtHostEditorTabs', function () { tabs: [tabDto], activeTab: undefined // NOT needed }]); - let all = extHostEditorTabs.tabGroups.all.map(group => group.tabs).flat(); + let all = extHostEditorTabs.tabGroups.groups.map(group => group.tabs).flat(); assert.strictEqual(all.length, 1); const apiTab1 = all[0]; assert.strictEqual(apiTab1.resource?.toString(), URI.revive(tabDto.resource)?.toString()); @@ -258,7 +258,7 @@ suite('ExtHostEditorTabs', function () { activeTab: undefined // NOT needed }]); - all = extHostEditorTabs.tabGroups.all.map(group => group.tabs).flat(); + all = extHostEditorTabs.tabGroups.groups.map(group => group.tabs).flat(); assert.strictEqual(all.length, 1); const apiTab2 = all[0]; assert.strictEqual(apiTab2.resource?.toString(), URI.revive(tabDto.resource)?.toString()); diff --git a/src/vscode-dts/vscode.proposed.tabs.d.ts b/src/vscode-dts/vscode.proposed.tabs.d.ts index 292dfb2d6dc..7cc8d4acbf8 100644 --- a/src/vscode-dts/vscode.proposed.tabs.d.ts +++ b/src/vscode-dts/vscode.proposed.tabs.d.ts @@ -99,8 +99,7 @@ declare module 'vscode' { /** * All the groups within the group container */ - // TODO@API rename to groups - readonly all: TabGroup[]; + readonly groups: TabGroup[]; /** * The currently active group From 2959fcde6aa9ff2058ad13cef8a5265ddb5f58a4 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 14 Mar 2022 19:07:36 +0100 Subject: [PATCH 159/175] Fixes #143567: Use directly language ids --- .../common/services/languagesAssociations.ts | 45 +++++++++++++------ .../common/services/languagesRegistry.ts | 6 +-- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/vs/editor/common/services/languagesAssociations.ts b/src/vs/editor/common/services/languagesAssociations.ts index 58ad7c3719c..4912ff8c7cf 100644 --- a/src/vs/editor/common/services/languagesAssociations.ts +++ b/src/vs/editor/common/services/languagesAssociations.ts @@ -10,6 +10,7 @@ import { basename, posix } from 'vs/base/common/path'; import { DataUri } from 'vs/base/common/resources'; import { startsWithUTF8BOM } from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; +import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry'; export interface ILanguageAssociation { readonly id: string; @@ -119,11 +120,27 @@ export function clearConfiguredLanguageAssociations(): void { userRegisteredAssociations = []; } +interface IdAndMime { + id: string; + mime: string; +} + /** * Given a file, return the best matching mime types for it * based on the registered language associations. */ export function getMimeTypes(resource: URI | null, firstLine?: string): string[] { + return getAssociations(resource, firstLine).map(item => item.mime); +} + +/** + * @see `getMimeTypes` + */ +export function getLanguageIds(resource: URI | null, firstLine?: string): string[] { + return getAssociations(resource, firstLine).map(item => item.id); +} + +function getAssociations(resource: URI | null, firstLine?: string): IdAndMime[] { let path: string | undefined; if (resource) { switch (resource.scheme) { @@ -141,7 +158,7 @@ export function getMimeTypes(resource: URI | null, firstLine?: string): string[] } if (!path) { - return [Mimes.unknown]; + return [{ id: 'unknown', mime: Mimes.unknown }]; } path = path.toLowerCase(); @@ -149,29 +166,29 @@ export function getMimeTypes(resource: URI | null, firstLine?: string): string[] const filename = basename(path); // 1.) User configured mappings have highest priority - const configuredLanguage = getMimeByPath(path, filename, userRegisteredAssociations); + const configuredLanguage = getAssociationByPath(path, filename, userRegisteredAssociations); if (configuredLanguage) { - return [configuredLanguage, Mimes.text]; + return [configuredLanguage, { id: PLAINTEXT_LANGUAGE_ID, mime: Mimes.text }]; } // 2.) Registered mappings have middle priority - const registeredLanguage = getMimeByPath(path, filename, nonUserRegisteredAssociations); + const registeredLanguage = getAssociationByPath(path, filename, nonUserRegisteredAssociations); if (registeredLanguage) { - return [registeredLanguage, Mimes.text]; + return [registeredLanguage, { id: PLAINTEXT_LANGUAGE_ID, mime: Mimes.text }]; } // 3.) Firstline has lowest priority if (firstLine) { - const firstlineLanguage = getMimeByFirstline(firstLine); + const firstlineLanguage = getAssociationByFirstline(firstLine); if (firstlineLanguage) { - return [firstlineLanguage, Mimes.text]; + return [firstlineLanguage, { id: PLAINTEXT_LANGUAGE_ID, mime: Mimes.text }]; } } - return [Mimes.unknown]; + return [{ id: 'unknown', mime: Mimes.unknown }]; } -function getMimeByPath(path: string, filename: string, associations: ILanguageAssociationItem[]): string | undefined { +function getAssociationByPath(path: string, filename: string, associations: ILanguageAssociationItem[]): ILanguageAssociationItem | undefined { let filenameMatch: ILanguageAssociationItem | undefined = undefined; let patternMatch: ILanguageAssociationItem | undefined = undefined; let extensionMatch: ILanguageAssociationItem | undefined = undefined; @@ -209,23 +226,23 @@ function getMimeByPath(path: string, filename: string, associations: ILanguageAs // 1.) Exact name match has second highest priority if (filenameMatch) { - return filenameMatch.mime; + return filenameMatch; } // 2.) Match on pattern if (patternMatch) { - return patternMatch.mime; + return patternMatch; } // 3.) Match on extension comes next if (extensionMatch) { - return extensionMatch.mime; + return extensionMatch; } return undefined; } -function getMimeByFirstline(firstLine: string): string | undefined { +function getAssociationByFirstline(firstLine: string): ILanguageAssociationItem | undefined { if (startsWithUTF8BOM(firstLine)) { firstLine = firstLine.substr(1); } @@ -242,7 +259,7 @@ function getMimeByFirstline(firstLine: string): string | undefined { const matches = firstLine.match(association.firstline); if (matches && matches.length > 0) { - return association.mime; + return association; } } } diff --git a/src/vs/editor/common/services/languagesRegistry.ts b/src/vs/editor/common/services/languagesRegistry.ts index 138fe2e8bb5..01b58ce512c 100644 --- a/src/vs/editor/common/services/languagesRegistry.ts +++ b/src/vs/editor/common/services/languagesRegistry.ts @@ -3,12 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { coalesce } from 'vs/base/common/arrays'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { compareIgnoreCase, regExpLeadsToEndlessLoop } from 'vs/base/common/strings'; -import { clearPlatformLanguageAssociations, getMimeTypes, registerPlatformLanguageAssociation } from 'vs/editor/common/services/languagesAssociations'; +import { clearPlatformLanguageAssociations, getLanguageIds, registerPlatformLanguageAssociation } from 'vs/editor/common/services/languagesAssociations'; import { URI } from 'vs/base/common/uri'; import { ILanguageIdCodec, LanguageId } from 'vs/editor/common/languages'; import { ModesRegistry, PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry'; @@ -362,7 +361,6 @@ export class LanguagesRegistry extends Disposable { if (!resource && !firstLine) { return []; } - const mimeTypes = getMimeTypes(resource, firstLine); - return coalesce(mimeTypes.map(mimeType => this.getLanguageIdByMimeType(mimeType))); + return getLanguageIds(resource, firstLine); } } From 4483c082e86087b1fc664eafb5008e94742e2c83 Mon Sep 17 00:00:00 2001 From: David Dossett Date: Mon, 14 Mar 2022 11:21:22 -0700 Subject: [PATCH 160/175] Fix #145067 --- .../common/media/dark.png | Bin 14165 -> 2277 bytes .../common/media/light.png | Bin 14341 -> 2225 bytes .../common/media/monokai.png | Bin 14287 -> 2256 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/common/media/dark.png b/src/vs/workbench/contrib/welcomeGettingStarted/common/media/dark.png index bac2bc8d2d80329b01a1906e0266b503b46bc4f6..67ad6fcbd35fb0c87f7c4c2c1b829f6eb1c0aa73 100644 GIT binary patch literal 2277 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV4T3g1{AUTd{GrhaTa()7BevDc!MzGQrl@O zfr5<1LGDfr>(0r%1aer?9eo`c7&i8E|4C$JVBo0oba4!+V0?R5u}`H`qW$4|Px+Mh z0l6Mwy-LdN0tOi(TzivDxmu4o2q>$s*f_)X$h?KON>-*lJ$1IN#PGLW{~F;vKbL;` z%fCK;|2{qj2FZ9{1_n(g0R{y(1}26h91aW(5{w)S0?G`G3`r~s3=TaEEDRlj4Gav1 zLrl?`hrbRUm-kzKxxo5$mE4M3+fFkSRErHR|2?y?uKxb+?wgk-R=gL!9Pi)He?V^E z|F`WoC$kcWk(+<{6b{6F+jp3CgE%+cqN#Y!+_`?s85tgw>7b;DH~;v7uDNHkU;al( z{`)xI8ckGr%wz?Lojqr(qiG*GeakOrGBCW@Kq!G9XYBa(d3iqjj^6imf3tu5C#a!4 zHFDkIylY==0=DK(XMFIDkf({tOJ@qpzJ2&$P+e71Bg4=jL`LN9-p|UjVfymr%NwV^ z`uDHyL2)FZ%v{dUs8fEWL5mE_XcPtvi}uxh{?1U-SAVb0Sbrv=>|m*Lx=6Nc^SbAa zt8#bqFl-Y&0}A+?X3~Rop~s} zopJX*Q(Z;H3|m_}J3a=7P83O+merPg4p%N;zI@>MuKoMvD^?Op-DeUbr@h`VyVRCH zB=>eI!wy?AQWN#+7+_|u`uwNv!P1KA?^zG_ClN{ze5W_XwBKFxx^h9*Z9V1#Zwcm^ j;ZaKxRV0BG{S*(E%o5q8+4ddSDq-++^>bP0l+XkKzz*ko literal 14165 zcmeHtcT^MW+HVpP2q0al0+Av}7ZjuiDT1_!AVp~^AiYRaT7ndn4k{`w*g%n@fJjG? zjUot2=v7dV(0eEMji6iixqsZX&bsG(=R2FVhMCN~<>}Awd1kI*435#!aMC~^5IP-g z4I>BymJNYG^N^I_&Kc^3UI>Jy$5CA!qob~l!g#scJG$6GAllb%CR1UOx>&K(q%1k4 zfQCY*oSFjkL0Ah+SexnuwGJxtO?>EeOY<|Yit&7*do1^yC=kGQV53cl94059s*^0FTO5}QaUN|zuY&`b46#y)Y(iC4)AbU_-Mi61|F!QmH>vvX@SH_4dN>-2V z)~|8y35++BX!e37L4Afo?v>>XyLTwh49%|4WgGTT)LsqTg?OIxF!Q5J@w9J3 zH}E#X%-3;=nTLc~64A#mFcmS2;Erd~T#z%S;|@1KkK#o!R11v6(6!8x76*1jlC6RZ z{Pe4nHmr>i{DVjQSyQP;Um-m9Rj^7#<_xNPPz2IfQ4WMFem0$9q`_+oQ#S1Wianco zBwN^+Mub98U0iL?{RWIlwuQ0G6FMKRwriZ|prhwL9y-J_iCt2Q%pCq0=*@GP`Z8S^ zEC|wvt-@BtOdVyoS8XfIt{$!Y2Ul&KfUWewc`41?(v2#5$|HOu5|60nd7|p13);;L zUD#zgQo=2-T3+dk&8>Z5qgc?_xod-w8rBs+{SkHCEFvY0y@bOncZ<1#A z`?CciRS=S|@@tYmGYmBkx_=Ist%ZxcN*vU`%7;YKBFB*d)JdM?`)+qf?)@#dG}FPmRj z=hWvEX~NHHQsWeJFEiBFfmnUx(*(`~+&+``b>Gj>IxTft3%T4CNt#K&OV zTN<-VlrlM?)~x=>A1~`yl-^xn4oLL)MARuxa?@YKJL9?Vq6G2w+}6sRb@RB#Y)_MO zOVsjDOg~n!7%&Kl*izc$USnIN+Vzc6g);EU*(>KL<96AqE7r2thDQYK%IBiz;NS}9 z)QNe)nI^|6WzSBKt3DLof3doHGV>$F&pn5voi zX+ewJ=T1e$!uH}33pTS3Gu3CAohvFF=JGTA$+;d|3pZo)Qz zA>i4j?|SUJ+wZKB1e0?15BQ-J3%KXFo%WXP<%ms)72V6lZEg7McA~Uh?Tr@)22y*| zyi%7GlzrQM>HVxe_fBlI*L?_|HX8G)zd6J?R7NO%w-}RBnbP7K*+b!Xcm2?^$yDx? zwX%}(d7fgP&2-ju$Mhbh>B4VMFSK*E+et>7;yaA;Pg-SEC|B(1udfJM_MCaQB>$~d zuI=&@4`To0zAF1FrGdVxv|zpJL)DhSX&W*6>PJxM9zc$#>rG#}db4PN1%H6(1xz7WsHv zExhCCP5u|OP}~0 z9n$^!M=I3J!(1}x$v|;t|~uYipYlo5j%n z(D+bZwtH-IY%e6FEsFwAbevrp>eIywj_Fz?-<1?U(_JX$-G%%5=4;pc5UbBc_q^+P zMOjQ`**Nz|h)!%tER^5ni{Uf>xM`x2;~N~eWwjBs?$ptC+B8Izb+@&+r^o@()#nk_ zBSeM|sy9e@i?-$H zwgpK9Wv!{NxmTsGJ|Dfg&^Ckq=x$N%8sIv=mNh^TT&;5ZQ0KhXlGdVclVYXcI>}@G zzK`(bZ(ZxX%eB1MRf$1LGuIX$PhK1v?f-nq+QYh`x;xl)i*JJ;lP7*!kiomq6_JyVBT90Nt(W=gRN#0)cb7a~ zrgL9n4xXgNDiG5wNr8FMO&cM^*=f#b<3Y-;JQ9NT0Z(&!lKw@2cCXu+>DcS*Lqxze z5(0;ELJ;5z3Jw)0*UxJ$s4#@$`+XP$66pwm?~E}3XYyY>ILLFh&lHIf5GwGC865t2 z*pJb$Y&^w}YiJ&L1_4PyM+clwp7XM^bGvxK-JAZvUVz3S)E?UAfI3z|@&VN`5|{z& zw>uh}d7J6$DV%e6m9RbUe%4OH-_?V>4n)ac0bIJ;dE27=U0vKRD)=k&eIKC!uF1D0 z`B2}7csncendxIt>h4~4C|L<92`N4m8Wakp9q5A{BtL_i#u!q1|`W)Bo9hRN&Z|LOjRP^Rlqp<+qsx)IJyFv zfjv|X$w(=EAO8%wL}Tb*9NhJ1=#2SFokG%Ae}m+4k3mI}?>8 z$(;WpiES}|zYFB7LZc-4Q)enP5_G$(fg1NZY8V=WGcdC6e;wezFgVC(aO_SQdo#rg z&JH>nYR3N1iQeiQK|hZA+0yXiXXNS zv4204nx2tBxLN_NK-vK@=9aUx=OhK*@*M~(5c5yEnUiAnCGbwbbYrTbOoqdhC~8G{ zIrWZ%RWsII%xk7aoq^l3!vEPk0~7{FGNRB}2(B2Rvb8ciHJEUWN4_j@b*{VcrRtwg zr)n8gcW3ug{2aa)io07#oAiAydDw;_8h@E?doA$$9vtpOP}rr8g>0{Z!c;#3K zfWZzsaYyU}+kSt_nBBiUicE(v6vtUiU;A@mr1A958fYx~1{NJ-5o!B#8~78yA3LB? z$I*DL+*+xh+rZisf9!x_6hvX}x7)J+pdX4Oa+BHqzVB6L#_SX0QoDW-fkiLU|J+}L z8cE3ZVUPGh1Yncu=l*}Q`5&jvK-TOy<)zM#h0QAEGM%)N6)k;bKF*^uk#>lw-qO~- z()kQKccL5oI!)l(n2@HBoGjTaieM$~15@E~n6Pmp|Tjj)WBm2qb%mc-BUrC%vK0)&h)6JxfCtepX%U>6Hxc5Nyv=@!~D zwU>^T7D;&hUPb||bQ!oB!|~V0V25pK?X&q%m>ideRNw^c`%#!kdGRfAT-lLQE>>2? z?C@j@ zU4-U#`iZb+uBAMvvcxmAmMOk*kZb5Nb&kR zzmPN9P1(Q_JNNicHI4eJn$7NJ$&ORq@?UNc&3~#ryP7+2c|3P&ZE-xOc^}5q8V9AJ z7Jw6j*rvzR*SF@w3DL)a30UGBg69{es6^A@PFEx`T#UzH2w*ulL5>6n&L22xAs>l> zC~=)c<hck$BRVKSOvdUGg8^sj07yEF;xoM|)mQH{SKB`^4-aWFrWn%3W6?+P ztTxhoVBrSf+4d%|VyLG81`WK?ERl)q*GJKKS+l?I{_mCpN(5say!w^te)D`=$v|*< zdGO|%5*x2)TWxLa)XYp0Q}v7qY}6EuPao(D@Pff#9AIS0_PZo$T~$#wmwURTtej-N z&WkHsqU^0s1R=giyby%=L2q0(S~;k9ex43@IoNknXPJ#Ld!4Hc2COX+_|7NUDyb;+ zCM<$Rt>o-unlaI$}@AuhN|-^Q@`dJS*L^7xcBX`^0b+4m&O8H_KM^Jv^e5D!YJ>~G-* z6Oya8Vx}D2Hy%4E@G{-rKhxtpFut|bQLVTB%$iA90)0>{BWuJ2~dPH;X*NCz3l5UnaH4kmR7{i`S8ZlE_m&%0}^u|IiK!yCMM zl63d+-5i-k4&cc$=+t3mm=C>4NADBh<8E#37nwlPrGw(iBG#}0Gz6%2)zLu`4Az!I zMjEal^t1%g5L)WkMU4Oy&a1F_o zQ3p>w0I2#*R3->8Qs!v9!K0MrNSKe6wdueuEV{2tf=_VE&r-~&PQJV^d`-1>QG2$zB^gH8jv zpI%=$1ZV_QOp^_UY%Fl6FBZEr0Xy%&bLqYcP<70&m94!15%1( zlLkq6Tg-kPFq4FU6VI1j3K7PPF8VBzMd3Qx+6q8CprVT6SB38e%cPv>2s@`EdLBr@J9^Lcpjm`xzT^+Cb%$k z<*2ANv1&fo{g#)E7;b+5%t!{wx1XnUVjh@p8}+tCQTs5{<;zExH)KrtgMdlYjKT~_ z#AV^@Wb4x08MI^PL%=?JkH>Or<9T!or+DGSvaKmAVC(JO$&S=dfyO!#c|)vm3jHn# z)<}Zp?Y{H;K(PE#3+!-vpj{b?jL%;YM2@rRUmwDW=1yhp?ZBSezdlkUNQQ-C%Ze#iwkOLCS6;ab4bPMpaJHpk~Rglse+h_kX=NAY_YvvaS?Kw&{Z zIfjDsGPt{?$p*i<1EUZMGknTx0u5Uln(j_d16YkNac5y|B%xf7L1_jJ73XK}G#p%- z?CI+xtwh$O0uDaz*_XuJZzN)TY&gu8;tH6>4#gm4L(LxFg!Uk~1X=BA za~||c*oi%Au$Drp*|liyDtCyIXYLB`3!tuOUQ8cP9SBNmMt26uj+Qq2gyad$xXPMN zS1$KA4cEsRE^m&$OA^X*Xio22X3t`iv`S4^4GEsUc*fc~BQHP1clshbwuTahLF-hn#g<0^zD*zOzNYoH=uLG?Ix+9e<3b4hqN2!!hP}~~!*5ng7 zQVD2`v&{alh{O&U^rP{h6ZoYyg&+W=(uxgBwh_iAA;nX3;~qBjMjACN>aNiS?~d4tw<)xLQq zR13iT<>6^0GK7vq4+etzrRrve0NUmeP*-Wk%hS|^mp9pkL0^kfvi<@b*?SF(u4J*V z*1)e(B2y(%nC6nXBsj7WR1z}FoPMG>&Jtz{1TdMwuk0}poFWJ$ey=Bzk;VfM+&lmj ztEYk!A-Fq0zav(|Zh`;+oWZSs}RkklpKqSaXos9%r?fJdX_`huh^1j?a;O0W#^p@3w zxJ;xTv zzGA(O^?T^aMV~b>P%=AbxPe*|cN-nF@a^Lm$f3(s3HjAqYYTH<-v?x<N5 zDP1tvBG-o;u!FcY{Zy5JrHSZ-fRHbBQEXYG%^AyEi82Ok*$${xCYUN{;;0}%(r5%l z;(HauKPE>wF%)#r8ROuxAgOX~L);?(?XrpC%CP%X7cft5yA|mH^0I^(%m+HFZ9@U(y-JMM2E0)K&A<9*^ZDN- z|MOA?I5$5pPqsyRC=VtlCs!T|`gM`OPmb>2F$Q4kS%w+uDr?{F(-lR(%&Bq62=ZN9 zXf^cX9_WSB12_`?L+Kz$@P=&6Qd(&BnhYixs>lb;C#%AFLIE6mA@-YXv4NBsMa@k% zV#`~mlwV*Y^_fZDE7TimNXpDAO?|2tEyBitw|GA^)u_#F8kscv)wCZ z{}=;r#(Q7Cj}M>$r43t_`_^1!jXEQEvk{36`VtFUym~7m=o={P*IN7rw}9in)CVyk zQ8p#VpMmt&k|9)IJ=?cU^nHSqnX5drA!o0=x5MDTeefCR0X zA8-dve$h*q8sx@Zrg|G(#|~0a&}P$s!sh3JjZOBGZ2M+taUrYa)kiivs!2VPJexv0 z05)(V8A%wn@ArR6w&In^0r}0Zsv%n*$%7;35L-(ORYI70H@W4rAd$)an#>4{AbFin zNU>B0oiDv#yI-83M-VCIRp<;FdEvk1S9Op;;x*lT>3|nV{ptx$05fnuf7_I|4`gbP zvH$Et(*cyN&RW`a7!*~ne=V%C_kpbPmQSuc0_6Q4?;?y~i_4^q``WzfOfNMCGq%fQxKN0W|P`=fwgI(uw%SZ^0O2T9DgW`0rk_SZx_z(zy1pum$ zppH>{FGchH2f1}PCV&Y-fCt;(`2FJthgCmDf)5UHB#NjoeZK;zB_sJOO&v`Gjl82a Gq5lURohw@a diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/common/media/light.png b/src/vs/workbench/contrib/welcomeGettingStarted/common/media/light.png index 81aa74dc4de3356a4e08f2c718061dfe20bd7f9b..14a472108e510fd1908ca64fe17e5b491506d970 100644 GIT binary patch literal 2225 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV4T3g1{AUTd{GrhaTa()7BevDc!MzGQrl@O zfr5<1LGDfr>(0r%1aer?9eo`c7&i8E|4C$JVBm1`ba4!+V0?RbWA0rx5x0k@XDn@4 zQnV|aL$Z-Oqxr$rn@2zBt?bNE;9VfN$stCSS;8kbv@M}~+PUwgPgvOPJ5E0>+9|`# z;Bd?zNOUoBwp+SO?gF!%< zfsrAJMS;Pg2d;@}uq&GJ^=0?%+qd=SZO@h7H^05Ty>Zp-*|QlRJdGS&o|#eV_wC0I zi}YLDavPTIzxUUcA^peS&-uk_+yuhA_?N6h!{#})?c5J^#OM}NX>%v%-Zo=k*dv4L zzUB4I90k+L_t(h$h?@WZufd0~2twgp&d{h+ez!pj)gbC6EMU66y^WWFA%8ld6dlQ~ z@ap{c_v{st^)A5ZMe={&l zAsA|y`O)%k`~ima$Z4q$wp#TiKiEl>>#eiMas7+a;sRd_BiZ7*`HvfZSW7UEfJ>IEv@2N%zz+4mVlWep|Src|aB%2sx%l(iVL z4N8%*@4Gqol(y&j$5D2T@ zp##St5Euahf#x#MfsxaUbG;Aexviw70=*ml4kmGk-iT2TdHZF2=v51|(=|nSkcqNa{jT@#uR*T4ubcRVu%maZ6xSYl6tY3FI%tkenuTJIZ8?f~v;3T)1bHD| z_WCXeT2O0jXm)GsmdY?Wi-@h4-TE2qW2ck192K@z^dgF*BEs@%A-?i);tg=@Sa@g3 z^4bwmwtajy;#bhpTE4t5f&;f0V&xJLN1B_`RbS9B^dL8mK_ooG%|=45rYt8fjgXhr zEbrf{TjARl7;lPd`Y5xc88;N7?-F}aEppq_HzH=HEO)%F%?8A)EA4Mem>V$~l;)0J ziFimi*liq_pEj{#xSm4HyP4CM z!}03UgMeWJqHI#W_?h}dVi9AwRt=ZNv}4Ev5lp)NEw0B4h@tR@<1=ff^Om$T?nlRB zPG;J0%c}XOX^Aq>9^qiWh=sj@u!lo-$3t%KSGL;S%3`1Ei93?E>zG{En;0(n=bV*; z=k7-(MkzpcEc%Qk`quGOBy$Xs!<}vSKq|$JCEMRJnlBkZV(&xIk23SS8e!OO=ISrU z1Mf+PG)4$5*FZ$x!9DTx(YSs2P_}AXUx+XVBvecJGRz&x+ejCPggrm>Wwu%*UtlYa zGhfJwZkx4uCk-36c7W$RJiB_I8{=sjr5cMV9?wvrDJGWCMQff=q`(2(`FNpoFthy& z@ystn*YMU7oL6xPw-qJ063~awZz<%I#2voPbY97rRq)bL^e|ouLqEqs4qdrj^3I-z zHql1K32t6<+?u;FV#k28FLxT_a1E{7_Hu4iWX^!L8%-cvC0+j|)sH4q98CB_5_I)j zzhKYYRwhUoGfC2jY0GGB%c{qmAe=H*c*yF--+qM;9kl=KdqqXAaqNOt|^mHGl0ZQ5*T)vvLP-$~S5pQ6CZ+LfxmI6^eQ# zpWk6>=)|*^H}#UmWs5LU?Bm*EYt?*G=XL?M?8t(;5B+t(4dvA$*WHO$o{Ei!1ZImbS+%6CSkzfvIqkMGs7rD0Ao`)f4I;KIisla z26JMsw-j7%xbo%YsZR$#aeY$dymC%wMx+UOMX%w|m%BUeHrz$Eia*`k72CKyJK_50 zqR;D}xo5OzRGBWFImn2=i`kk~l;l|NSFcd7%X%v!i_SzF|HL@!SeDk{jn@|pLhs+( zY3@;MhqFr=a&O|lMPm$WzgmBLhM-TlPUIr461U6Tx>0a4>11vP-{Y`TCWR}7?%gN5 zYr0|M`^VM0hl|P_ByR1C(H?9&*}Bk*YW4qWTDm7)zvWKyJNCAokua5R6&Dpom02%I zucM=$@)#B=y5wuMrgh4%pVcj?y*AU0~Rmu(Nb=EH>JzwLG<#A_7?Q_}O@Q z`7iP5#T4_UEAh$M@zC?w^Sa7wob7epuQ08!CDloO--Vfk2es!EJZ^qzWNy?tuH7bg z{N9L5n|GUy!i56gf^BwQc7{z?hNNd%W(|fO4~22>TpVug1Q;`PMQ~EHP(izYkJ1UvNgyQJ_?SH}+brlmNe=mEn_{3G%kJNyWSR z(|Xe{rY)$bdv|!V`B;AJ9b4;o)qH94*vQ4Y>!0{Ol@g2I&c~!yq`q^G?4j|wwW_#y zV&d_HmAabxIiVt<^$hL|hm0Pz$%3zs&Uf&2*vdwm;6EJ8J8qd-u3o;audX~~(S7Re z!oIIsI-th!(aSQzpLvC@UdjrQfk1gC|X=2HE?q_HCFu>7>Tw&HxFw{~iZyw^^Jl5u+ zI6O5ZU|4%s?7rZU)fZ8pPE1F%J|F36rC%1<;NFnZ!dfTdt-eZ0Z(FcivP-g?vt6-s zX&gf=N7WyoITQPA|JqI|=?nH9kz<6h^{$6$FVjj-2fCb^V7yW+YJSlsce;1kL-p=L ztB8YrhELy6xt3YDQ>H*dOM=p_uW#_477kf!N4u_1CR?RY+$~>}56%`1=?__1S(jMP zhxUcWhYBO^AZ8H7D0z#*K%)<57Cw>m@nR$Tr;=~U%AD>lkoN4teR=t%t0BblW8odo zSHeqRmTOu(cX7ATeXykYY$8A`y1+6-MXg4cKJCF3r+OKSOP zMAZ<{>Ft z7hBa5juMFy&l|col$?t?OM^#~nT%eM>Z|KZog;cqx~}G1hB(_M%UNCR{?M$}weBsI`I)aT> zt#uaRNx`n?4+ak`UFopP99l_?6<^GhS3lu*YIv?x;ibYQdt-a%X11b3=5)=r8KW-g zZ7WNGt;?ziyVK{Zc-*IF?#1g5_jEej%dT2#c)eP!zmoGPC+34%?w->=RhE>3)t32j zp>b9vHCIK_TxnPD?xMj)8H)L^3q7gQGcsVfn>6C1I`OJMz)f>Lc$lUptTJ*Rd%s$J zh~k=W7guBAr)*-jZ3|20iS;w9`WD%`!y~!)+|ib^nVJ(rK2<9xHb#>(ULcYXwiP=o z+JjI**(=&Bu9a!aPlvD1wNIhnyPm3Y4sf1b$?m5KuF|-v*g31Spfm5?q*~##N^x7w z@{;iX+O^udSSx&0lN_Wrb!Gm+xW}jAzK?!ZZdUbG-NDWq+|%P%Bu(xm%$zHKZv?p{ zt-ONS(z8YC$G(6AKUaH3l>wssKdA>E|glM`-%p8>Of4iP8v5P7TMs)3%Lb_ zL`NTVheEu)PUM9|snxdIN^|q3pmqzNc<7@88Mp;ql05z(q9n)IYEk5s1{^Qu>Xa+I zku(^?35dXg{Ncz|vrmqN>YSEwZ;(ZBLWpS@^n>*8_V)stIKz1COQT7 z?{F|S^)xj&qH@;N8D(?M^^7gb*V&D_4@AvZ1w1<2dfFg;ot<1fRD9J%zO7IJ&(vXA z5#+Zeo)^?bObswdZP$yo$h{~zl$?kL6B3D3yLiq{<=6q8&DX(y>LTYoJ>67fWqo{n zP(BJM*NgVDyZ7zeCo3l}D=#ktR>*kxxp><6%D8y!_`b=HeGb@qoW1Da=IP+-f~4+i zbH>%nQ(Z)aO6ce3JD;|`4!*1MZvX)jneJ$v+eQYRa?)4gjEPWzv~yUnxbqUEsuGF?p6(81 zgs^Q-pBXcgCGWjc*(zz=8>UZR*CV2J`j#o5(aQ@i1I7F1)h5-4KR5XWw>;0pDo%Rz zFRD{!mxVv;N0jaJ7;4lSW{1My3>-)_7J}oz#h_Wc!gqiF7mT|w_A(KNGXmJ?e=Q=z z@~SrceWWn`L5n1EEe{s5IX7^QSwKL*6CrE4l_0*l+img3wgOPxtpeu6Z#1ZDd$)2B zglK+Jm4M>-ir8v@PBR#{{MZtUPQs#NPDR@M<99%bXkpqft4QP0q1c^gPQ?`Ue;phy*X5h#yR#@&0r_ z>ED6F9f>L|+CRu3G3qow=^MdddmIHLw*Mf*LCE+)0fPJYnE!FwtUw1%RxJA0R;-Y7 zNbNZ$0rr;CQf?Ey&nHssGt3t51g4OVfqU4z>4VrWys;yYiNV+2(wl& zz7o->3kbWzU|wm*i+mV~j&rD9JQnTj=Ag3^jjaYwC5YBj;Uwtw$my42(FXnT%fOA~ zj-v6g9uF5#xKlBGm-s;_U_~{(0fOV<;2_XQ=;^}tIPlx)Avg#l{PMzp@N3|X?nm4E z#4tJU%iO|Xu%eoKyeU8yG=MThY~&Drr*p0J2yne1?V%ljurd%u^Mmd(xZ@swgbN0Z z-}_8)2N#e98jWYeiwZIl?>gTUvq0nTyS@pe5*9~d>h_%oNJc-_nS8;@#6YA=wmS!8 z!NR~mgeKkH@vjp8ZzzF-myp_I*E{F4Y!RtkL}4Iy^SiCzfS-XCZBV=l3-=aqBI9>* z#M`*z{8#2iCa#-UKB#;cr?El^_;?BNuw^?YC$Ad9%6Jz}7M2Zq7qs?)q9|%_4AdAX zIkjY1*%|cl{qam8<0bRcc#WljFp{}z#R=S94{keZ??R__A{auwA&7 zvbv2{(h>&0cNNK-R;|bVY&kExe`!9sOjg~!^kFDkW{Q~zi#`jh0e0uRPiF@j&kD@0 zT$~cx?K3S)2x8A;a00H>~&# ziYqm!YoYqqeqiA{7>Sip={8R5d4o zmZuIL3S!XI#b~M!89`9Miv7#*{}Bn}-k^hKo0P&OUAk35zxB? z^8q?Xzuv?}E}Z|2_eAV4Fsfy54LzVaQIM$$V{m35w_M!;qXpUpCIiM_17lly0j|(! zgjhT$fu7z-I>OqtCnt30wwD4k-t1|-T>`5E+9}EZRdS`NJ*(mdKMOJ|& zs?o+F3~7KTzDj3sAqNkBhk|zW!1?GeSKiU1PVN0?O@V-?R5hEET4hJBmEf-}l*}Iq z-e`06LR79_Kj~WC3%3J@Fmq}MI)q2rj~^aqz6*C;O_-npSTEp07L>DjC`_E#3>_>J z__CqI+9fb!08}(J&q$o2<(2(~vTw>DG4^dTvs$>)=z^R_+Gu?4*|>>NupYK&jhBP) zky+mI7hsn&N8_9Cn-7J-ym;+R%p$R9i#j0^EeIMwuL?*^E#h4HFHme<40LKx(nwEB zmT%5|$_9d3ta>Rk2qu6Ndo(^m_Koi^d|mAXqGPH{3Of_gHqF9T5a>rRz!L$C4RFx{ zVvAM$^e?E6>jLw8N%F#52@T3+^(r99sw{j(f#3tU$fWA@r>d!_zkn7_b}F^ikN{@m zeccN%;5GK%0@Me93r!l>o zf7T+6AaoXt+*rn=Enat>=-7_Le0ZYkqXo2qZfbgAcqpRf{6 ze%hDY0p#c$5OQA}q>yW9S&Xpn04~de!n%cnusupnhYN(tD|>hoz%lCp(m8vDT&acc znD?1423j#+m6rkPISkf_a$Q7Ww7G4fcY<-Q3-Y31Ja!ugp^mdXC=C60bdu~0%&K_7 z_7u=i5?G_R^YdwZg!Bs@10b)R9p?^#aRDhLu&jrxbhuL=`rCVe%$&y?3aJqRyqj?3 z&2u!XS@`Z-Kx77w-o}G*<&$W-!+ebE>XKblr;*ESwRp(hPbluf=Q`Rgl5V`@vpzS|fs3BBILWi{@y zw(e@Q7nElMhpgMwS0gpOGDDU=X3<{yb?GDY{ zLSQ~qW;_cxSl(6&g)sxM(#B6Nal+~;8+#(=>n-PxQSRQgz_oi z!=+Zy6_qW;S}9zw!~omgzG>fg;f`CcQY-0q0Hw29-THsuN&Y!e=`u6%c=k~*L-l#% z`KI1y?pXn=<0UyiK`R3>;)X31t2zNUr4{)97&rmw{hHs^^Fyu$^9^}EoGMqR(_T_v zU*BU2sY_{D5oZJ9{#fe|TnJXb*%9Zty1H6(OlODNFif^;?c!pqzAR}Ou}t^9Li{py z=y%ZCO$O1Qe3H*g8&;Ih_J^c%0ASBCcObGd5?`qN0Z1Q%qBYm$o{^F$hItfd=okDf zRso5s^tuiy9xd}o`@ca51S$1^g-2Ej+t$)}oRwgaxRp;)vJ*oMfy}rT;QK9Dfr_mJ zUCs@CydYRRuZrpMvpb?zc)1%upkcs#cx3+T8Y+>$lKh4Z6US%CM zvNzw_{tyR$jmSOg3l9`7-Mc@_-dU8Q!SrAjAsTh}-D^e_WSE*=;TyUkRfWZr)qRV@ zDvMI>L*36OCYLLlFO{3QpTwau~T%c*#R72 zH<#Z5a$1Hg5`)lzc|iw%uRaDqIxYou1~X6G?i-)gdJ5{Rw)t`iOh8(?JV0{IomuAJAx_BOAWl60-l>UnO{)r49gUyfTZP?Qh zfHd+|aY`Yh*GWxlg*aMrn{j9cBN1=QBW4NeqP{rd2&8psw zugza3Tz6t>O(g!*&O4x-)S8xMWt@L=kI$kuz?iqsY^XtDi9kkoog?}W{(&&icr(zr z3d@{zhs~#zOin}su%`WL%@0)E06XdRuvA6;nZMBm0AtW;4iCb~`&|1;>;S7pUR|CA zwK#xIiN(CZh@UWk92e38;>^4aPee5@GSd>bsAF$Q zHNmy7x>d#NuU&%|5qBomghSXJmteF%>oOw=YPY+Z4HObft$)S3NnkW3claQ#dvGj? z7r4V~A<|~C!2j1`0RwQcZD|IA)-kT&xE=5_-T=={@bCIp@Q((fxiR7ozGhHwKAHkt z!G7$$%y%$f^*1nY3u?;yqkcvJsj1ph>&7R#CEvk0nCxnEPho)QZ@Dvrf}ER%~+$2}jANDExIzkhwYSbfD?zNl=A^0n$$3*`Qdb?-sa z;!)4avtA##VhS~Pz;y8_Yqj4yivplzN0|QK%-0+QW@%h0cKY|8r5h;jEkJjY zHu{e~Bn_2i{eM}eHhcezsOWz#W#HX!DK_)$xY4c8z^6HLu?Kz>RO$#R@a{L9b{9^j z7Y@u1nr}A&qCb)<0cGk_RfTTJ9sal^nfX|HX9H{c@u{-ZKDzP0qRph829<#VfJ z1uYA~tg~Fc_knJwz}jEB^;QI!O!2VhRuFLz4WKap1q;W|!(j90lY%8cn;Ugw$M0~j z`#ms+_Y&(E(CfC4{=`%Trm6?8`L511$Qo+YjrWw4tS(Mw2C~s`bcO-v z4qh3_?x~GrUqsuz7Gx@?Y^?U^3I`R|zKuCD@QU^mZ2pz5W}N0OOv~987e4`NG1Bb3 z#smOzGw5qXOj`a4PO$&P1o1Cs_)i5n=p%SbizbK{GptI|&3!tDGNj4%>?H8H$K|q= zLD>8k*7X<548XlLH@Y%i*h7}*m#fQ0%ouu?XRA70*5|VA-A$6!DnKG%XUo`!LkI1Q zqa;+b!$HW%3t99jj-)I!vD?kc!o6jtNEH8-f~w`Radyh*EDNjJsa4Q&`B=vJd-M7` z#O{3szLZ-6mGieRA-;8RZ|VW3Y~AbQP6g9DHv#pxUyIl!0BBj*WYG&?eBK|;!W2;? zM%>v0;j@MC@xp(D4E6YH(=El6jfEc2=jZU{#fgU;q!@0@FqawjfXF9byO!>2( zfZ+bE5I28Z^q*eR{>Rne|1$hgP(^L zSoD_r&5~zkW_YTGm0~5Px-aB8yH>3)YzcX9xaFqQRJ~MQV?|mj=)(>)!Yh|PMN!y^ z3S}jup#1v&!$LUoT0bR}Pc4)B3yJSz%|}2H)%C(68T52P&_>3irmFN()Or_3ALN79 PEJW|%(F3{rtwa9@81|s` diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/common/media/monokai.png b/src/vs/workbench/contrib/welcomeGettingStarted/common/media/monokai.png index ea0926178e0f8abd66e0665c996ed3b7cb8b942b..68c4aff78b1758eb620694bdda0607c4b8b4e43d 100644 GIT binary patch literal 2256 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV4T3g1{AUTd{GrhaTa()7BevDc!MzGQrl@O zfr5<1LGDfr>(0r%1aer?9eo`c7&i8E|4C$JVBkpgba4!+V0?RbV^&J3MEk@1Ljn>X zgj^JTgDj0BZbo$W9)0z!=?M3!S7K&KsmZFIdxRZlq;|E2 z3^hfo&GY|R{{4TrY`grq=LHsgA-QJLnGgJo99&+U@m1%|$A@*(w%mQop7HDV+waU9 zTJ-hmW~vf$=ZvH88JKiZUs}g7cyFX%{Jf650Sr(EhI7Z6kkiYVNBInl(?0zuu>Y`b zPvrCDBt`=1=ME#wraPs~t8{3T#@1}#{g;8^LLwn|Tw@ma`unv!n?-+q+#j173qtNW z^Xk{LS0*~osGOic$>7_!r#dg+y}Qc5FeQTYL>l=g{s4pb&tG5Tna^L9*WV{op~X!g zBR}R-nDDeuDj=0mAYqmWX{EKrrBY(W7BcLs%x0fveDH@*z!6oVoT*}1RQKoYWX6iF z`TPEs&od_Eh0VM6?X=?Uwv_2(4xN4WDMLY>*g%$Lpw#sI_ItJp^Z3|5Ry8&R1I4<* zVcPCAhpDW{rRR?i=%YR99iC zAR=S$$INXzD#LfYan;#pMGO}9^m8f}PrqjDsH)i^U!k{c_um7*i7SFaX;%bs3}i~g f%(BE+;(yo|=6N$nQm7NixBooROLxqwx`#LkoQnpaCk2X^Zg~%?XL@JYg zO^EFKKIfU1|F7SB&biL}KiB`g&ilS6*Y)*%zRz+$_j50w`@SEdFei1H8TlC@5D4=z zJ#8Zh1WJNHX!79npyw=Nu@?ei?75_+g*m3Bg~VKOwZG(K2Z88C-Arb{BzAG*XDB%e z@IBhf*$SGZLnZVWP9csVv+LtSu34F%tt}>sgm77Lohpzz>J&-WbEk77L<-te zM!L>?Xof+^_HD(=XhurfLd%;MIlXH$%`YGr5kI3#EGOuYrg!2S!sz7^6O3<{3gPML z@i4cV#KvU(t`8q>KyJ8infl>a(W2|m>+~Muwkg=7mdK<98oUwvNuJkhFW@D}%keTd z_d(FRG$%(Fc79~93YE1A-x=vP0C$L;OJ+YQYG5%EybDwkw@at1Ai|gW)5mWNr|)JNdNeFi>OL%$#LyU9=;RWuY#JV2C*+XnB$6+u zV(rX>crmd`cc--8{T+|^31J66Z>Rb&R$b@hedozbOk&vtPCqSjcfCB1F}p~f%v(mL~=1AOtY3#ea;d0Py~~qpUU}UnP)WY(bW8=*^)Kgy!*+?m@`?n z+%l^E>6&}sbSKzYui&AtA*^AL1M!gTBZ}AqA9pz9c@j>f?=zC^dL6?l_kyEp_`-wh ziPz;JqANa=iN1}zmC0x zaLwUDYqb!O_b^W)Lo`9DfQF@p&KDxg1_{wrjD)%)`I_kikl3#NI`AF#dx6$Q1c_p@l5q0 zn?xH4j%$R3?1K`V3FzY&*^4;#6OLyyUQ{q)-gWgPdW)|2 zAV?p+3SSj7eT4N+wXFoNR$#>9rgFXf>bKgU`o!72 zzC3|&bvl{a{F>w;*3Yeju0sKHb+G-l34;caB5*hp{2M#~(Gn&QCiGJF)b)!7i(;?X z3nSk~jnrFwKKhySvkFJl1)X`37G%`1w|XP@MDM-5hx#b~>~L3X^X{C4n_r5*Y<=OL z*P2&hyn5~^f_M+JGpRVqvB|GVzDbukHT*8UsTT36$z7wnn!~qVT{Z}LaDT6*$8&pv zeafhNi$E%^3G~yortEo=KItZzle|IREuDI+@J!N~ymtO4p%$h^>qYL}XS!>1%6q3UItzVK36&Q^S!P|m%UlcmkJEiS?(_3NEHh?wY z>6Z6K?3>$ftP{l&bN3GTAXN%>&F^v)EED95y%8%ZD6k7_`1E#yoLybg^L+#9y%|^1 zmzCAL+r3$QtcQ9hH`^QDU7ax+ztVW~Gymr@a`Bs`n6%2Y_s$VLv_7dD2Uku{Kbgj= zsj6KNDi+$xM<@-BYc4WTrvp0Mc;CO1H(!9NJw6#pm66gJHvd!b**zBmF zVck8k2fI#eyuAMT^j!GI7vnu28P){1xwj=X@ivJ>>{m%Cu4VgG`y~5CyLEe)=1HEl z>rL9U=VD8bZ0?nmy6n&%F-e-->Uxx3pI&x0(8XdJ5%qkJa__`SyYJs8x%Mo)dUS&I zokkLcXp#2xc~C}U*{*L-zlnXDah@G;BbwwE5sLzbi(;75Zl_&S*m~;sZdB6F#ZIM! ztwf^4^Oo){1?S?PP~;&&CR#CYGD+^o>A_*Ogp zzK{9znbURw1p)Ib6`g4XB~!ZXai2C8S8h&jlwqG$FQA(VOrJ78ePUo{&C4ZRPCB#| zVZ_>}D(G4Iusz$`XV=}lFL1>>s`K*~yFUapio_NRIqb^cdNZHnyi~OQnVw{;S!Z*X z^t5o_i-*J7t5NOtS)=QTvEnOPa%!jjEXEegxy<;iXv!s7#m-)>lqiuaP z@Z*{akNw$;)x7R=^Y`QR$9g)Q9b`7F)x8=vnxb+a=f-rX<{digQ*BKt+-O~z5}IOG zP<1`nw^-KId!Tr@S(;)w=EBfd-5&S4SlN|-LdgJV&1pb^I00xqdwK^r?YF=HjPW^aodqYUcpwh4q{P+Td#S+Xp)rbe46NyjxT%eKsg=8+W}V z{J(Z>^sdwiU(=WfQk{)jdN}3rd8~iP59@|)s_qVU-sYa0irQ~_KVkkt#fMXnt5S-h zwD^*Z8*7Su5Pmr=Hiy`jj=Rv9N`ww#Q(P#mR=0r`Z=oF%t&`3TiABD3KS+3qzvvt#xK29W)r4Tr#J z_#t$lMFSpn8i9Ybb!a3YwBP%o5Jz6FSwqwL-{(pQRzTbeU(Ae+0N4z>Fey|;-T!TCh~oTGH6q~WkitQ zr+8jg6EQQuAhlet*dY(2WKpsr>WoMvQuWFOdu1bSouA9Wmzu~$Pfs^x85tiRAC!+g z%Jqta%mF1OB^g;c896y=FhknI&&AW$SK7rx^aqh&bhPa}&R@CY=6T801xclAd(PF% zQ%yvKy3s#=e(-7Md+D#8Ts(dr3mi~}IwErbB`fm}+F+?FwO1K)$=A-wT>FwUkQvxR z{h++8>i7Bo)5u>t{iW6u?}I-Vs>)DL z{+lFzi1~Xjkh40Ys?0xhrp}0B-dPRQD0oTR&;-1Jk$wN^0KX-`Lw$p1XM-J2!X$X# zIHs*>;!88xTYG(v17G7@Y74(6y#BiHfmfl|h^HcN=Sq@FU@Ld*Ps2E4Oe@9r3UQo3 zZ8M##xW*(R!3)=BJ5!$)08&7q9oBaWbZmQ>7rPTrbSzsQvRVol-I5AR84oU*c-Yz& zmQOSGwQ6HpMQC$38V{j?!r*L3HW9Zy7_Gy$JHCH`Zh`_G>=7&U$0!<)PQs&OEFx^d z)E{eLk6M2&{bvWK*+{`hAH~6ck*;|L^LR)ym8`;wQK6Q0O5SF?x}o$6b_0VmA7# zbHsms*CXKM(wn@Ie>VRk_Ww5qSF?+D>FY}hAvP|KLJ6JuWydhMAll|2Mg|*vVU?_v zRT0#4xg%KNY^DFwa%+{j?w|%`ZDtTB`S|=yUNH=HR*@fNU6I@V{(%_Pfo%_BvI3?z z>PFsTOIsET)7;m;BpUW@cPV^>_m>Yn*|B=am zK06`E5&S(p4{q3wSr4wR`c8|z`!d5smbdl1!2(NwdTrrCy$amo^zb#Buy#@w2f=@& z>293^%1RmT|Mn05{8c9Z5iMsjFD*;l2VdI)l>Rp7wvnopk(%T+ZF8mJn4 zb7&x+Sz~?W*_N>gCd+SheCS4mu=SSwY)qq&aGq89^L0U}*Af>mF%o^87(A6BEL0Ud zqkE0Smk8iSoGy5-wR%S@<=culR&~}8T1;a`JZz(Moa$KgQnhdxJc);mq;lqKH8C@6 z4vR7LUyZ6k(Gbe?Uws4a+KELIrwcep;aH`;r9IJT zwecZwXgLfvf#S;tE^C7W>+6mKg6t%5wM}iCWIVc0Y}g9~)JYkz-V8xbl!Y$ci^zgc zar?DFm>5Z+yK|#BQBbo|U2oTU|4F1ir*={3| z7=ibHCVw}A|6bA%gD#EdR4b^?&(?7Y%{Wn-&d1?AO1-DLyR1E5esbycJ+G*)o;jnC)FlL)q6QSK%M6(2bJ;3f&g#J8f=ZWKyK%6IZUHw6h*ZT*51Nkwb4sMn z`|>)NgQQLiTjpdVZ73-n1^owU2&vC+sEx9d0+32a20;j0Isg({v;hsl!p#+0JoquX z;u_kBD70(WlXHU)#tdsH3`3h!WX?(}G_k60&o&o;c)Wl&c4MOD0Hc&1|_^3i4kpoe>e>7yl|xqOGD_MnQmQ3 zWFjwAShYT9XCnzj9l_E$X4~<3od&+VzdB7=4^0$;x7*zXZbepJ7SJJ1kA2xmLzs|v z69OFh^*(a&&&8vIa`gyVbdCfuz5_?lM4iXAYz|ULOe-&WM1&6J_{HK?1P5tYyzt>vwn*oBn0ZnT&u$^1EK2~Gl3=3 zw71i1gh1NBdap zRq8nbrANR5`kG&#g?hmnEn&|AN^*z0g5m)KB+6~kZf`;;yD@vSrWB9fwK9hSl#GC+ zChT=aIY^?4{UQYbaZ6+a^?`vM0XF#l+2Om40ZR86;bd}4bh8*n*RA5HjXs*_V!L_^2=FSf zhip4%9WJUm5z!zfxC_q!O8-h#5I&%Tmb)Cn-zHbPZMX+}FHOvnjR(rN3SHZQ8GS1) zzpMtd&!wBu5ctdaLxG9dm;l|+U#QxLkzYCY zNEOJTgp-rnFASs>XVl3@;D63GTn~=h`H43g9PlnseUkWs0U`ATkMRhQR7J*ZYB9F~ zJSr&ZWIg?OvhM-0tCEu0Ol-dxJ9 zW6}r|^DI+u>bD>GHE{ZVUG|q4}9fF<|OG$lsEdZv604XuV)f!hJck0#aPZDF_sO`cT8lw z7;knMFtVq6wK&WG?&Vd5lrSSP13C$m5OmAH4TL-}s8>QKG?8F%)L9RR?@KHvf~>-! zgdQ{?+(U0QC2ywg6V?Z=TkZcQKjnB&4BDXQwa@~btQIf0+szm$hLH{h3W9Y5N@=F` zmk9h%>9uwOj_7V(&<3`gE`r1uY97NKBR+6_9k>rj+>UdU3e;(M0EgEUr2#bBL_&eH z)g(mg0dFw|KD$q1Tn0g2WKNMe3NXg$r65r0MS%Uz*6cZSj`jRIPEjirvjleFk8alh zs?mvUi4jt(b}!rqhLU7(o63?ipxGk%xdF>D(mt%d*-uz{qWm>Ffcv0hnIenY5S;b6gK^P6p>OK5WYZ zj#dQh^KgD-8}!gQ=5Ps+;4n$Oi3FS~0;V%V61Ef21_SYHMnEu4dz&@E(GCOXALVkl z_zu-{pdTRj4Zvv*V9prx5z9du7m&k(^B8o6DS_(kJ#eU=3Xzjcq8F(X^rZG^XyBLW%#ay?a}tt+4PF}=n!(|wAf_(m z_kIgNYDzTFVt{>h+y9>@Wx#@GDk-6Lg#xh>IR$}mSy3-1r+PJ7?Z!^O8j>H@kT@I*YraA?eo%L5D^t4}zXiB_$ea82O<=gy&t=5f~)mD^v ztW*P*EygU$SEJ5NSIoTXmN%WvT*XpXS#-`E0%t(hQ z62s#njo~R!J#Iq_iXAUnMoHlENT3Q-x;_zQz*0_=hAAfXIDatbN{+RU*wbN~kgf%cd#LcM6--h~|oZ2`erMk)*dE%3Yt zgl_2~oIqPaF@%eHB?F)fMMRM4q~bU_LEFU*MrCCXxVIIWlf+~uBvwEGiOwMW41mcR zfJ0^Yy+1hz?OOK7)GCV>Fbk@ze>daWun9{nWqo|91FJE+@NUC2bMtK?RRI|*_Zj+^ zC%eRR($dmsac$V$ZdL&A%BH6}IFN2iP(8lp?TLy9x#*wta&yM zJQvRh0R$4A45y|vApd+Dwk5+x+8W(!58`@rc~>eBD3~U|Mk44I&PRd(Y^#t2`s@J0 z?w!OD&{GNu2f#g*eSb?k5F3~_0Bl}0^`;_>>>$s2 z=^_F8nt;2V=%hdi-L5X@Kn2lKk@f^c6fmtCq%gh*CF6jS*}b)>`6Ed0?Oty4z{$ZL zobmuSNBf)%z?D0Jf0Y?duDNUOrwvk_0)gW|H_rf2b1qk-iOXqexA!42@-z0Afti45 zuHYI#sHI61C@-uJ1NxExrIZ2+9kh6$xBdh$%q7YEezl;HVwIFga6+WTpaUhqW4+6e zA~UT3uC^01PX3g5rx*rDsm#yVo~^_R9FR?d5WaD*j?Jj6ZM6+h90WtqF)ArQiYYfE zfE3v(p2FZxzzIr}8b)M3Q$qdM6qcDd>BOsoLvcKe=3uyq0)bn&?M z7OPFP-j3ONxd7HLDEc$eKwkizt$4eqF@YnP`|8=`ptnLJwo@Kvx7L_JO{HhQ1b~m+ zZHO|i0zE}OENO0&jNTf-1`RFhSI-;C-S0!N!2#UHf#a>Z#Gp(1o6W8 z_!>}xEH1=Qwf~rEIvEt!|2{?m@)JJ=%kOuy^ue@${Ow=pZ~u&FCwG#3d4jj%(=DZAa3}m%qg}vhjP_LZJs$(eVl2W#+_Y#2F2@M*EDZnC` zh1Wpoe+Sx&pzL|l>s$wO6j)lLN01lH{oCvSM!v1e$LbEs1J+Uo2x#Vt+`r+d1ppgK zpB`C4w@y%%CUhzAR=;N#*y-8Kw+{Bz6KJCKs1Lxtnf*Utl8^yi%Es9{ei4veoTsZA z%StJGEy_f$DP;VCcfds}aVy1b`2$-Mk%Vj*%4%@Dr7;J$u@)z@EfJ3bdsJv8%gjQwu`9<5F6F9%yl=2yrCKM~#>jL0$6*zycyB`60&nZf|P#A}&T zZ(g%FBjIEQR-yFi0o;N|?h2)~F-|xuQ+EiE-t90oHZ*`aQDN*BJ)=sxinN)tz5Y> zJ47#XrqqO>u|BNvf}Az#WAzYZbBYzeGDvR(SvRiAZ@vAl?hk_f>r(^&tBK!J%_G-A zX>5D=-YHA?Sp_KH3LUc2H}5vb4C*v6PI8c3tGAZN1qN0t&2+EN$jnZ;Ql_@`yW?v@fG49i zGjn}Sh}I1$Td(E8-y%p3tNW~}WpOU3Z3tuBf6~MMLwfkngsVT9_w9WJ#>D;?9^#xI z+5z;JzIgFs#BkFAluZN+1t(l6+F4vd)&vBxpp`zKleqQi^6YEvduJPW$ADi&(@?5H;D|KIb!$5nl3~bicWBRG9Z(x7?aUal@0it?hx{^|5U{8r=PySq$IK zL+=VvID8UZRAw~4)CAe@S2IE`HE<$+D;E64K=eJ%qP8ecH^CNY_Za=;>somSxINDw z?+(6P0_uA1>O4OX{ri7U`>dnz=*k2w)~ypDO~>*{VkG^yrw@S~{Bqgzfo|{*G35>U zmqCE7DEU3ent}=`|I2$V4Pzopt?4U9^0mzB00Z!M#0duq%Y@2Ig@?gn@HZ}a;A}0! z_Aaty=>pksC&_sJ>I-Nwek|YmCJ5pFr@sb+vHP;<&=>BEp&>wsM534l)i1v?Y|Lfh4{HM3tK?+Ug(~;7L590c${~vnn=t=FoBQ_!b E1BYg#Bme*a From 6db78b59f93258c94fd051aecc34c822c33362a9 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Mon, 14 Mar 2022 11:45:20 -0700 Subject: [PATCH 161/175] Add manual reset flag for settings update event (#144429) Ref https://github.com/microsoft/vscode/issues/58038 This flag could also come in useful for language overrides. --- .../preferences/browser/settingsEditor2.ts | 20 ++++++++++--------- .../preferences/browser/settingsTree.ts | 12 ++++++----- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 7e598f83d5b..ed4b20be0c8 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -788,7 +788,7 @@ export class SettingsEditor2 extends EditorPane { private createSettingsTree(container: HTMLElement): void { this.settingRenderers = this.instantiationService.createInstance(SettingTreeRenderers); - this._register(this.settingRenderers.onDidChangeSetting(e => this.onDidChangeSetting(e.key, e.value, e.type))); + this._register(this.settingRenderers.onDidChangeSetting(e => this.onDidChangeSetting(e.key, e.value, e.type, e.manualReset))); this._register(this.settingRenderers.onDidOpenSettings(settingKey => { this.openSettingsFile({ revealSetting: { key: settingKey, edit: true } }); })); @@ -869,16 +869,16 @@ export class SettingsEditor2 extends EditorPane { })); } - private onDidChangeSetting(key: string, value: any, type: SettingValueType | SettingValueType[]): void { + private onDidChangeSetting(key: string, value: any, type: SettingValueType | SettingValueType[], manualReset: boolean): void { if (this.pendingSettingUpdate && this.pendingSettingUpdate.key !== key) { - this.updateChangedSetting(key, value); + this.updateChangedSetting(key, value, manualReset); } this.pendingSettingUpdate = { key, value }; if (SettingsEditor2.shouldSettingUpdateFast(type)) { - this.settingFastUpdateDelayer.trigger(() => this.updateChangedSetting(key, value)); + this.settingFastUpdateDelayer.trigger(() => this.updateChangedSetting(key, value, manualReset)); } else { - this.settingSlowUpdateDelayer.trigger(() => this.updateChangedSetting(key, value)); + this.settingSlowUpdateDelayer.trigger(() => this.updateChangedSetting(key, value, manualReset)); } } @@ -948,7 +948,7 @@ export class SettingsEditor2 extends EditorPane { return ancestors.reverse(); } - private updateChangedSetting(key: string, value: any): Promise { + private updateChangedSetting(key: string, value: any, manualReset: boolean): Promise { // ConfigurationService displays the error if this fails. // Force a render afterwards because onDidConfigurationUpdate doesn't fire if the update doesn't result in an effective setting value change const settingsTarget = this.settingsTargetsWidget.settingsTarget; @@ -956,11 +956,13 @@ export class SettingsEditor2 extends EditorPane { const configurationTarget = (resource ? ConfigurationTarget.WORKSPACE_FOLDER : settingsTarget); const overrides: IConfigurationOverrides = { resource }; - const isManualReset = value === undefined; + const configurationTargetIsWorkspace = configurationTarget === ConfigurationTarget.WORKSPACE || configurationTarget === ConfigurationTarget.WORKSPACE_FOLDER; - // If the user is changing the value back to the default, do a 'reset' instead + const isManualReset = configurationTargetIsWorkspace ? manualReset : value === undefined; + + // If the user is changing the value back to the default, and we're not targeting a workspace scope, do a 'reset' instead const inspected = this.configurationService.inspect(key, overrides); - if (inspected.defaultValue === value) { + if (!configurationTargetIsWorkspace && inspected.defaultValue === value) { value = undefined; } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 83c3b881206..bfc5db90916 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -656,6 +656,7 @@ export interface ISettingChangeEvent { key: string; value: any; // undefined => reset/unconfigure type: SettingValueType | SettingValueType[]; + manualReset: boolean; } export interface ISettingLinkClickEvent { @@ -782,7 +783,7 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre const descriptionElement = DOM.append(container, $('.setting-item-description')); const modifiedIndicatorElement = DOM.append(container, $('.setting-item-modified-indicator')); - modifiedIndicatorElement.title = localize('modified', "Modified"); + modifiedIndicatorElement.title = localize('modified', "The setting has been configured in the current scope."); const valueElement = DOM.append(container, $('.setting-item-value')); const controlElement = DOM.append(valueElement, $('div.setting-item-control')); @@ -883,7 +884,7 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre template.miscLabel.updateOtherOverrides(element, template.elementDisposables, this._onDidClickOverrideElement); - const onChange = (value: any) => this._onDidChangeSetting.fire({ key: element.setting.key, value, type: template.context!.valueType }); + const onChange = (value: any) => this._onDidChangeSetting.fire({ key: element.setting.key, value, type: template.context!.valueType, manualReset: false }); const deprecationText = element.setting.deprecationMessage || ''; if (deprecationText && element.setting.deprecationMessageIsMarkdown) { const disposables = new DisposableStore(); @@ -1449,7 +1450,8 @@ export class SettingExcludeRenderer extends AbstractSettingRenderer implements I this._onDidChangeSetting.fire({ key: template.context.setting.key, value: Object.keys(newValue).length === 0 ? undefined : sortKeys(newValue), - type: template.context.valueType + type: template.context.valueType, + manualReset: false }); } } @@ -1765,7 +1767,7 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre const controlElement = DOM.append(descriptionAndValueElement, $('.setting-item-bool-control')); const descriptionElement = DOM.append(descriptionAndValueElement, $('.setting-item-description')); const modifiedIndicatorElement = DOM.append(container, $('.setting-item-modified-indicator')); - modifiedIndicatorElement.title = localize('modified', "Modified"); + modifiedIndicatorElement.title = localize('modified', "The setting has been configured in the current scope."); const deprecationWarningElement = DOM.append(container, $('.setting-item-deprecation-message')); @@ -1904,7 +1906,7 @@ export class SettingTreeRenderers { new Action('settings.resetSetting', localize('resetSettingLabel', "Reset Setting"), undefined, undefined, async context => { if (context instanceof SettingsTreeSettingElement) { if (!context.isUntrusted) { - this._onDidChangeSetting.fire({ key: context.setting.key, value: undefined, type: context.setting.type as SettingValueType }); + this._onDidChangeSetting.fire({ key: context.setting.key, value: undefined, type: context.setting.type as SettingValueType, manualReset: true }); } } }), From 43ebce7ce2185c8100175305818d7e42079f7a3e Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Mon, 14 Mar 2022 19:53:24 +0100 Subject: [PATCH 162/175] Use markdown for the timeline hover (#145038) --- extensions/git/src/timelineProvider.ts | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/extensions/git/src/timelineProvider.ts b/extensions/git/src/timelineProvider.ts index bfedf9155c5..3e804a16f6e 100644 --- a/extensions/git/src/timelineProvider.ts +++ b/extensions/git/src/timelineProvider.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vscode-nls'; -import { CancellationToken, ConfigurationChangeEvent, Disposable, env, Event, EventEmitter, ThemeIcon, Timeline, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvider, Uri, workspace } from 'vscode'; +import { CancellationToken, ConfigurationChangeEvent, Disposable, env, Event, EventEmitter, MarkdownString, ThemeIcon, Timeline, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvider, Uri, workspace } from 'vscode'; import { Model } from './model'; import { Repository, Resource } from './repository'; import { debounce } from './decorators'; @@ -50,6 +50,20 @@ export class GitTimelineItem extends TimelineItem { return this.shortenRef(this.previousRef); } + setItemDetails(author: string, email: string | undefined, date: string, message: string): void { + this.detail = new MarkdownString('', true); + + if (email) { + const emailTitle = localize('git.timeline.email', "Email"); + this.detail.appendMarkdown(`$(account) [**${author}**](mailto:${email} "${emailTitle} ${author}")\n\n`); + } else { + this.detail.appendMarkdown(`$(account) **${author}**\n\n`); + } + + this.detail.appendMarkdown(`$(history) ${date}\n\n`); + this.detail.appendMarkdown(message); + } + private shortenRef(ref: string): string { if (ref === '' || ref === '~' || ref === 'HEAD') { return ref; @@ -167,7 +181,8 @@ export class GitTimelineProvider implements TimelineProvider { if (showAuthor) { item.description = c.authorName; } - item.detail = `${c.authorName} (${c.authorEmail}) \u2014 ${c.hash.substr(0, 8)}\n${dateFormatter.format(date)}\n\n${message}`; + + item.setItemDetails(c.authorName!, c.authorEmail, dateFormatter.format(date), message); const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri); if (cmd) { @@ -192,7 +207,7 @@ export class GitTimelineProvider implements TimelineProvider { // TODO@eamodio: Replace with a better icon -- reflecting its status maybe? item.iconPath = new ThemeIcon('git-commit'); item.description = ''; - item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.index', 'Index'), dateFormatter.format(date), Resource.getStatusText(index.type)); + item.setItemDetails(you, undefined, dateFormatter.format(date), Resource.getStatusText(index.type)); const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri); if (cmd) { @@ -214,7 +229,7 @@ export class GitTimelineProvider implements TimelineProvider { // TODO@eamodio: Replace with a better icon -- reflecting its status maybe? item.iconPath = new ThemeIcon('git-commit'); item.description = ''; - item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.workingTree', 'Working Tree'), dateFormatter.format(date), Resource.getStatusText(working.type)); + item.setItemDetails(you, undefined, dateFormatter.format(date), Resource.getStatusText(working.type)); const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri); if (cmd) { From 6837589569e7d2dc6ad4de991ed2df6e422144ae Mon Sep 17 00:00:00 2001 From: Logan Ramos Date: Mon, 14 Mar 2022 14:55:00 -0400 Subject: [PATCH 163/175] Remove TabKind.other --- src/vs/workbench/api/browser/mainThreadEditorTabs.ts | 1 - src/vs/workbench/api/common/extHost.protocol.ts | 3 +-- src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts | 2 +- src/vscode-dts/vscode.proposed.tabs.d.ts | 3 +-- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadEditorTabs.ts b/src/vs/workbench/api/browser/mainThreadEditorTabs.ts index c6d956194f3..3b4fef9a358 100644 --- a/src/vs/workbench/api/browser/mainThreadEditorTabs.ts +++ b/src/vs/workbench/api/browser/mainThreadEditorTabs.ts @@ -47,7 +47,6 @@ export class MainThreadEditorTabs { * @returns A tab object */ private _buildTabObject(group: IEditorGroup, editor: EditorInput, editorIndex: number): IEditorTabDto { - // Even though the id isn't a diff / sideBySide on the main side we need to let the ext host know what type of editor it is const editorId = editor.editorId; const tabKind = editor instanceof DiffEditorInput ? TabKind.Diff : editor instanceof SideBySideEditorInput ? TabKind.SidebySide : TabKind.Singular; const tab: IEditorTabDto = { diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 73db462b209..d4419a85614 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -628,8 +628,7 @@ export interface IEditorTabGroupDto { export enum TabKind { Singular = 0, Diff = 1, - SidebySide = 2, - Other = 3 + SidebySide = 2 } export interface IEditorTabDto { diff --git a/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts b/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts index 3a6be40a699..359ecb35c55 100644 --- a/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts +++ b/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts @@ -40,7 +40,7 @@ suite('ExtHostEditorTabs', function () { label: 'label1', viewColumn: 0, additionalResourcesAndViewTypes: [], - kind: TabKind.Other + kind: TabKind.Singular }; extHostEditorTabs.$acceptEditorTabModel([{ diff --git a/src/vscode-dts/vscode.proposed.tabs.d.ts b/src/vscode-dts/vscode.proposed.tabs.d.ts index 7cc8d4acbf8..1affd362f79 100644 --- a/src/vscode-dts/vscode.proposed.tabs.d.ts +++ b/src/vscode-dts/vscode.proposed.tabs.d.ts @@ -10,8 +10,7 @@ declare module 'vscode' { export enum TabKind { Singular = 0, Diff = 1, - SidebySide = 2, - Other = 3 + SidebySide = 2 } /** From 94dd4dbc57cba812ab23a841e1642785ea0d59a6 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 14 Mar 2022 12:26:31 -0700 Subject: [PATCH 164/175] Serialize command, fix command history after reconnect --- .../common/capabilities/commandDetectionCapability.ts | 6 ++++-- src/vs/platform/terminal/common/terminalProcess.ts | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts index 25ed46ed986..e50cb18d0ce 100644 --- a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts +++ b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts @@ -226,10 +226,11 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { } serializeCommands(): ISerializedCommand[] { - const serialized = this.commands.map(e => { + const serialized: ISerializedCommand[] = this.commands.map(e => { return { startLine: e.marker?.line, endLine: e.endMarker?.line, + command: e.command, cwd: e.cwd, exitCode: e.exitCode, timestamp: e.timestamp @@ -239,6 +240,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { serialized.push({ startLine: this._currentCommand.commandStartMarker.line, endLine: undefined, + command: '', cwd: undefined, exitCode: undefined, timestamp: 0, @@ -265,7 +267,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { } // Full command const newCommand = { - command: '', + command: e.command, marker, endMarker: e.endLine !== undefined ? this._terminal.registerMarker(e.endLine - (buffer.baseY + buffer.cursorY)) : undefined, timestamp: e.timestamp, diff --git a/src/vs/platform/terminal/common/terminalProcess.ts b/src/vs/platform/terminal/common/terminalProcess.ts index 0bff257fd7a..9751078f1c7 100644 --- a/src/vs/platform/terminal/common/terminalProcess.ts +++ b/src/vs/platform/terminal/common/terminalProcess.ts @@ -69,6 +69,7 @@ export interface ReplayEntry { data: string; } export interface ISerializedCommand { + command: string; cwd: string | undefined; startLine: number | undefined; endLine: number | undefined; From 950205cdd193e566af023a6213683785127e199e Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 14 Mar 2022 12:47:14 -0700 Subject: [PATCH 165/175] Persist hasOutput/getOutput --- .../common/capabilities/capabilities.ts | 1 + .../commandDetectionCapability.ts | 35 +++++++++++-------- .../terminal/common/terminalProcess.ts | 1 + 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/vs/platform/terminal/common/capabilities/capabilities.ts b/src/vs/platform/terminal/common/capabilities/capabilities.ts index 4f24ba26cc5..f87d3c7ffdf 100644 --- a/src/vs/platform/terminal/common/capabilities/capabilities.ts +++ b/src/vs/platform/terminal/common/capabilities/capabilities.ts @@ -127,6 +127,7 @@ export interface ITerminalCommand { exitCode?: number; marker?: IXtermMarker; endMarker?: IXtermMarker; + executedMarker?: IXtermMarker; getOutput(): string | undefined; hasOutput: boolean; } diff --git a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts index e50cb18d0ce..1dc352c3d37 100644 --- a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts +++ b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts @@ -200,17 +200,19 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { if (command !== undefined && !command.startsWith('\\')) { const buffer = this._terminal.buffer.active; - const clonedPartialCommand = { ...this._currentCommand }; const timestamp = Date.now(); - const newCommand = { + const executedMarker = this._currentCommand.commandExecutedMarker; + const endMarker = this._currentCommand.commandFinishedMarker; + const newCommand: ITerminalCommand = { command, marker: this._currentCommand.commandStartMarker, - endMarker: this._currentCommand.commandFinishedMarker, + endMarker, + executedMarker, timestamp, cwd: this._cwd, exitCode: this._exitCode, - hasOutput: !!(this._currentCommand.commandExecutedMarker && this._currentCommand.commandFinishedMarker && this._currentCommand.commandExecutedMarker?.line < this._currentCommand.commandFinishedMarker!.line), - getOutput: () => getOutputForCommand(clonedPartialCommand, buffer) + hasOutput: !!(executedMarker && endMarker && executedMarker?.line < endMarker!.line), + getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer) }; this._commands.push(newCommand); this._logService.debug('CommandDetectionCapability#onCommandFinished', newCommand); @@ -230,6 +232,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { return { startLine: e.marker?.line, endLine: e.endMarker?.line, + executedLine: e.executedMarker?.line, command: e.command, cwd: e.cwd, exitCode: e.exitCode, @@ -240,6 +243,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { serialized.push({ startLine: this._currentCommand.commandStartMarker.line, endLine: undefined, + executedLine: undefined, command: '', cwd: undefined, exitCode: undefined, @@ -266,18 +270,18 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { continue; } // Full command + const endMarker = e.endLine !== undefined ? this._terminal.registerMarker(e.endLine - (buffer.baseY + buffer.cursorY)) : undefined; + const executedMarker = e.executedLine !== undefined ? this._terminal.registerMarker(e.executedLine - (buffer.baseY + buffer.cursorY)) : undefined; const newCommand = { command: e.command, marker, - endMarker: e.endLine !== undefined ? this._terminal.registerMarker(e.endLine - (buffer.baseY + buffer.cursorY)) : undefined, + endMarker, + executedMarker, timestamp: e.timestamp, cwd: e.cwd, exitCode: e.exitCode, - // TODO: Implement correctly - hasOutput: false, - getOutput: () => '' - // hasOutput: !!(this._currentCommand.commandExecutedMarker && this._currentCommand.commandFinishedMarker && this._currentCommand.commandExecutedMarker?.line < this._currentCommand.commandFinishedMarker!.line), - // getOutput: () => getOutputForCommand(clonedPartialCommand, buffer) + hasOutput: !!(executedMarker && endMarker && executedMarker.line < endMarker.line), + getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer) }; this._commands.push(newCommand); this._logService.debug('CommandDetectionCapability#onCommandFinished', newCommand); @@ -286,9 +290,12 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { } } -function getOutputForCommand(command: ICurrentPartialCommand, buffer: IBuffer): string | undefined { - const startLine = command.commandExecutedMarker!.line; - const endLine = command.commandFinishedMarker!.line; +function getOutputForCommand(executedMarker: IMarker | undefined, endMarker: IMarker | undefined, buffer: IBuffer): string | undefined { + if (!executedMarker || !endMarker) { + return undefined; + } + const startLine = executedMarker.line; + const endLine = endMarker.line; if (startLine === endLine) { return undefined; diff --git a/src/vs/platform/terminal/common/terminalProcess.ts b/src/vs/platform/terminal/common/terminalProcess.ts index 9751078f1c7..2d33ff1e087 100644 --- a/src/vs/platform/terminal/common/terminalProcess.ts +++ b/src/vs/platform/terminal/common/terminalProcess.ts @@ -73,6 +73,7 @@ export interface ISerializedCommand { cwd: string | undefined; startLine: number | undefined; endLine: number | undefined; + executedLine: number | undefined; exitCode: number | undefined; timestamp: number; } From 512145b4b9c0ea7e7edba592921bcbc5f103c136 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 14 Mar 2022 14:27:23 -0700 Subject: [PATCH 166/175] Fix next command after restore --- .../common/capabilities/commandDetectionCapability.ts | 8 +++++--- src/vs/platform/terminal/common/terminalProcess.ts | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts index 1dc352c3d37..4b456372e5e 100644 --- a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts +++ b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts @@ -231,6 +231,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { const serialized: ISerializedCommand[] = this.commands.map(e => { return { startLine: e.marker?.line, + startX: undefined, endLine: e.endMarker?.line, executedLine: e.executedMarker?.line, command: e.command, @@ -242,10 +243,11 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { if (this._currentCommand.commandStartMarker) { serialized.push({ startLine: this._currentCommand.commandStartMarker.line, + startX: this._currentCommand.commandStartX, endLine: undefined, executedLine: undefined, command: '', - cwd: undefined, + cwd: this._cwd, exitCode: undefined, timestamp: 0, }); @@ -264,8 +266,8 @@ export class CommandDetectionCapability implements ICommandDetectionCapability { // Partial command if (!e.endLine) { this._currentCommand.commandStartMarker = marker; - // TODO: Get real value if needed - this._currentCommand.commandStartX = 0; + this._currentCommand.commandStartX = e.startX; + this._cwd = e.cwd; this._onCommandStarted.fire({ marker } as ITerminalCommand); continue; } diff --git a/src/vs/platform/terminal/common/terminalProcess.ts b/src/vs/platform/terminal/common/terminalProcess.ts index 2d33ff1e087..3e9613ce4ce 100644 --- a/src/vs/platform/terminal/common/terminalProcess.ts +++ b/src/vs/platform/terminal/common/terminalProcess.ts @@ -72,6 +72,7 @@ export interface ISerializedCommand { command: string; cwd: string | undefined; startLine: number | undefined; + startX: number | undefined; endLine: number | undefined; executedLine: number | undefined; exitCode: number | undefined; From 508435d60d48e11a82819ebf618d7be81897bd74 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 14 Mar 2022 14:31:45 -0700 Subject: [PATCH 167/175] Avoid recreating duplicate menus and hovers --- .../contrib/terminal/browser/xterm/decorationAddon.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts index e2caecd6fcf..673da2261d9 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts @@ -183,12 +183,13 @@ export class DecorationAddon extends Disposable implements ITerminalAddon { this._placeholderDecoration = decoration; this._placeholderDecoration.onDispose(() => this._placeholderDecoration = undefined); } else { - this._decorations.set(decoration.marker.id, - { + if (!this._decorations.has(decoration.marker.id)) { + this._decorations.set(decoration.marker.id, { decoration, disposables: command.exitCode === undefined ? [] : [this._createContextMenu(element, command), ...this._createHover(element, command)], exitCode: command.exitCode }); + } } if (!element.classList.contains(DecorationSelector.Codicon) || command.marker?.line === 0) { // first render or buffer was cleared From 79d9bb8754331225372e892393619d4072474a19 Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Mon, 14 Mar 2022 18:22:00 -0700 Subject: [PATCH 168/175] Add some Settings editor event annotations (#144287) --- .../preferences/browser/settingsEditor2.ts | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index ed4b20be0c8..237036a5be6 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -1033,13 +1033,13 @@ export class SettingsEditor2 extends EditorPane { /* __GDPR__ "settingsEditor.settingModified" : { - "key" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "groupId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "nlpIndex" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "displayIndex" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "showConfiguredOnly" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "isReset" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "target" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "key" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "rzhao271", "comment": "The setting that is being modified." }, + "groupId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "rzhao271", "comment": "Whether the setting is from the local search or remote search provider, if applicable." }, + "nlpIndex" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "rzhao271", "comment": "The index of the setting in the remote search provider results, if applicable." }, + "displayIndex" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "rzhao271", "comment": "The index of the setting in the combined search results, if applicable." }, + "showConfiguredOnly" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "rzhao271", "comment": "Whether the user is in the modified view, which shows configured settings only." }, + "isReset" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "rzhao271", "comment": "Identifies whether a setting was reset to its default value." }, + "target" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "rzhao271", "comment": "The scope of the setting, such as user or workspace." } } */ this.telemetryService.publicLog('settingsEditor.settingModified', data); @@ -1341,10 +1341,10 @@ export class SettingsEditor2 extends EditorPane { private reportFilteringUsed(query: string, results: ISearchResult[]): void { const nlpResult = results[SearchResultIdx.Remote]; - const nlpMetadata = nlpResult && nlpResult.metadata; + const nlpMetadata = nlpResult?.metadata; - const durations = { - nlpResult: nlpMetadata && nlpMetadata.duration + const duration = { + nlpResult: nlpMetadata?.duration }; // Count unique results @@ -1358,20 +1358,20 @@ export class SettingsEditor2 extends EditorPane { counts['nlpResult'] = nlpResult.filterMatches.length; } - const requestCount = nlpMetadata && nlpMetadata.requestCount; + const requestCount = nlpMetadata?.requestCount; const data = { - durations, + durations: duration, counts, requestCount }; /* __GDPR__ "settingsEditor.filter" : { - "durations.nlpResult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "counts.nlpResult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "counts.filterResult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "requestCount" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } + "durations.nlpResult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "rzhao271", "comment": "How long the remote search provider took, if applicable." }, + "counts.nlpResult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "rzhao271", "comment": "The number of matches found by the remote search provider, if applicable." }, + "counts.filterResult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "rzhao271", "comment": "The number of matches found by the local search provider, if applicable." }, + "requestCount" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "rzhao271", "comment": "The number of requests sent to Bing, if applicable." } } */ this.telemetryService.publicLog('settingsEditor.filter', data); @@ -1501,7 +1501,7 @@ export class SettingsEditor2 extends EditorPane { } else { /* __GDPR__ "settingsEditor.searchError" : { - "message": { "classification": "CallstackOrException", "purpose": "FeatureInsight" } + "message": { "classification": "CallstackOrException", "purpose": "FeatureInsight", "owner": "rzhao271", comment: "The error message of the search error." } } */ const message = getErrorMessage(err).trim(); From afcebfa6ae642564d43165e1e72375361e2338ed Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 15 Mar 2022 08:47:05 +0100 Subject: [PATCH 169/175] change how `scheme` and `pattern` are interpreted when `notebookType` is present on DocumentFilter --- .../editor/common/languageFeatureRegistry.ts | 48 ++++++++++++------- .../common/services/languageFeatures.ts | 4 +- .../services/languageFeaturesService.ts | 8 ++-- .../common/modes/languageSelector.test.ts | 1 + .../notebook/browser/notebook.contribution.ts | 10 ++-- src/vscode-dts/vscode.d.ts | 10 ++-- 6 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/vs/editor/common/languageFeatureRegistry.ts b/src/vs/editor/common/languageFeatureRegistry.ts index 8791e9e5101..74995dbe597 100644 --- a/src/vs/editor/common/languageFeatureRegistry.ts +++ b/src/vs/editor/common/languageFeatureRegistry.ts @@ -26,8 +26,27 @@ function isExclusive(selector: LanguageSelector): boolean { } } -export interface NotebookTypeResolver { - (uri: URI): string | undefined; +export interface NotebookInfo { + readonly uri: URI; + readonly type: string; +} + +export interface NotebookInfoResolver { + (uri: URI): NotebookInfo | undefined; +} + +class MatchCandidate { + constructor( + readonly uri: URI, + readonly languageId: string, + readonly notebookType: string | undefined + ) { } + + equals(other: MatchCandidate): boolean { + return this.notebookType === other.notebookType + && this.languageId === other.languageId + && this.uri.toString() === other.uri.toString(); + } } export class LanguageFeatureRegistry { @@ -38,7 +57,7 @@ export class LanguageFeatureRegistry { private readonly _onDidChange = new Emitter(); readonly onDidChange = this._onDidChange.event; - constructor(private readonly _notebookTypeResolver?: NotebookTypeResolver) { } + constructor(private readonly _notebookInfoResolver?: NotebookInfoResolver) { } register(selector: LanguageSelector, provider: T): IDisposable { @@ -123,24 +142,19 @@ export class LanguageFeatureRegistry { } } - private _lastCandidate: { uri: string; language: string; notebookType?: string } | undefined; + private _lastCandidate: MatchCandidate | undefined; private _updateScores(model: ITextModel): void { - const notebookType = this._notebookTypeResolver?.(model.uri); + const notebookInfo = this._notebookInfoResolver?.(model.uri); - const candidate = { - uri: model.uri.toString(), - language: model.getLanguageId(), - notebookType - }; - - if (this._lastCandidate - && this._lastCandidate.language === candidate.language - && this._lastCandidate.uri === candidate.uri - && this._lastCandidate.notebookType === candidate.notebookType - ) { + // use the uri (scheme, pattern) of the notebook info iff we have one + // otherwise it's the model's/document's uri + const candidate = notebookInfo + ? new MatchCandidate(notebookInfo.uri, model.getLanguageId(), notebookInfo.type) + : new MatchCandidate(model.uri, model.getLanguageId(), undefined); + if (this._lastCandidate?.equals(candidate)) { // nothing has changed return; } @@ -148,7 +162,7 @@ export class LanguageFeatureRegistry { this._lastCandidate = candidate; for (let entry of this._entries) { - entry._score = score(entry.selector, model.uri, model.getLanguageId(), shouldSynchronizeModel(model), notebookType); + entry._score = score(entry.selector, candidate.uri, candidate.languageId, shouldSynchronizeModel(model), candidate.notebookType); if (isExclusive(entry.selector) && entry._score > 0) { // support for one exclusive selector that overwrites diff --git a/src/vs/editor/common/services/languageFeatures.ts b/src/vs/editor/common/services/languageFeatures.ts index a814f5fe7d5..14bd7532635 100644 --- a/src/vs/editor/common/services/languageFeatures.ts +++ b/src/vs/editor/common/services/languageFeatures.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { LanguageFeatureRegistry, NotebookTypeResolver } from 'vs/editor/common/languageFeatureRegistry'; +import { LanguageFeatureRegistry, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry'; import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -69,5 +69,5 @@ export interface ILanguageFeaturesService { // -- - setNotebookTypeResolver(resolver: NotebookTypeResolver | undefined): void; + setNotebookTypeResolver(resolver: NotebookInfoResolver | undefined): void; } diff --git a/src/vs/editor/common/services/languageFeaturesService.ts b/src/vs/editor/common/services/languageFeaturesService.ts index 8eb6fe2e22b..92f57d892a7 100644 --- a/src/vs/editor/common/services/languageFeaturesService.ts +++ b/src/vs/editor/common/services/languageFeaturesService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { LanguageFeatureRegistry, NotebookTypeResolver } from 'vs/editor/common/languageFeatureRegistry'; +import { LanguageFeatureRegistry, NotebookInfo, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry'; import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -42,13 +42,13 @@ export class LanguageFeaturesService implements ILanguageFeaturesService { readonly documentSemanticTokensProvider = new LanguageFeatureRegistry(this._score.bind(this)); - private _notebookTypeResolver?: NotebookTypeResolver; + private _notebookTypeResolver?: NotebookInfoResolver; - setNotebookTypeResolver(resolver: NotebookTypeResolver | undefined) { + setNotebookTypeResolver(resolver: NotebookInfoResolver | undefined) { this._notebookTypeResolver = resolver; } - private _score(uri: URI): string | undefined { + private _score(uri: URI): NotebookInfo | undefined { return this._notebookTypeResolver?.(uri); } diff --git a/src/vs/editor/test/common/modes/languageSelector.test.ts b/src/vs/editor/test/common/modes/languageSelector.test.ts index b873efdcb16..e2d59071382 100644 --- a/src/vs/editor/test/common/modes/languageSelector.test.ts +++ b/src/vs/editor/test/common/modes/languageSelector.test.ts @@ -105,6 +105,7 @@ suite('LanguageSelector', function () { assert.strictEqual(score('javascript', obj.uri, obj.langId, true, undefined), 10); assert.strictEqual(score('javascript', obj.uri, obj.langId, true, obj.notebookType), 10); assert.strictEqual(score({ notebookType: 'fooBook' }, obj.uri, obj.langId, true, obj.notebookType), 10); + assert.strictEqual(score({ notebookType: 'fooBook', language: 'javascript', scheme: 'file' }, obj.uri, obj.langId, true, obj.notebookType), 10); assert.strictEqual(score({ notebookType: 'fooBook', language: '*' }, obj.uri, obj.langId, true, obj.notebookType), 10); assert.strictEqual(score({ notebookType: '*', language: '*' }, obj.uri, obj.langId, true, obj.notebookType), 5); assert.strictEqual(score({ notebookType: '*', language: 'javascript' }, obj.uri, obj.langId, true, obj.notebookType), 10); diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index b751908a22d..30fc905f22f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -103,6 +103,7 @@ import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/mode import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; +import { NotebookInfo } from 'vs/editor/common/languageFeatureRegistry'; /*--------------------------------------------------------------------------------------------- */ @@ -617,10 +618,10 @@ class NotebookLanguageSelectorScoreRefine { @INotebookService private readonly _notebookService: INotebookService, @ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService, ) { - languageFeaturesService.setNotebookTypeResolver(this._getNotebookType.bind(this)); + languageFeaturesService.setNotebookTypeResolver(this._getNotebookInfo.bind(this)); } - private _getNotebookType(uri: URI): string | undefined { + private _getNotebookInfo(uri: URI): NotebookInfo | undefined { const cellUri = CellUri.parse(uri); if (!cellUri) { return undefined; @@ -629,7 +630,10 @@ class NotebookLanguageSelectorScoreRefine { if (!notebook) { return undefined; } - return notebook.viewType; + return { + uri: notebook.uri, + type: notebook.viewType + }; } } diff --git a/src/vscode-dts/vscode.d.ts b/src/vscode-dts/vscode.d.ts index bc8381dc645..11fb02eb7df 100644 --- a/src/vscode-dts/vscode.d.ts +++ b/src/vscode-dts/vscode.d.ts @@ -2065,12 +2065,14 @@ declare module 'vscode' { readonly language?: string; /** - * The {@link NotebookDocument.notebookType type} of a notebook, like `jupyter`. This allows + * The {@link NotebookDocument.notebookType type} of a notebook, like `jupyter-notebook`. This allows * to narrow down on the type of a notebook that a {@link NotebookCell.document cell document} belongs to. * - * *Note* that combining `notebookType` and {@link DocumentFilter.scheme `scheme`} with a value - * different than `"vscode-notebook-cell"` or `undefined` is invalid and will not match - * any document. + * *Note* that setting the `notebookType`-property changes how `scheme` and `pattern` are interpreted. When set + * they are evaluated against the {@link NotebookDocument.uri notebook uri}, not the document uri. + * + * @example Match python document inside jupyter notebook that aren't stored yet + * { language: 'python', notebookType: 'jupyter-notebook', scheme: 'untitled' } */ readonly notebookType?: string; From 9fbc861fa41a977c51fbaa1d9395fac64cf96430 Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 15 Mar 2022 09:15:07 +0100 Subject: [PATCH 170/175] tiny tweak and API-todo --- src/vscode-dts/vscode.proposed.tabs.d.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vscode-dts/vscode.proposed.tabs.d.ts b/src/vscode-dts/vscode.proposed.tabs.d.ts index 1affd362f79..38c81fbe4a4 100644 --- a/src/vscode-dts/vscode.proposed.tabs.d.ts +++ b/src/vscode-dts/vscode.proposed.tabs.d.ts @@ -78,12 +78,14 @@ declare module 'vscode' { * @param index The index to move the tab to * @param viewColumn The column to move the tab into */ + // TODO@API move into TabGroups move(index: number, viewColumn: ViewColumn): Thenable; /** * Closes the tab. This makes the tab object invalid and the tab * should no longer be used for further actions. */ + // TODO@API move into TabGroups close(): Thenable; } @@ -94,7 +96,7 @@ declare module 'vscode' { export const tabGroups: TabGroups; } - interface TabGroups { + export interface TabGroups { /** * All the groups within the group container */ @@ -117,7 +119,7 @@ declare module 'vscode' { onDidChangeActiveTabGroup: Event; } - interface TabGroup { + export interface TabGroup { /** * Whether or not the group is currently active */ From e80e4e6fd20cf045dd6c77eb4790dce06f158736 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 15 Mar 2022 09:35:08 +0100 Subject: [PATCH 171/175] Fixes #144989 --- .../browser/abstractTextMateService.ts | 6 +++++- .../textMate/common/TMGrammarFactory.ts | 19 +++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/textMate/browser/abstractTextMateService.ts b/src/vs/workbench/services/textMate/browser/abstractTextMateService.ts index fd04e1fd157..57aa1cd2c21 100644 --- a/src/vs/workbench/services/textMate/browser/abstractTextMateService.ts +++ b/src/vs/workbench/services/textMate/browser/abstractTextMateService.ts @@ -26,7 +26,7 @@ import type { IGrammar, StackElement, IOnigLib, IRawTheme } from 'vscode-textmat import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IValidGrammarDefinition, IValidEmbeddedLanguagesMap, IValidTokenTypeMap } from 'vs/workbench/services/textMate/common/TMScopeRegistry'; -import { TMGrammarFactory } from 'vs/workbench/services/textMate/common/TMGrammarFactory'; +import { missingTMGrammarErrorMessage, TMGrammarFactory } from 'vs/workbench/services/textMate/common/TMGrammarFactory'; import { IExtensionResourceLoaderService } from 'vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { TMTokenization } from 'vs/workbench/services/textMate/common/TMTokenization'; @@ -266,6 +266,10 @@ export abstract class AbstractTextMateService extends Disposable implements ITex }); return new TMTokenizationSupportWithLineLimit(languageId, encodedLanguageId, tokenization, this._configurationService); } catch (err) { + if (err.message && err.message === missingTMGrammarErrorMessage) { + // Don't log this error message + return null; + } onUnexpectedError(err); return null; } diff --git a/src/vs/workbench/services/textMate/common/TMGrammarFactory.ts b/src/vs/workbench/services/textMate/common/TMGrammarFactory.ts index 5d5ae7a8c8e..2bb9be17ad0 100644 --- a/src/vs/workbench/services/textMate/common/TMGrammarFactory.ts +++ b/src/vs/workbench/services/textMate/common/TMGrammarFactory.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; import { URI } from 'vs/base/common/uri'; import type { IGrammar, Registry, StackElement, IRawTheme, IOnigLib } from 'vscode-textmate'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -22,6 +21,8 @@ export interface ICreateGrammarResult { containsEmbeddedLanguages: boolean; } +export const missingTMGrammarErrorMessage = 'No TM Grammar registered for this language.'; + export class TMGrammarFactory extends Disposable { private readonly _host: ITMGrammarFactoryHost; @@ -113,13 +114,13 @@ export class TMGrammarFactory extends Disposable { const scopeName = this._languageToScope.get(languageId); if (typeof scopeName !== 'string') { // No TM grammar defined - return Promise.reject(new Error(nls.localize('no-tm-grammar', "No TM Grammar registered for this language."))); + throw new Error(missingTMGrammarErrorMessage); } const grammarDefinition = this._scopeRegistry.getGrammarDefinition(scopeName); if (!grammarDefinition) { // No TM grammar defined - return Promise.reject(new Error(nls.localize('no-tm-grammar', "No TM Grammar registered for this language."))); + throw new Error(missingTMGrammarErrorMessage); } let embeddedLanguages = grammarDefinition.embeddedLanguages; @@ -134,7 +135,17 @@ export class TMGrammarFactory extends Disposable { const containsEmbeddedLanguages = (Object.keys(embeddedLanguages).length > 0); - const grammar = await this._grammarRegistry.loadGrammarWithConfiguration(scopeName, encodedLanguageId, { embeddedLanguages, tokenTypes: grammarDefinition.tokenTypes }); + let grammar: IGrammar | null; + + try { + grammar = await this._grammarRegistry.loadGrammarWithConfiguration(scopeName, encodedLanguageId, { embeddedLanguages, tokenTypes: grammarDefinition.tokenTypes }); + } catch (err) { + if (err.message && err.message.startsWith('No grammar provided for')) { + // No TM grammar defined + throw new Error(missingTMGrammarErrorMessage); + } + throw err; + } return { languageId: languageId, From 57f776891738fbc70388baf541afcbba1c1bdc8c Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 15 Mar 2022 11:04:48 +0100 Subject: [PATCH 172/175] Update Swift grammar --- .../swift/syntaxes/swift.tmLanguage.json | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/extensions/swift/syntaxes/swift.tmLanguage.json b/extensions/swift/syntaxes/swift.tmLanguage.json index be1b132172e..f63b127dc62 100644 --- a/extensions/swift/syntaxes/swift.tmLanguage.json +++ b/extensions/swift/syntaxes/swift.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/textmate/swift.tmbundle/commit/8c7672d74c1baa4e6944a05ac6c57a623532f18b", + "version": "https://github.com/textmate/swift.tmbundle/commit/7a35637eb70aef3114b091c4ff6fbf6a2faa881b", "name": "Swift", "scopeName": "source.swift", "comment": "See swift.tmbundle/grammar-test.swift for test cases.", @@ -109,7 +109,7 @@ "name": "invalid.illegal.character-not-allowed-here.swift" } }, - "match": "(?:(\\*)|\\b(deprecated|unavailable)\\b)\\s*(.*?)(?=[,)])" + "match": "(?:(\\*)|\\b(deprecated|unavailable|noasync)\\b)\\s*(.*?)(?=[,)])" } ] }, @@ -818,7 +818,11 @@ "name": "keyword.operator.type.opaque.swift" }, { - "match": "\\binout\\b", + "match": "\\bany\\b", + "name": "keyword.operator.type.existential.swift" + }, + { + "match": "\\b(?:inout|isolated)\\b", "name": "storage.modifier.swift" }, { @@ -986,19 +990,22 @@ ] }, "function": { - "begin": "(?x)\n\t\t\t\t\t\t\\b\n\t\t\t\t\t\t(func)\n\t\t\t\t\t\t\\s+\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t(?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*(\\k)\n\t\t\t\t\t\t | (?:\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t(?\t\t\t\t\t\t\t\t# operator-head\n\t\t\t\t\t\t\t\t\t\t[/=\\-+!*%<>&|^~?]\n\t\t\t\t\t\t\t\t\t | [\\x{00A1}-\\x{00A7}]\n\t\t\t\t\t\t\t\t\t | [\\x{00A9}\\x{00AB}]\n\t\t\t\t\t\t\t\t\t | [\\x{00AC}\\x{00AE}]\n\t\t\t\t\t\t\t\t\t | [\\x{00B0}-\\x{00B1}\\x{00B6}\\x{00BB}\\x{00BF}\\x{00D7}\\x{00F7}]\n\t\t\t\t\t\t\t\t\t | [\\x{2016}-\\x{2017}\\x{2020}-\\x{2027}]\n\t\t\t\t\t\t\t\t\t | [\\x{2030}-\\x{203E}]\n\t\t\t\t\t\t\t\t\t | [\\x{2041}-\\x{2053}]\n\t\t\t\t\t\t\t\t\t | [\\x{2055}-\\x{205E}]\n\t\t\t\t\t\t\t\t\t | [\\x{2190}-\\x{23FF}]\n\t\t\t\t\t\t\t\t\t | [\\x{2500}-\\x{2775}]\n\t\t\t\t\t\t\t\t\t | [\\x{2794}-\\x{2BFF}]\n\t\t\t\t\t\t\t\t\t | [\\x{2E00}-\\x{2E7F}]\n\t\t\t\t\t\t\t\t\t | [\\x{3001}-\\x{3003}]\n\t\t\t\t\t\t\t\t\t | [\\x{3008}-\\x{3030}]\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\\g\n\t\t\t\t\t\t\t\t\t | (?\t\t\t\t\t\t\t\t# operator-character\n\t\t\t\t\t\t\t\t\t\t\t[\\x{0300}-\\x{036F}]\n\t\t\t\t\t\t\t\t\t\t | [\\x{1DC0}-\\x{1DFF}]\n\t\t\t\t\t\t\t\t\t\t | [\\x{20D0}-\\x{20FF}]\n\t\t\t\t\t\t\t\t\t\t | [\\x{FE00}-\\x{FE0F}]\n\t\t\t\t\t\t\t\t\t\t | [\\x{FE20}-\\x{FE2F}]\n\t\t\t\t\t\t\t\t\t\t | [\\x{E0100}-\\x{E01EF}]\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t)*\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t | ( \\. ( \\g | \\g | \\. )+ )\t\t\t# Dot operators\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\\s*\n\t\t\t\t\t\t(?=\\(|<)\n\t\t\t\t\t", + "begin": "(?x)\n\t\t\t\t\t\t\\b\n\t\t\t\t\t\t(?:(nonisolated)\\s+)?\n\t\t\t\t\t\t(func)\n\t\t\t\t\t\t\\s+\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t(?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*(\\k)\n\t\t\t\t\t\t | (?:\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t(?\t\t\t\t\t\t\t\t# operator-head\n\t\t\t\t\t\t\t\t\t\t[/=\\-+!*%<>&|^~?]\n\t\t\t\t\t\t\t\t\t | [\\x{00A1}-\\x{00A7}]\n\t\t\t\t\t\t\t\t\t | [\\x{00A9}\\x{00AB}]\n\t\t\t\t\t\t\t\t\t | [\\x{00AC}\\x{00AE}]\n\t\t\t\t\t\t\t\t\t | [\\x{00B0}-\\x{00B1}\\x{00B6}\\x{00BB}\\x{00BF}\\x{00D7}\\x{00F7}]\n\t\t\t\t\t\t\t\t\t | [\\x{2016}-\\x{2017}\\x{2020}-\\x{2027}]\n\t\t\t\t\t\t\t\t\t | [\\x{2030}-\\x{203E}]\n\t\t\t\t\t\t\t\t\t | [\\x{2041}-\\x{2053}]\n\t\t\t\t\t\t\t\t\t | [\\x{2055}-\\x{205E}]\n\t\t\t\t\t\t\t\t\t | [\\x{2190}-\\x{23FF}]\n\t\t\t\t\t\t\t\t\t | [\\x{2500}-\\x{2775}]\n\t\t\t\t\t\t\t\t\t | [\\x{2794}-\\x{2BFF}]\n\t\t\t\t\t\t\t\t\t | [\\x{2E00}-\\x{2E7F}]\n\t\t\t\t\t\t\t\t\t | [\\x{3001}-\\x{3003}]\n\t\t\t\t\t\t\t\t\t | [\\x{3008}-\\x{3030}]\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\\g\n\t\t\t\t\t\t\t\t\t | (?\t\t\t\t\t\t\t\t# operator-character\n\t\t\t\t\t\t\t\t\t\t\t[\\x{0300}-\\x{036F}]\n\t\t\t\t\t\t\t\t\t\t | [\\x{1DC0}-\\x{1DFF}]\n\t\t\t\t\t\t\t\t\t\t | [\\x{20D0}-\\x{20FF}]\n\t\t\t\t\t\t\t\t\t\t | [\\x{FE00}-\\x{FE0F}]\n\t\t\t\t\t\t\t\t\t\t | [\\x{FE20}-\\x{FE2F}]\n\t\t\t\t\t\t\t\t\t\t | [\\x{E0100}-\\x{E01EF}]\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t)*\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t | ( \\. ( \\g | \\g | \\. )+ )\t\t\t# Dot operators\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\\s*\n\t\t\t\t\t\t(?=\\(|<)\n\t\t\t\t\t", "beginCaptures": { "1": { - "name": "storage.type.function.swift" + "name": "storage.modifier.swift" }, "2": { - "name": "entity.name.function.swift" + "name": "storage.type.function.swift" }, "3": { - "name": "punctuation.definition.identifier.swift" + "name": "entity.name.function.swift" }, "4": { "name": "punctuation.definition.identifier.swift" + }, + "5": { + "name": "punctuation.definition.identifier.swift" } }, "end": "(?<=\\})|$(?# functions in protocol declarations or generated interfaces have no body)", @@ -2253,9 +2260,12 @@ ] }, "typed-variable-declaration": { - "begin": "(?x)\n\t\t\t\t\t\t\\b(let|var)\\b\\s+\n\t\t\t\t\t\t(?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*(\\k)\\s*\n\t\t\t\t\t\t:\n\t\t\t\t\t", + "begin": "(?x)\n\t\t\t\t\t\t\\b(?:(async)\\s+)?(let|var)\\b\\s+\n\t\t\t\t\t\t(?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*(\\k)\\s*\n\t\t\t\t\t\t:\n\t\t\t\t\t", "beginCaptures": { "1": { + "name": "keyword.control.async.swift" + }, + "2": { "name": "keyword.other.declaration-specifier.swift" } }, @@ -2641,7 +2651,21 @@ "match": "(? Date: Tue, 15 Mar 2022 11:35:23 +0100 Subject: [PATCH 173/175] Configure server using env vars. Fixes #141333 --- scripts/code-server.js | 70 +++++++++++++++++------------------------- src/server-main.js | 8 +++++ 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/scripts/code-server.js b/scripts/code-server.js index f4d34131cb3..8f2c630fc1f 100644 --- a/scripts/code-server.js +++ b/scripts/code-server.js @@ -8,23 +8,15 @@ const cp = require('child_process'); const path = require('path'); const opn = require('opn'); -const crypto = require('crypto'); const minimist = require('minimist'); -function main() { +async function main() { const args = minimist(process.argv.slice(2), { boolean: [ 'help', 'launch' - ], - string: [ - 'host', - 'port', - 'driver', - 'connection-token', - 'server-data-dir' - ], + ] }); if (args.help) { @@ -36,46 +28,42 @@ function main() { return; } + process.env['VSCODE_SERVER_PORT'] = '9888'; + const serverArgs = process.argv.slice(2).filter(v => v !== '--launch'); - - const HOST = args['host'] ?? 'localhost'; - const PORT = args['port'] ?? '9888'; - const TOKEN = args['connection-token'] ?? String(crypto.randomInt(0xffffffff)); - - if (args['connection-token'] === undefined && args['connection-token-file'] === undefined && !args['without-connection-token']) { - serverArgs.push('--connection-token', TOKEN); - } - if (args['host'] === undefined) { - serverArgs.push('--host', HOST); - } - if (args['port'] === undefined) { - serverArgs.push('--port', PORT); - } - - startServer(serverArgs); + const addr = await startServer(serverArgs); if (args['launch']) { - opn(`http://${HOST}:${PORT}/?tkn=${TOKEN}`); + opn(addr); } } function startServer(programArgs) { - const env = { ...process.env }; + return new Promise((s, e) => { + const env = { ...process.env }; + const entryPoint = path.join(__dirname, '..', 'out', 'server-main.js'); - const entryPoint = path.join(__dirname, '..', 'out', 'server-main.js'); + console.log(`Starting server: ${entryPoint} ${programArgs.join(' ')}`); + const proc = cp.spawn(process.execPath, [entryPoint, ...programArgs], { env, stdio: [process.stdin, null, process.stderr] }); + proc.stdout.on('data', e => { + const data = e.toString(); + console.log(data); + const m = data.match(/Web UI available at (.*)/); + if (m) { + s(m[1]); + } + }); - console.log(`Starting server: ${entryPoint} ${programArgs.join(' ')}`); - const proc = cp.spawn(process.execPath, [entryPoint, ...programArgs], { env, stdio: 'inherit' }); + proc.on('exit', (code) => process.exit(code)); - proc.on('exit', (code) => process.exit(code)); - - process.on('exit', () => proc.kill()); - process.on('SIGINT', () => { - proc.kill(); - process.exit(128 + 2); // https://nodejs.org/docs/v14.16.0/api/process.html#process_signal_events - }); - process.on('SIGTERM', () => { - proc.kill(); - process.exit(128 + 15); // https://nodejs.org/docs/v14.16.0/api/process.html#process_signal_events + process.on('exit', () => proc.kill()); + process.on('SIGINT', () => { + proc.kill(); + process.exit(128 + 2); // https://nodejs.org/docs/v14.16.0/api/process.html#process_signal_events + }); + process.on('SIGTERM', () => { + proc.kill(); + process.exit(128 + 15); // https://nodejs.org/docs/v14.16.0/api/process.html#process_signal_events + }); }); } diff --git a/src/server-main.js b/src/server-main.js index 79f4d4d0112..d8e5fdd45dd 100644 --- a/src/server-main.js +++ b/src/server-main.js @@ -24,6 +24,14 @@ async function start() { string: ['install-extension', 'install-builtin-extension', 'uninstall-extension', 'locate-extension', 'socket-path', 'host', 'port', 'pick-port', 'compatibility'], alias: { help: 'h', version: 'v' } }); + ['host', 'port', 'accept-server-license-terms'].forEach(e => { + if (!parsedArgs[e]) { + const envValue = process.env[`VSCODE_SERVER_${e.toUpperCase().replace('-', '_')}`]; + if (envValue) { + parsedArgs[e] = envValue; + } + } + }); const extensionLookupArgs = ['list-extensions', 'locate-extension']; const extensionInstallArgs = ['install-extension', 'install-builtin-extension', 'uninstall-extension']; From 724657e4e36887345d75b41ceab9293cf4aa7c9b Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 15 Mar 2022 11:48:46 +0100 Subject: [PATCH 174/175] Fix executeTask for new'd tasks Fixes #145065 --- .../workbench/contrib/tasks/browser/abstractTaskService.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 62b66ab4749..70c269e4a69 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -1700,7 +1700,10 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer const taskFolder = task.getWorkspaceFolder(); const taskIdentifier = task.configurationProperties.identifier; // Since we save before running tasks, the task may have changed as part of the save. - taskToRun = ((taskFolder && taskIdentifier) ? await this.getTask(taskFolder, taskIdentifier) : task) ?? task; + // However, if the TaskRunSource is not User, then we shouldn't try to fetch the task again + // since this can cause a new'd task to get overwritten with a provided task. + taskToRun = ((taskFolder && taskIdentifier && (runSource === TaskRunSource.User)) + ? await this.getTask(taskFolder, taskIdentifier) : task) ?? task; } await ProblemMatcherRegistry.onReady(); let executeResult = this.getTaskSystem().run(taskToRun, resolver); From 3470f052760c1a6ee6cbba36acdeaedc59d72690 Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 15 Mar 2022 12:58:33 +0100 Subject: [PATCH 175/175] some more tab todos --- src/vscode-dts/vscode.proposed.tabs.d.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vscode-dts/vscode.proposed.tabs.d.ts b/src/vscode-dts/vscode.proposed.tabs.d.ts index 38c81fbe4a4..b8f8893b4b3 100644 --- a/src/vscode-dts/vscode.proposed.tabs.d.ts +++ b/src/vscode-dts/vscode.proposed.tabs.d.ts @@ -25,6 +25,7 @@ declare module 'vscode' { /** * The column which the tab belongs to */ + // TODO@API point to TabGroup instead? readonly viewColumn: ViewColumn; /** @@ -85,7 +86,8 @@ declare module 'vscode' { * Closes the tab. This makes the tab object invalid and the tab * should no longer be used for further actions. */ - // TODO@API move into TabGroups + // TODO@API move into TabGroups, support one or many tabs or tab groups + // TODO@API add `preserveFocus` close(): Thenable; }